summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:20:44 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:20:44 +0900
commit99a800848c2512f7c93504fc7b28e6182a6ceb93 (patch)
tree0236502664965e5284d0c950ed2c1bf294b1233b
parentdf4ed7977a77409f899f6f05389960f6b73125a8 (diff)
downloadcmake-99a800848c2512f7c93504fc7b28e6182a6ceb93.tar.gz
cmake-99a800848c2512f7c93504fc7b28e6182a6ceb93.tar.bz2
cmake-99a800848c2512f7c93504fc7b28e6182a6ceb93.zip
Imported Upstream version 3.20.0upstream/3.20.0
-rw-r--r--.clang-tidy11
-rw-r--r--Auxiliary/cmake-mode.el106
-rwxr-xr-xAuxiliary/vim/extract-upper-case.pl24
-rw-r--r--Auxiliary/vim/syntax/cmake.vim753
-rw-r--r--CMakeLists.txt2
-rw-r--r--Copyright.txt4
-rw-r--r--Help/command/DEVICE_LINK_OPTIONS.txt21
-rw-r--r--Help/command/FIND_XXX.txt42
-rw-r--r--Help/command/OPTIONS_SHELL.txt14
-rw-r--r--Help/command/add_custom_command.rst164
-rw-r--r--Help/command/add_custom_target.rst47
-rw-r--r--Help/command/add_dependencies.rst3
-rw-r--r--Help/command/add_executable.rst30
-rw-r--r--Help/command/add_library.rst70
-rw-r--r--Help/command/add_test.rst7
-rw-r--r--Help/command/cmake_host_system_information.rst8
-rw-r--r--Help/command/cmake_minimum_required.rst3
-rw-r--r--Help/command/cmake_parse_arguments.rst38
-rw-r--r--Help/command/cmake_path.rst784
-rw-r--r--Help/command/cmake_policy.rst3
-rw-r--r--Help/command/configure_file.rst37
-rw-r--r--Help/command/ctest_build.rst9
-rw-r--r--Help/command/ctest_configure.rst4
-rw-r--r--Help/command/ctest_coverage.rst4
-rw-r--r--Help/command/ctest_memcheck.rst2
-rw-r--r--Help/command/ctest_start.rst9
-rw-r--r--Help/command/ctest_submit.rst32
-rw-r--r--Help/command/ctest_test.rst18
-rw-r--r--Help/command/ctest_update.rst4
-rw-r--r--Help/command/ctest_upload.rst4
-rw-r--r--Help/command/enable_language.rst9
-rw-r--r--Help/command/execute_process.rst25
-rw-r--r--Help/command/export.rst17
-rw-r--r--Help/command/file.rst183
-rw-r--r--Help/command/find_package.rst23
-rw-r--r--Help/command/foreach.rst2
-rw-r--r--Help/command/function.rst5
-rw-r--r--Help/command/get_directory_property.rst6
-rw-r--r--Help/command/get_filename_component.rst16
-rw-r--r--Help/command/get_property.rst41
-rw-r--r--Help/command/get_source_file_property.rst29
-rw-r--r--Help/command/if.rst173
-rw-r--r--Help/command/include_external_msproject.rst7
-rw-r--r--Help/command/install.rst110
-rw-r--r--Help/command/link_directories.rst30
-rw-r--r--Help/command/list.rst21
-rw-r--r--Help/command/macro.rst5
-rw-r--r--Help/command/mark_as_advanced.rst8
-rw-r--r--Help/command/math.rst23
-rw-r--r--Help/command/message.rst47
-rw-r--r--Help/command/project.rst29
-rw-r--r--Help/command/separate_arguments.rst4
-rw-r--r--Help/command/set_property.rst46
-rw-r--r--Help/command/set_source_files_properties.rst12
-rw-r--r--Help/command/site_name.rst4
-rw-r--r--Help/command/source_group.rst7
-rw-r--r--Help/command/string.rst58
-rw-r--r--Help/command/target_compile_definitions.rst13
-rw-r--r--Help/command/target_compile_features.rst4
-rw-r--r--Help/command/target_compile_options.rst4
-rw-r--r--Help/command/target_include_directories.rst10
-rw-r--r--Help/command/target_link_libraries.rst20
-rw-r--r--Help/command/target_link_options.rst4
-rw-r--r--Help/command/target_precompile_headers.rst4
-rw-r--r--Help/command/target_sources.rst30
-rw-r--r--Help/command/try_compile.rst120
-rw-r--r--Help/command/try_run.rst20
-rw-r--r--Help/cpack_gen/archive.rst13
-rw-r--r--Help/cpack_gen/bundle.rst10
-rw-r--r--Help/cpack_gen/cygwin.rst4
-rw-r--r--Help/cpack_gen/deb.rst135
-rw-r--r--Help/cpack_gen/dmg.rst13
-rw-r--r--Help/cpack_gen/external.rst4
-rw-r--r--Help/cpack_gen/freebsd.rst8
-rw-r--r--Help/cpack_gen/ifw.rst82
-rw-r--r--Help/cpack_gen/nsis.rst36
-rw-r--r--Help/cpack_gen/nuget.rst78
-rw-r--r--Help/cpack_gen/packagemaker.rst8
-rw-r--r--Help/cpack_gen/productbuild.rst20
-rw-r--r--Help/cpack_gen/rpm.rst86
-rw-r--r--Help/cpack_gen/wix.rst40
-rw-r--r--Help/dev/README.rst2
-rw-r--r--Help/dev/documentation.rst30
-rw-r--r--Help/dev/experimental.rst70
-rw-r--r--Help/dev/maint.rst10
-rw-r--r--Help/envvar/CUDAARCHS.rst13
-rw-r--r--Help/envvar/CUDAHOSTCXX.rst7
-rw-r--r--Help/generator/CodeBlocks.rst11
-rw-r--r--Help/generator/CodeLite.rst8
-rw-r--r--Help/generator/Green Hills MULTI.rst43
-rw-r--r--Help/generator/NMake Makefiles JOM.rst3
-rw-r--r--Help/generator/Ninja Multi-Config.rst75
-rw-r--r--Help/generator/Ninja.rst45
-rw-r--r--Help/generator/VS_TOOLSET_HOST_ARCH.txt18
-rw-r--r--Help/generator/Visual Studio 10 2010.rst15
-rw-r--r--Help/generator/Visual Studio 11 2012.rst19
-rw-r--r--Help/generator/Visual Studio 12 2013.rst15
-rw-r--r--Help/generator/Visual Studio 14 2015.rst2
-rw-r--r--Help/generator/Visual Studio 15 2017.rst26
-rw-r--r--Help/generator/Visual Studio 9 2008.rst19
-rw-r--r--Help/generator/Xcode.rst15
-rw-r--r--Help/guide/ide-integration/index.rst4
-rw-r--r--Help/guide/importing-exporting/MathFunctions/CMakeLists.txt6
-rw-r--r--Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt2
-rw-r--r--Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt4
-rw-r--r--Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt2
-rw-r--r--Help/guide/tutorial/index.rst69
-rw-r--r--Help/guide/user-interaction/index.rst2
-rw-r--r--Help/manual/cmake-commands.7.rst1
-rw-r--r--Help/manual/cmake-compile-features.7.rst4
-rw-r--r--Help/manual/cmake-developer.7.rst136
-rw-r--r--Help/manual/cmake-env-variables.7.rst1
-rw-r--r--Help/manual/cmake-file-api.7.rst157
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst399
-rw-r--r--Help/manual/cmake-modules.7.rst10
-rw-r--r--Help/manual/cmake-policies.7.rst13
-rw-r--r--Help/manual/cmake-presets.7.rst952
-rw-r--r--Help/manual/cmake-properties.7.rst6
-rw-r--r--Help/manual/cmake-qt.7.rst7
-rw-r--r--Help/manual/cmake-server.7.rst741
-rw-r--r--Help/manual/cmake-toolchains.7.rst8
-rw-r--r--Help/manual/cmake-variables.7.rst6
-rw-r--r--Help/manual/cmake.1.rst25
-rw-r--r--Help/manual/ctest.1.rst15
-rw-r--r--Help/manual/presets/example.json18
-rw-r--r--Help/manual/presets/schema.json485
-rw-r--r--Help/module/UseJavaClassFilelist.rst7
-rw-r--r--Help/module/UseJavaSymlinks.rst7
-rw-r--r--Help/policy/CMP0026.rst4
-rw-r--r--Help/policy/CMP0051.rst2
-rw-r--r--Help/policy/CMP0115.rst34
-rw-r--r--Help/policy/CMP0116.rst41
-rw-r--r--Help/policy/CMP0117.rst43
-rw-r--r--Help/policy/CMP0118.rst25
-rw-r--r--Help/policy/CMP0119.rst36
-rw-r--r--Help/policy/CMP0120.rst47
-rw-r--r--Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst3
-rw-r--r--Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst2
-rw-r--r--Help/prop_sf/GENERATED.rst11
-rw-r--r--Help/prop_sf/LANGUAGE.rst8
-rw-r--r--Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY.rst2
-rw-r--r--Help/prop_tgt/AUTOMOC.rst3
-rw-r--r--Help/prop_tgt/CUDA_STANDARD.rst2
-rw-r--r--Help/prop_tgt/CXX_STANDARD.rst2
-rw-r--r--Help/prop_tgt/EXPORT_COMPILE_COMMANDS.rst9
-rw-r--r--Help/prop_tgt/IMPORTED_OBJECTS.rst86
-rw-r--r--Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst13
-rw-r--r--Help/prop_tgt/INSTALL_NAME_DIR.rst4
-rw-r--r--Help/prop_tgt/LANG_CLANG_TIDY.rst2
-rw-r--r--Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY.rst2
-rw-r--r--Help/prop_tgt/OBJCXX_STANDARD.rst2
-rw-r--r--Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.rst2
-rw-r--r--Help/prop_tgt/UNITY_BUILD.rst5
-rw-r--r--Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst55
-rw-r--r--Help/prop_tgt/XCODE_ATTRIBUTE_an-attribute.rst8
-rw-r--r--Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst8
-rw-r--r--Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst8
-rw-r--r--Help/prop_tgt/XCODE_EMBED_type.rst14
-rw-r--r--Help/prop_tgt/XCODE_EMBED_type_PATH.rst9
-rw-r--r--Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt11
-rw-r--r--Help/release/3.20.rst329
-rw-r--r--Help/release/index.rst1
-rw-r--r--Help/variable/CMAKE_ANDROID_EXCEPTIONS.rst7
-rw-r--r--Help/variable/CMAKE_ANDROID_NDK_VERSION.rst8
-rw-r--r--Help/variable/CMAKE_ANDROID_RTTI.rst7
-rw-r--r--Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst5
-rw-r--r--Help/variable/CMAKE_BUILD_TYPE.rst5
-rw-r--r--Help/variable/CMAKE_CUDA_ARCHITECTURES.rst18
-rw-r--r--Help/variable/CMAKE_DEPENDS_USE_COMPILER.rst9
-rw-r--r--Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst3
-rw-r--r--Help/variable/CMAKE_LANG_BYTE_ORDER.rst20
-rw-r--r--Help/variable/CMAKE_LANG_CLANG_TIDY.rst2
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER_ID.rst2
-rw-r--r--Help/variable/CMAKE_LINK_SEARCH_END_STATIC.rst2
-rw-r--r--Help/variable/CMAKE_LINK_SEARCH_START_STATIC.rst2
-rw-r--r--Help/variable/CMAKE_NO_BUILTIN_CHRPATH.rst19
-rw-r--r--Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst2
-rw-r--r--Help/variable/CMAKE_POSITION_INDEPENDENT_CODE.rst2
-rw-r--r--Help/variable/CMAKE_SYSTEM_PROCESSOR.rst13
-rw-r--r--Help/variable/CMAKE_UNITY_BUILD_UNIQUE_ID.rst8
-rw-r--r--Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst10
-rw-r--r--Help/variable/CTEST_MEMORYCHECK_SANITIZER_OPTIONS.rst5
-rw-r--r--Help/variable/MSVC.rst5
-rw-r--r--Help/variable/MSVC_IDE.rst7
-rw-r--r--Modules/AddFileDependencies.cmake27
-rw-r--r--Modules/BundleUtilities.cmake28
-rw-r--r--Modules/CMakeCCompiler.cmake.in1
-rw-r--r--Modules/CMakeCCompilerABI.c2
-rw-r--r--Modules/CMakeCUDACompiler.cmake.in2
-rw-r--r--Modules/CMakeCUDACompilerABI.cu2
-rw-r--r--Modules/CMakeCUDACompilerId.cu.in4
-rw-r--r--Modules/CMakeCUDAInformation.cmake15
-rw-r--r--Modules/CMakeCXXCompiler.cmake.in4
-rw-r--r--Modules/CMakeCXXCompilerABI.cpp2
-rw-r--r--Modules/CMakeCXXCompilerId.cpp.in4
-rw-r--r--Modules/CMakeCompilerABI.h12
-rw-r--r--Modules/CMakeCompilerIdDetection.cmake2
-rw-r--r--Modules/CMakeDetermineASMCompiler.cmake4
-rw-r--r--Modules/CMakeDetermineCCompiler.cmake10
-rw-r--r--Modules/CMakeDetermineCUDACompiler.cmake34
-rw-r--r--Modules/CMakeDetermineCXXCompiler.cmake8
-rw-r--r--Modules/CMakeDetermineCompileFeatures.cmake14
-rw-r--r--Modules/CMakeDetermineCompilerABI.cmake48
-rw-r--r--Modules/CMakeDetermineCompilerId.cmake80
-rw-r--r--Modules/CMakeDetermineFortranCompiler.cmake8
-rw-r--r--Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake4
-rw-r--r--Modules/CMakeFindBinUtils.cmake96
-rw-r--r--Modules/CMakeFortranCompilerId.F.in33
-rw-r--r--Modules/CMakeGraphVizOptions.cmake5
-rw-r--r--Modules/CMakeOBJCCompiler.cmake.in1
-rw-r--r--Modules/CMakeOBJCCompilerABI.m2
-rw-r--r--Modules/CMakeOBJCXXCompiler.cmake.in2
-rw-r--r--Modules/CMakeOBJCXXCompilerABI.mm2
-rw-r--r--Modules/CMakeOBJCXXCompilerId.mm.in4
-rw-r--r--Modules/CMakePackageConfigHelpers.cmake50
-rw-r--r--Modules/CMakeParseLibraryArchitecture.cmake56
-rw-r--r--Modules/CMakePlatformId.h.in6
-rw-r--r--Modules/CMakeTestGNU.c3
-rw-r--r--Modules/CPack.cmake35
-rw-r--r--Modules/CPackIFW.cmake84
-rw-r--r--Modules/CTest.cmake34
-rw-r--r--Modules/CTestCoverageCollectGCOV.cmake13
-rw-r--r--Modules/CTestUseLaunchers.cmake9
-rw-r--r--Modules/CheckCSourceCompiles.cmake4
-rw-r--r--Modules/CheckCSourceRuns.cmake4
-rw-r--r--Modules/CheckCXXSourceCompiles.cmake4
-rw-r--r--Modules/CheckCXXSourceRuns.cmake4
-rw-r--r--Modules/CheckCXXSymbolExists.cmake6
-rw-r--r--Modules/CheckFortranFunctionExists.cmake5
-rw-r--r--Modules/CheckFortranSourceCompiles.cmake2
-rw-r--r--Modules/CheckFunctionExists.cmake6
-rw-r--r--Modules/CheckIPOSupported.cmake3
-rw-r--r--Modules/CheckIncludeFile.cmake6
-rw-r--r--Modules/CheckIncludeFileCXX.cmake6
-rw-r--r--Modules/CheckIncludeFiles.cmake6
-rw-r--r--Modules/CheckLanguage.cmake6
-rw-r--r--Modules/CheckLibraryExists.cmake19
-rw-r--r--Modules/CheckPrototypeDefinition.cmake22
-rw-r--r--Modules/CheckStructHasMember.cmake23
-rw-r--r--Modules/CheckSymbolExists.cmake6
-rw-r--r--Modules/CheckTypeSize.cmake26
-rw-r--r--Modules/CheckVariableExists.cmake19
-rw-r--r--Modules/Compiler/ARMCC.cmake2
-rw-r--r--Modules/Compiler/AppleClang-C.cmake13
-rw-r--r--Modules/Compiler/AppleClang-CXX.cmake10
-rw-r--r--Modules/Compiler/AppleClang-OBJC.cmake9
-rw-r--r--Modules/Compiler/AppleClang-OBJCXX.cmake10
-rw-r--r--Modules/Compiler/CMakeCommonCompilerMacros.cmake34
-rw-r--r--Modules/Compiler/Clang-C.cmake15
-rw-r--r--Modules/Compiler/Clang-CUDA.cmake8
-rw-r--r--Modules/Compiler/Clang-CXX.cmake14
-rw-r--r--Modules/Compiler/Clang-FindBinUtils.cmake8
-rw-r--r--Modules/Compiler/Clang-OBJC.cmake9
-rw-r--r--Modules/Compiler/Clang-OBJCXX.cmake8
-rw-r--r--Modules/Compiler/Clang.cmake16
-rw-r--r--Modules/Compiler/Cray-Fortran.cmake4
-rw-r--r--Modules/Compiler/GNU-ASM.cmake2
-rw-r--r--Modules/Compiler/GNU-C.cmake11
-rw-r--r--Modules/Compiler/GNU-CXX.cmake11
-rw-r--r--Modules/Compiler/GNU-OBJC.cmake9
-rw-r--r--Modules/Compiler/GNU-OBJCXX.cmake9
-rw-r--r--Modules/Compiler/GNU.cmake2
-rw-r--r--Modules/Compiler/IAR-ASM.cmake5
-rw-r--r--Modules/Compiler/IAR-C.cmake4
-rw-r--r--Modules/Compiler/IAR-CXX.cmake4
-rw-r--r--Modules/Compiler/IAR-DetermineCompiler.cmake2
-rw-r--r--Modules/Compiler/IAR-FindBinUtils.cmake3
-rw-r--r--Modules/Compiler/IAR.cmake4
-rw-r--r--Modules/Compiler/Intel-C.cmake11
-rw-r--r--Modules/Compiler/Intel-CXX.cmake10
-rw-r--r--Modules/Compiler/Intel-ISPC.cmake8
-rw-r--r--Modules/Compiler/IntelLLVM-ASM.cmake12
-rw-r--r--Modules/Compiler/IntelLLVM-C.cmake58
-rw-r--r--Modules/Compiler/IntelLLVM-CXX.cmake69
-rw-r--r--Modules/Compiler/IntelLLVM-DetermineCompiler.cmake41
-rw-r--r--Modules/Compiler/IntelLLVM-Fortran.cmake27
-rw-r--r--Modules/Compiler/IntelLLVM.cmake92
-rw-r--r--Modules/Compiler/MSVC-C.cmake1
-rw-r--r--Modules/Compiler/NAG-Fortran.cmake1
-rw-r--r--Modules/Compiler/NVHPC-C.cmake3
-rw-r--r--Modules/Compiler/NVHPC-CXX.cmake3
-rw-r--r--Modules/Compiler/NVHPC-DetermineCompiler.cmake9
-rw-r--r--Modules/Compiler/NVHPC-Fortran.cmake3
-rw-r--r--Modules/Compiler/NVHPC.cmake15
-rw-r--r--Modules/Compiler/NVIDIA-CUDA.cmake9
-rw-r--r--Modules/Compiler/PGI-CXX.cmake3
-rw-r--r--Modules/Compiler/QCC.cmake2
-rw-r--r--Modules/Compiler/SunPro-C.cmake2
-rw-r--r--Modules/Compiler/SunPro-CXX.cmake2
-rw-r--r--Modules/Compiler/TI.cmake2
-rw-r--r--Modules/Compiler/XL.cmake2
-rw-r--r--Modules/Compiler/XLClang-C.cmake2
-rw-r--r--Modules/Compiler/XLClang-CXX.cmake2
-rw-r--r--Modules/DartConfiguration.tcl.in4
-rw-r--r--Modules/Documentation.cmake3
-rw-r--r--Modules/ExternalData.cmake68
-rw-r--r--Modules/ExternalProject-gitupdate.cmake.in405
-rw-r--r--Modules/ExternalProject.cmake459
-rw-r--r--Modules/FeatureSummary.cmake26
-rw-r--r--Modules/FetchContent.cmake23
-rw-r--r--Modules/FetchContent/CMakeLists.cmake.in2
-rw-r--r--Modules/FindALSA.cmake2
-rw-r--r--Modules/FindArmadillo.cmake3
-rw-r--r--Modules/FindBISON.cmake16
-rw-r--r--Modules/FindBLAS.cmake75
-rw-r--r--Modules/FindBZip2.cmake5
-rw-r--r--Modules/FindBoost.cmake440
-rw-r--r--Modules/FindCUDA.cmake829
-rw-r--r--Modules/FindCUDA/select_compute_arch.cmake89
-rw-r--r--Modules/FindCUDAToolkit.cmake26
-rw-r--r--Modules/FindCURL.cmake14
-rw-r--r--Modules/FindCups.cmake2
-rw-r--r--Modules/FindCurses.cmake8
-rw-r--r--Modules/FindDoxygen.cmake79
-rw-r--r--Modules/FindEXPAT.cmake2
-rw-r--r--Modules/FindFLEX.cmake19
-rw-r--r--Modules/FindFLTK.cmake4
-rw-r--r--Modules/FindFreetype.cmake7
-rw-r--r--Modules/FindGDAL.cmake64
-rw-r--r--Modules/FindGLEW.cmake5
-rw-r--r--Modules/FindGLUT.cmake5
-rw-r--r--Modules/FindGTK2.cmake25
-rw-r--r--Modules/FindGTest.cmake102
-rw-r--r--Modules/FindGettext.cmake2
-rw-r--r--Modules/FindGit.cmake58
-rw-r--r--Modules/FindGnuTLS.cmake2
-rw-r--r--Modules/FindHDF5.cmake86
-rw-r--r--Modules/FindHg.cmake3
-rw-r--r--Modules/FindICU.cmake38
-rw-r--r--Modules/FindIce.cmake12
-rw-r--r--Modules/FindImageMagick.cmake3
-rw-r--r--Modules/FindIntl.cmake50
-rw-r--r--Modules/FindJPEG.cmake10
-rw-r--r--Modules/FindJava.cmake7
-rw-r--r--Modules/FindLAPACK.cmake108
-rw-r--r--Modules/FindLATEX.cmake4
-rw-r--r--Modules/FindLibArchive.cmake4
-rw-r--r--Modules/FindLibLZMA.cmake2
-rw-r--r--Modules/FindLibXml2.cmake8
-rw-r--r--Modules/FindLibXslt.cmake5
-rw-r--r--Modules/FindLua.cmake5
-rw-r--r--Modules/FindMPI.cmake27
-rw-r--r--Modules/FindMatlab.cmake135
-rw-r--r--Modules/FindOpenACC.cmake22
-rw-r--r--Modules/FindOpenCL.cmake5
-rw-r--r--Modules/FindOpenGL.cmake46
-rw-r--r--Modules/FindOpenMP.cmake17
-rw-r--r--Modules/FindOpenSSL.cmake49
-rw-r--r--Modules/FindPNG.cmake5
-rw-r--r--Modules/FindPackageHandleStandardArgs.cmake18
-rw-r--r--Modules/FindPkgConfig.cmake76
-rw-r--r--Modules/FindPostgreSQL.cmake36
-rw-r--r--Modules/FindProtobuf.cmake26
-rw-r--r--Modules/FindPython.cmake112
-rw-r--r--Modules/FindPython/Support.cmake25
-rw-r--r--Modules/FindPython2.cmake99
-rw-r--r--Modules/FindPython3.cmake113
-rw-r--r--Modules/FindQt.cmake6
-rw-r--r--Modules/FindQt3.cmake7
-rw-r--r--Modules/FindRuby.cmake12
-rw-r--r--Modules/FindSDL.cmake8
-rw-r--r--Modules/FindSWIG.cmake19
-rw-r--r--Modules/FindSquish.cmake3
-rw-r--r--Modules/FindSubversion.cmake9
-rw-r--r--Modules/FindTIFF.cmake7
-rw-r--r--Modules/FindThreads.cmake4
-rw-r--r--Modules/FindVulkan.cmake7
-rw-r--r--Modules/FindX11.cmake20
-rw-r--r--Modules/FindXercesC.cmake5
-rw-r--r--Modules/FindZLIB.cmake5
-rw-r--r--Modules/FindwxWidgets.cmake9
-rw-r--r--Modules/FortranCInterface.cmake8
-rw-r--r--Modules/FortranCInterface/Detect.cmake10
-rw-r--r--Modules/GNUInstallDirs.cmake40
-rw-r--r--Modules/GenerateExportHeader.cmake28
-rw-r--r--Modules/GetPrerequisites.cmake11
-rw-r--r--Modules/GoogleTest.cmake10
-rw-r--r--Modules/GoogleTestAddTests.cmake2
-rw-r--r--Modules/InstallRequiredSystemLibraries.cmake46
-rw-r--r--Modules/Internal/CPack/CPack.NuGet.nuspec.in5
-rw-r--r--Modules/Internal/CPack/CPackDeb.cmake21
-rw-r--r--Modules/Internal/CPack/CPackNuGet.cmake80
-rw-r--r--Modules/Internal/CPack/NSIS.template.in3
-rw-r--r--Modules/MacroAddFileDependencies.cmake29
-rw-r--r--Modules/Platform/Android-Clang.cmake48
-rw-r--r--Modules/Platform/Android-Common.cmake12
-rw-r--r--Modules/Platform/Android-Determine.cmake181
-rw-r--r--Modules/Platform/Android-Initialize.cmake14
-rw-r--r--Modules/Platform/Android.cmake68
-rw-r--r--Modules/Platform/Android/Determine-Compiler.cmake12
-rw-r--r--Modules/Platform/Android/abi-arm64-v8a-Clang.cmake3
-rw-r--r--Modules/Platform/Android/abi-armeabi-Clang.cmake3
-rw-r--r--Modules/Platform/Android/abi-armeabi-v6-Clang.cmake3
-rw-r--r--Modules/Platform/Android/abi-armeabi-v7a-Clang.cmake3
-rw-r--r--Modules/Platform/Android/abi-mips-Clang.cmake3
-rw-r--r--Modules/Platform/Android/abi-mips64-Clang.cmake3
-rw-r--r--Modules/Platform/Android/abi-x86-Clang.cmake3
-rw-r--r--Modules/Platform/Android/abi-x86_64-Clang.cmake3
-rw-r--r--Modules/Platform/Apple-IntelLLVM-C.cmake2
-rw-r--r--Modules/Platform/Apple-IntelLLVM-CXX.cmake2
-rw-r--r--Modules/Platform/Apple-IntelLLVM-Fortran.cmake8
-rw-r--r--Modules/Platform/Apple-IntelLLVM.cmake17
-rw-r--r--Modules/Platform/Linux-IntelLLVM-C.cmake3
-rw-r--r--Modules/Platform/Linux-IntelLLVM-CXX.cmake3
-rw-r--r--Modules/Platform/Linux-IntelLLVM-Fortran.cmake4
-rw-r--r--Modules/Platform/Linux-IntelLLVM.cmake55
-rw-r--r--Modules/Platform/Linux-NVHPC-C.cmake2
-rw-r--r--Modules/Platform/Linux-NVHPC-CXX.cmake2
-rw-r--r--Modules/Platform/Linux-NVHPC-Fortran.cmake2
-rw-r--r--Modules/Platform/Linux-NVHPC.cmake15
-rw-r--r--Modules/Platform/Linux.cmake1
-rw-r--r--Modules/Platform/Windows-Clang-C.cmake16
-rw-r--r--Modules/Platform/Windows-Clang-CXX.cmake16
-rw-r--r--Modules/Platform/Windows-Clang.cmake11
-rw-r--r--Modules/Platform/Windows-Embarcadero.cmake8
-rw-r--r--Modules/Platform/Windows-Intel-C.cmake27
-rw-r--r--Modules/Platform/Windows-Intel-CXX.cmake27
-rw-r--r--Modules/Platform/Windows-Intel.cmake14
-rw-r--r--Modules/Platform/Windows-IntelLLVM-ASM.cmake2
-rw-r--r--Modules/Platform/Windows-IntelLLVM-C.cmake2
-rw-r--r--Modules/Platform/Windows-IntelLLVM-CXX.cmake3
-rw-r--r--Modules/Platform/Windows-IntelLLVM-Fortran.cmake44
-rw-r--r--Modules/Platform/Windows-IntelLLVM.cmake17
-rw-r--r--Modules/Platform/Windows-MSVC-C.cmake7
-rw-r--r--Modules/Platform/Windows-MSVC-CXX.cmake7
-rw-r--r--Modules/Platform/Windows-MSVC.cmake44
-rw-r--r--Modules/ProcessorCount.cmake3
-rw-r--r--Modules/TestBigEndian.cmake36
-rw-r--r--Modules/UseJava.cmake103
-rw-r--r--Modules/UseJava/ClassFilelist.cmake (renamed from Modules/UseJavaClassFilelist.cmake)15
-rw-r--r--Modules/UseJava/Symlinks.cmake (renamed from Modules/UseJavaSymlinks.cmake)11
-rw-r--r--Modules/UseJava/javaTargets.cmake.in (renamed from Modules/javaTargets.cmake.in)2
-rw-r--r--Modules/UseSWIG.cmake147
-rw-r--r--Modules/WriteCompilerDetectionHeader.cmake43
-rw-r--r--Source/CMakeLists.txt51
-rw-r--r--Source/CMakeVersion.cmake6
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.cxx8
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.h8
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx51
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.h4
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx8
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.h2
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.cxx10
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.h4
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx67
-rw-r--r--Source/CPack/cmCPackComponentGroup.cxx2
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx221
-rw-r--r--Source/CPack/cmCPackExternalGenerator.cxx10
-rw-r--r--Source/CPack/cmCPackGenerator.cxx67
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx51
-rw-r--r--Source/CPack/cmCPackNuGetGenerator.cxx23
-rw-r--r--Source/CPack/cmCPackRPMGenerator.cxx65
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.cxx2
-rw-r--r--Source/CTest/cmCTestBZR.cxx6
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx45
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx10
-rw-r--r--Source/CTest/cmCTestLaunch.cxx2
-rw-r--r--Source/CTest/cmCTestLaunch.h2
-rw-r--r--Source/CTest/cmCTestLaunchReporter.cxx4
-rw-r--r--Source/CTest/cmCTestLaunchReporter.h2
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx14
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h2
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx36
-rw-r--r--Source/CTest/cmCTestP4.cxx72
-rw-r--r--Source/CTest/cmCTestResourceGroupsLexerHelper.cxx2
-rw-r--r--Source/CTest/cmCTestRunTest.cxx17
-rw-r--r--Source/CTest/cmCTestSVN.cxx8
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx10
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx3
-rw-r--r--Source/CTest/cmParseBlanketJSCoverage.cxx4
-rw-r--r--Source/CTest/cmParseCoberturaCoverage.cxx4
-rw-r--r--Source/CTest/cmParseDelphiCoverage.cxx2
-rw-r--r--Source/CTest/cmProcess.cxx16
-rw-r--r--Source/CTest/cmProcess.h4
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx4
-rw-r--r--Source/CursesDialog/form/CMakeLists.txt2
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.cxx982
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.y8
-rw-r--r--Source/LexerParser/cmCommandArgumentParserTokens.h53
-rw-r--r--Source/LexerParser/cmDependsJavaParser.cxx4007
-rw-r--r--Source/LexerParser/cmDependsJavaParser.y8
-rw-r--r--Source/LexerParser/cmDependsJavaParserTokens.h326
-rw-r--r--Source/LexerParser/cmExprParser.cxx993
-rw-r--r--Source/LexerParser/cmExprParser.y12
-rw-r--r--Source/LexerParser/cmExprParserTokens.h59
-rw-r--r--Source/LexerParser/cmFortranParser.cxx1093
-rw-r--r--Source/LexerParser/cmFortranParser.y6
-rw-r--r--Source/LexerParser/cmFortranParserTokens.h135
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.cxx2
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.in.l2
-rw-r--r--Source/QtDialog/CMakeLists.txt132
-rw-r--r--Source/QtDialog/CMakeSetup.cxx6
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx23
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui19
-rw-r--r--Source/QtDialog/EnvironmentDialog.cxx14
-rw-r--r--Source/QtDialog/EnvironmentDialog.ui14
-rw-r--r--Source/QtDialog/QCMake.cxx13
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx8
-rw-r--r--Source/QtDialog/QCMakeWidgets.cxx40
-rw-r--r--Source/bindexplib.cxx4
-rw-r--r--Source/cmAddCustomCommandCommand.cxx54
-rw-r--r--Source/cmAddCustomTargetCommand.cxx19
-rw-r--r--Source/cmAddLibraryCommand.cxx10
-rw-r--r--Source/cmAlgorithms.h3
-rw-r--r--Source/cmArchiveWrite.cxx16
-rw-r--r--Source/cmArchiveWrite.h5
-rw-r--r--Source/cmAuxSourceDirectoryCommand.cxx2
-rw-r--r--Source/cmBase32.cxx2
-rw-r--r--Source/cmBase32.h3
-rw-r--r--Source/cmCMakePath.cxx3
-rw-r--r--Source/cmCMakePathCommand.cxx139
-rw-r--r--Source/cmCMakePolicyCommand.cxx3
-rw-r--r--Source/cmCMakePresetsFile.cxx1286
-rw-r--r--Source/cmCMakePresetsFile.h307
-rw-r--r--Source/cmCPluginAPI.cxx27
-rw-r--r--Source/cmCTest.cxx393
-rw-r--r--Source/cmCTest.h6
-rw-r--r--Source/cmCacheManager.cxx4
-rw-r--r--Source/cmCacheManager.h20
-rw-r--r--Source/cmCheckCustomOutputs.cxx36
-rw-r--r--Source/cmCheckCustomOutputs.h15
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx4
-rw-r--r--Source/cmCommandLineArgument.h159
-rw-r--r--Source/cmCommands.cxx19
-rw-r--r--Source/cmCommonTargetGenerator.cxx2
-rw-r--r--Source/cmComputeLinkInformation.cxx3
-rw-r--r--Source/cmComputeTargetDepends.cxx2
-rw-r--r--Source/cmConditionEvaluator.cxx16
-rw-r--r--Source/cmConfigure.cmake.h.in5
-rw-r--r--Source/cmConfigureFileCommand.cxx109
-rw-r--r--Source/cmConnection.cxx173
-rw-r--r--Source/cmConnection.h137
-rw-r--r--Source/cmConsoleBuf.cxx2
-rw-r--r--Source/cmConsoleBuf.h2
-rw-r--r--Source/cmCreateTestSourceList.cxx4
-rw-r--r--Source/cmCryptoHash.cxx2
-rw-r--r--Source/cmCustomCommand.cxx10
-rw-r--r--Source/cmCustomCommand.h6
-rw-r--r--Source/cmCustomCommandGenerator.cxx261
-rw-r--r--Source/cmCustomCommandGenerator.h25
-rw-r--r--Source/cmCustomCommandTypes.h7
-rw-r--r--Source/cmDepends.cxx2
-rw-r--r--Source/cmDepends.h3
-rw-r--r--Source/cmDependsC.cxx31
-rw-r--r--Source/cmDependsCompiler.cxx252
-rw-r--r--Source/cmDependsCompiler.h60
-rw-r--r--Source/cmDependsFortran.cxx29
-rw-r--r--Source/cmDependsJavaParserHelper.cxx2
-rw-r--r--Source/cmDependsJavaParserHelper.h2
-rw-r--r--Source/cmDocumentation.cxx2
-rw-r--r--Source/cmELF.cxx8
-rw-r--r--Source/cmELF.h4
-rw-r--r--Source/cmExecuteProcessCommand.cxx2
-rw-r--r--Source/cmExportFileGenerator.cxx8
-rw-r--r--Source/cmExportInstallFileGenerator.cxx1
-rw-r--r--Source/cmExprParserHelper.cxx16
-rw-r--r--Source/cmExprParserHelper.h2
-rw-r--r--Source/cmExternalMakefileProjectGenerator.h6
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx37
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx36
-rw-r--r--Source/cmExtraCodeLiteGenerator.h1
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx7
-rw-r--r--Source/cmFLTKWrapUICommand.cxx7
-rw-r--r--Source/cmFileAPI.cxx63
-rw-r--r--Source/cmFileAPI.h5
-rw-r--r--Source/cmFileAPICMakeFiles.cxx4
-rw-r--r--Source/cmFileAPICache.cxx2
-rw-r--r--Source/cmFileAPICodemodel.cxx4
-rw-r--r--Source/cmFileAPIToolchains.cxx151
-rw-r--r--Source/cmFileAPIToolchains.h12
-rw-r--r--Source/cmFileCommand.cxx280
-rw-r--r--Source/cmFileLock.cxx2
-rw-r--r--Source/cmFileLock.h2
-rw-r--r--Source/cmFileLockPool.cxx11
-rw-r--r--Source/cmFileLockUnix.cxx2
-rw-r--r--Source/cmFileMonitor.cxx383
-rw-r--r--Source/cmFileMonitor.h35
-rw-r--r--Source/cmFilePathChecksum.cxx13
-rw-r--r--Source/cmFileTimes.cxx6
-rw-r--r--Source/cmFileTimes.h2
-rw-r--r--Source/cmFindCommon.cxx4
-rw-r--r--Source/cmFindLibraryCommand.cxx2
-rw-r--r--Source/cmFindPackageCommand.cxx41
-rw-r--r--Source/cmFindPathCommand.cxx6
-rw-r--r--Source/cmFindPathCommand.h2
-rw-r--r--Source/cmFindProgramCommand.cxx73
-rw-r--r--Source/cmFunctionBlocker.h1
-rw-r--r--Source/cmFunctionCommand.cxx7
-rw-r--r--Source/cmGccDepfileLexerHelper.cxx33
-rw-r--r--Source/cmGccDepfileLexerHelper.h3
-rw-r--r--Source/cmGccDepfileReader.cxx38
-rw-r--r--Source/cmGccDepfileReader.h10
-rw-r--r--Source/cmGeneratedFileStream.cxx8
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx6
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h1
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx52
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.h6
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx6
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h3
-rw-r--r--Source/cmGeneratorExpressionLexer.cxx4
-rw-r--r--Source/cmGeneratorExpressionNode.cxx14
-rw-r--r--Source/cmGeneratorExpressionParser.cxx2
-rw-r--r--Source/cmGeneratorExpressionParser.h1
-rw-r--r--Source/cmGeneratorTarget.cxx189
-rw-r--r--Source/cmGeneratorTarget.h11
-rw-r--r--Source/cmGetDirectoryPropertyCommand.cxx43
-rw-r--r--Source/cmGetPropertyCommand.cxx22
-rw-r--r--Source/cmGetSourceFilePropertyCommand.cxx7
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx37
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx9
-rw-r--r--Source/cmGlobalGenerator.cxx26
-rw-r--r--Source/cmGlobalGenerator.h31
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx20
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx2
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx479
-rw-r--r--Source/cmGlobalNinjaGenerator.h90
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx15
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h27
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx7
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx19
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx2
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx1
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx297
-rw-r--r--Source/cmGlobalXCodeGenerator.h8
-rw-r--r--Source/cmGraphVizWriter.cxx70
-rw-r--r--Source/cmIncludeCommand.cxx22
-rw-r--r--Source/cmInstallCommand.cxx110
-rw-r--r--Source/cmInstallCommandArguments.cxx13
-rw-r--r--Source/cmInstallDirectoryGenerator.cxx28
-rw-r--r--Source/cmInstallDirectoryGenerator.h18
-rw-r--r--Source/cmInstallExportGenerator.cxx11
-rw-r--r--Source/cmInstallExportGenerator.h6
-rw-r--r--Source/cmInstallFilesCommand.cxx2
-rw-r--r--Source/cmInstallFilesGenerator.cxx42
-rw-r--r--Source/cmInstallFilesGenerator.h6
-rw-r--r--Source/cmInstallGenerator.cxx4
-rw-r--r--Source/cmInstallGenerator.h10
-rw-r--r--Source/cmInstallProgramsCommand.cxx2
-rw-r--r--Source/cmInstallScriptGenerator.cxx32
-rw-r--r--Source/cmInstallScriptGenerator.h14
-rw-r--r--Source/cmInstallSubdirectoryGenerator.cxx5
-rw-r--r--Source/cmInstallSubdirectoryGenerator.h4
-rw-r--r--Source/cmInstallTargetGenerator.cxx257
-rw-r--r--Source/cmInstallTargetGenerator.h32
-rw-r--r--Source/cmJsonObjectDictionary.h45
-rw-r--r--Source/cmJsonObjects.cxx692
-rw-r--r--Source/cmJsonObjects.h24
-rw-r--r--Source/cmLinkItemGraphVisitor.cxx5
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx19
-rw-r--r--Source/cmLinkedTree.h4
-rw-r--r--Source/cmListCommand.cxx32
-rw-r--r--Source/cmListFileCache.cxx122
-rw-r--r--Source/cmListFileCache.h10
-rw-r--r--Source/cmLoadCommandCommand.cxx14
-rw-r--r--Source/cmLocalGenerator.cxx626
-rw-r--r--Source/cmLocalGenerator.h155
-rw-r--r--Source/cmLocalNinjaGenerator.cxx321
-rw-r--r--Source/cmLocalNinjaGenerator.h17
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx576
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h33
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx12
-rw-r--r--Source/cmMSVC60LinkLineComputer.cxx2
-rw-r--r--Source/cmMachO.h4
-rw-r--r--Source/cmMacroCommand.cxx7
-rw-r--r--Source/cmMakefile.cxx429
-rw-r--r--Source/cmMakefile.h153
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx13
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx13
-rw-r--r--Source/cmMakefileTargetGenerator.cxx260
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx39
-rw-r--r--Source/cmNewLineStyle.cxx14
-rw-r--r--Source/cmNinjaLinkLineComputer.cxx2
-rw-r--r--Source/cmNinjaLinkLineDeviceComputer.cxx2
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx88
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h1
-rw-r--r--Source/cmNinjaTargetGenerator.cxx567
-rw-r--r--Source/cmNinjaTargetGenerator.h19
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx63
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.h4
-rw-r--r--Source/cmOSXBundleGenerator.h1
-rw-r--r--Source/cmOutputConverter.cxx41
-rw-r--r--Source/cmOutputConverter.h9
-rw-r--r--Source/cmOutputRequiredFilesCommand.cxx2
-rw-r--r--Source/cmPipeConnection.cxx71
-rw-r--r--Source/cmPipeConnection.h29
-rw-r--r--Source/cmPolicies.h22
-rw-r--r--Source/cmProcessOutput.cxx6
-rw-r--r--Source/cmProcessOutput.h2
-rw-r--r--Source/cmProjectCommand.cxx13
-rw-r--r--Source/cmPropertyMap.cxx22
-rw-r--r--Source/cmQTWrapCPPCommand.cxx10
-rw-r--r--Source/cmQTWrapUICommand.cxx10
-rw-r--r--Source/cmQtAutoGen.h13
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx58
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.h4
-rw-r--r--Source/cmQtAutoGenInitializer.cxx222
-rw-r--r--Source/cmQtAutoGenInitializer.h9
-rw-r--r--Source/cmQtAutoGenerator.cxx121
-rw-r--r--Source/cmQtAutoGenerator.h19
-rw-r--r--Source/cmQtAutoMocUic.cxx1299
-rw-r--r--Source/cmQtAutoRcc.cxx361
-rw-r--r--Source/cmRST.cxx5
-rw-r--r--Source/cmRulePlaceholderExpander.cxx16
-rw-r--r--Source/cmRulePlaceholderExpander.h79
-rw-r--r--Source/cmRuntimeDependencyArchive.cxx11
-rw-r--r--Source/cmScanDepFormat.cxx265
-rw-r--r--Source/cmScanDepFormat.h30
-rw-r--r--Source/cmScriptGenerator.cxx12
-rw-r--r--Source/cmServer.cxx570
-rw-r--r--Source/cmServer.h162
-rw-r--r--Source/cmServerConnection.cxx165
-rw-r--r--Source/cmServerConnection.h67
-rw-r--r--Source/cmServerDictionary.h67
-rw-r--r--Source/cmServerProtocol.cxx760
-rw-r--r--Source/cmServerProtocol.h162
-rw-r--r--Source/cmSetPropertyCommand.cxx109
-rw-r--r--Source/cmSetPropertyCommand.h15
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.cxx13
-rw-r--r--Source/cmSourceFile.cxx170
-rw-r--r--Source/cmSourceFile.h47
-rw-r--r--Source/cmSourceFileLocation.cxx7
-rw-r--r--Source/cmStandardLevelResolver.cxx43
-rw-r--r--Source/cmStandardLexer.h4
-rw-r--r--Source/cmState.cxx44
-rw-r--r--Source/cmState.h8
-rw-r--r--Source/cmStateDirectory.cxx10
-rw-r--r--Source/cmStateDirectory.h1
-rw-r--r--Source/cmString.cxx44
-rw-r--r--Source/cmString.hxx134
-rw-r--r--Source/cmStringAlgorithms.cxx20
-rw-r--r--Source/cmStringAlgorithms.h8
-rw-r--r--Source/cmStringCommand.cxx13
-rw-r--r--Source/cmSystemTools.cxx155
-rw-r--r--Source/cmSystemTools.h6
-rw-r--r--Source/cmTarget.cxx702
-rw-r--r--Source/cmTarget.h6
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx5
-rw-r--r--Source/cmTargetPrecompileHeadersCommand.cxx2
-rw-r--r--Source/cmTargetPropCommandBase.cxx41
-rw-r--r--Source/cmTargetPropCommandBase.h5
-rw-r--r--Source/cmTargetSourcesCommand.cxx8
-rw-r--r--Source/cmTestGenerator.cxx2
-rw-r--r--Source/cmTimestamp.cxx12
-rw-r--r--Source/cmTimestamp.h4
-rw-r--r--Source/cmTransformDepfile.cxx122
-rw-r--r--Source/cmTransformDepfile.h16
-rw-r--r--Source/cmTryRunCommand.cxx21
-rw-r--r--Source/cmTryRunCommand.h1
-rw-r--r--Source/cmUVHandlePtr.cxx48
-rw-r--r--Source/cmUVHandlePtr.h6
-rw-r--r--Source/cmUuid.cxx6
-rw-r--r--Source/cmVersion.h8
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx98
-rw-r--r--Source/cmWorkerPool.cxx355
-rw-r--r--Source/cmWorkerPool.h25
-rw-r--r--Source/cmWorkingDirectory.h4
-rw-r--r--Source/cmXCOFF.cxx356
-rw-r--r--Source/cmXCOFF.h65
-rw-r--r--Source/cmXCodeObject.h7
-rw-r--r--Source/cmXMLSafe.cxx2
-rw-r--r--Source/cmXMLSafe.h2
-rw-r--r--Source/cmXMLWriter.h22
-rw-r--r--Source/cm_codecvt.cxx8
-rw-r--r--Source/cmake.cxx1041
-rw-r--r--Source/cmake.h30
-rw-r--r--Source/cmakemain.cxx458
-rw-r--r--Source/cmcmd.cxx329
-rw-r--r--Source/ctest.cxx4
-rw-r--r--Source/kwsys/FStream.hxx.in46
-rw-r--r--Source/kwsys/ProcessWin32.c5
-rw-r--r--Source/kwsys/SystemInformation.cxx314
-rw-r--r--Source/kwsys/testFStream.cxx38
-rw-r--r--Templates/MSBuild/FlagTables/v142_CSharp.json18
-rw-r--r--Templates/MSBuild/FlagTables/v142_Link.json7
-rw-r--r--Templates/MSBuild/FlagTables/v14_LIB.json7
-rw-r--r--Templates/TestDriver.cxx.in2
-rw-r--r--Tests/Architecture/CMakeLists.txt2
-rw-r--r--Tests/ArgumentExpansion/CMakeLists.txt2
-rw-r--r--Tests/Assembler/CMakeLists.txt2
-rw-r--r--Tests/BuildDepends/Project/CMakeLists.txt6
-rw-r--r--Tests/BundleTest/BundleLib.cxx4
-rw-r--r--Tests/BundleTest/BundleSubDir/CMakeLists.txt8
-rw-r--r--Tests/BundleTest/CMakeLists.txt17
-rw-r--r--Tests/BundleUtilities/CMakeLists.txt11
-rw-r--r--Tests/CFBundleTest/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/add_compile_options/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/target_compile_options/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/target_include_directories/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/target_link_libraries/CMakeLists.txt3
-rw-r--r--Tests/CMakeLib/run_compile_commands.cxx52
-rw-r--r--Tests/CMakeLib/testCMExtMemory.cxx4
-rw-r--r--Tests/CMakeLib/testGccDepfileReader.cxx21
-rw-r--r--Tests/CMakeLib/testGccDepfileReader_data/deps4.d1
-rw-r--r--Tests/CMakeLib/testGccDepfileReader_data/deps5.d0
-rw-r--r--Tests/CMakeLib/testGccDepfileReader_data/deps5.txt2
-rw-r--r--Tests/CMakeLib/testGccDepfileReader_data/deps7.d6
-rw-r--r--Tests/CMakeLib/testGccDepfileReader_data/deps7.txt10
-rw-r--r--Tests/CMakeLib/testOptional.cxx28
-rw-r--r--Tests/CMakeLib/testRST.expect22
-rw-r--r--Tests/CMakeLib/testRST.rst22
-rw-r--r--Tests/CMakeLib/testUVProcessChain.cxx4
-rw-r--r--Tests/CMakeLists.txt65
-rw-r--r--Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/MajorVersionSelection/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/find_library/CMakeLists.txt2
-rw-r--r--Tests/CMakeOnly/find_path/CMakeLists.txt2
-rw-r--r--Tests/CMakeServerLib/CMakeLists.txt21
-rw-r--r--Tests/CMakeServerLib/testServerBuffering.cpp87
-rw-r--r--Tests/CMakeTestMultipleConfigures/RunCMake.cmake165
-rw-r--r--Tests/CMakeTests/CMakeLists.txt4
-rw-r--r--Tests/CMakeTests/EndStuffTestScript.cmake60
-rw-r--r--Tests/CMakeTests/FileDownloadTest.cmake.in3
-rw-r--r--Tests/CMakeTests/ListTest.cmake.in3
-rw-r--r--Tests/CPackComponentsDEB/CMakeLists.txt14
-rw-r--r--Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-failure.cmake.in24
-rw-r--r--Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-success.cmake.in33
-rw-r--r--Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-failure.cmake19
-rw-r--r--Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-success.cmake75
-rw-r--r--Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake13
-rw-r--r--Tests/CPackComponentsDEB/mylibapp.cpp15
-rw-r--r--Tests/CPackComponentsDEB/shlibdeps-with-private-lib/CMakeLists.txt5
-rw-r--r--Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.cpp8
-rw-r--r--Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.h1
-rw-r--r--Tests/CPackNSISGenerator/CMakeLists.txt2
-rw-r--r--Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake8
-rw-r--r--Tests/CPackTestAllGenerators/CMakeLists.txt2
-rw-r--r--Tests/CPackWiXGenerator/CMakeLists.txt2
-rw-r--r--Tests/CTestCoverageCollectGCOV/test.cmake.in19
-rw-r--r--Tests/CTestLimitDashJ/CMakeLists.txt2
-rw-r--r--Tests/CTestTest/SmallAndFast/CMakeLists.txt2
-rw-r--r--Tests/CTestUpdateCVS.cmake.in18
-rw-r--r--Tests/CTestUpdateGIT.cmake.in32
-rw-r--r--Tests/CheckCompilerRelatedVariables/CMakeLists.txt2
-rw-r--r--Tests/CompileDefinitions/CMakeLists.txt2
-rw-r--r--Tests/CompileFeatures/CMakeLists.txt11
-rw-r--r--Tests/CompileFeatures/default_dialect.cpp6
-rw-r--r--Tests/CompileFeatures/genex_test.cpp6
-rw-r--r--Tests/CompileOptions/CMakeLists.txt2
-rw-r--r--Tests/ConfigSources/CMakeLists.txt76
-rw-r--r--Tests/ConfigSources/custom1.cpp.in13
-rw-r--r--Tests/ConfigSources/custom2.cpp.in13
-rw-r--r--Tests/ConfigSources/custom3.cpp.in13
-rw-r--r--Tests/ConfigSources/custom4.cpp.in13
-rw-r--r--Tests/ConfigSources/custom5.cpp.in13
-rw-r--r--Tests/ConfigSources/main_debug.cpp9
-rw-r--r--Tests/ConfigSources/main_other.cpp9
-rw-r--r--Tests/Contracts/Trilinos/CMakeLists.txt2
-rw-r--r--Tests/Contracts/VTK/CMakeLists.txt2
-rw-r--r--Tests/Cuda/Toolkit/CMakeLists.txt4
-rw-r--r--Tests/CudaOnly/CMakeLists.txt1
-rw-r--r--Tests/CudaOnly/CompileFlags/CMakeLists.txt1
-rw-r--r--Tests/CudaOnly/ExportPTX/CMakeLists.txt6
-rw-r--r--Tests/CudaOnly/Toolkit/CMakeLists.txt4
-rw-r--r--Tests/CudaOnly/ToolkitBeforeLang/CMakeLists.txt26
-rw-r--r--Tests/CudaOnly/ToolkitBeforeLang/main.cu8
-rw-r--r--Tests/CustomCommand/CMakeLists.txt4
-rw-r--r--Tests/CustomCommand/empty_command.cxx (renamed from Tests/Server/empty.cpp)1
-rw-r--r--Tests/EmptyDepends/CMakeLists.txt2
-rw-r--r--Tests/ExportImport/Import/try_compile/CMakeLists.txt2
-rw-r--r--Tests/ExternalProject/CMakeLists.txt32
-rw-r--r--Tests/ExternalProject/Example/CMakeLists.txt2
-rw-r--r--Tests/ExternalProject/gitrepo-sub-rec.tgzbin9008 -> 2086 bytes
-rw-r--r--Tests/ExternalProject/gitrepo-sub.tgzbin1911 -> 2229 bytes
-rwxr-xr-xTests/ExternalProject/gitrepo.bash129
-rw-r--r--Tests/ExternalProject/gitrepo.tgzbin1934 -> 1817 bytes
-rw-r--r--Tests/ExternalProjectLocal/CMakeLists.txt2
-rw-r--r--Tests/ExternalProjectUpdate/CMakeLists.txt17
-rw-r--r--Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake33
-rw-r--r--Tests/ExternalProjectUpdate/gitrepo.tgzbin3057 -> 3397 bytes
-rw-r--r--Tests/FindGTK2/atk/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/atkmm/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/cairo/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/cairomm/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gdk/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gdk_pixbuf/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gdkmm/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gio/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/giomm/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/glib/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/glibmm/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gmodule/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gobject/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gthread/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gtk/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/gtkmm/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/pango/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/pangocairo/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/pangoft2/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/pangomm/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/pangoxft/CMakeLists.txt2
-rw-r--r--Tests/FindGTK2/sigc++/CMakeLists.txt2
-rw-r--r--Tests/FindIntl/CMakeLists.txt10
-rw-r--r--Tests/FindIntl/Test/CMakeLists.txt14
-rw-r--r--Tests/FindIntl/Test/main.cxx11
-rw-r--r--Tests/FindPostgreSQL/Test/CMakeLists.txt2
-rw-r--r--Tests/FindPython/CMakeLists.txt12
-rw-r--r--Tests/FindPython/UnversionedNames/CMakeLists.txt66
-rw-r--r--Tests/Fortran/CMakeLists.txt2
-rw-r--r--Tests/Fortran/myc.c4
-rw-r--r--Tests/FortranC/CMakeLists.txt2
-rw-r--r--Tests/FortranOnly/CMakeLists.txt6
-rw-r--r--Tests/Fuzzing/README.rst8
-rw-r--r--Tests/Fuzzing/xml_parser_fuzzer.cc27
-rw-r--r--Tests/IncludeDirectories/CMakeLists.txt6
-rw-r--r--Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt2
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt2
-rw-r--r--Tests/InterfaceLibrary/CMakeLists.txt2
-rw-r--r--Tests/JavaNativeHeaders/CMakeLists.txt9
-rw-r--r--Tests/JavaNativeHeaders/Import/CMakeLists.txt19
-rw-r--r--Tests/LinkDirectory/CMakeLists.txt2
-rw-r--r--Tests/LinkDirectory/External/CMakeLists.txt2
-rw-r--r--Tests/LinkFlags/CMakeLists.txt2
-rw-r--r--Tests/MFC/CMakeLists.txt2
-rw-r--r--Tests/MFC/CMakeLists.txt.in2
-rw-r--r--Tests/MFC/try_compile/CMakeLists.txt2
-rw-r--r--Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt5
-rw-r--r--Tests/MacRuntimePath/A/CMakeLists.txt2
-rw-r--r--Tests/MacRuntimePath/B/CMakeLists.txt2
-rw-r--r--Tests/MissingSourceFile/CMakeLists.txt2
-rw-r--r--Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt4
-rw-r--r--Tests/ObjectLibrary/CMakeLists.txt2
-rw-r--r--Tests/ObjectLibrary/ExportLanguages/CMakeLists.txt2
-rw-r--r--Tests/ObjectLibrary/ExportLanguages/ExportLanguagesTest/CMakeLists.txt2
-rw-r--r--Tests/PDBDirectoryAndName/CMakeLists.txt7
-rw-r--r--Tests/Plugin/PluginTest/CMakeLists.txt2
-rw-r--r--Tests/PositionIndependentTargets/CMakeLists.txt2
-rw-r--r--Tests/Preprocess/CMakeLists.txt7
-rw-r--r--Tests/Qt4Targets/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt13
-rw-r--r--Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt8
-rw-r--r--Tests/QtAutogen/MocOnly/CMakeLists.txt12
-rw-r--r--Tests/QtAutogen/MocOnly/CfgDebug.cpp5
-rw-r--r--Tests/QtAutogen/MocOnly/CfgDebug.hpp15
-rw-r--r--Tests/QtAutogen/MocOnly/CfgOther.cpp5
-rw-r--r--Tests/QtAutogen/MocOnly/CfgOther.hpp15
-rw-r--r--Tests/QtAutogen/MocOnly/main.cpp8
-rw-r--r--Tests/QtAutogen/RerunMocBasic/CMakeLists.txt79
-rw-r--r--Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt7
-rw-r--r--Tests/QtAutogen/RerunMocBasic/MocBasic/main.cpp.in2
-rw-r--r--Tests/QtAutogen/RerunMocBasic/MocBasic/myobject3a.h.in13
-rw-r--r--Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.cpp12
-rw-r--r--Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.h12
-rw-r--r--Tests/QtAutogen/RerunMocBasic/MocBasic/test1c.h.in6
-rw-r--r--Tests/QtAutogen/TestMacros.cmake10
-rw-r--r--Tests/QtAutomocNoQt/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/ABI/C-stdout.txt1
-rw-r--r--Tests/RunCMake/ABI/C.cmake22
-rw-r--r--Tests/RunCMake/ABI/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/ABI/CUDA.cmake13
-rw-r--r--Tests/RunCMake/ABI/CXX-stdout.txt1
-rw-r--r--Tests/RunCMake/ABI/CXX.cmake22
-rw-r--r--Tests/RunCMake/ABI/OBJC.cmake13
-rw-r--r--Tests/RunCMake/ABI/OBJCXX.cmake13
-rw-r--r--Tests/RunCMake/ABI/RunCMakeTest.cmake15
-rw-r--r--Tests/RunCMake/ABI/TestBigEndian-NoLang-result.txt (renamed from Tests/RunCMake/CommandLine/E_server-arg-result.txt)0
-rw-r--r--Tests/RunCMake/ABI/TestBigEndian-NoLang-stderr.txt8
-rw-r--r--Tests/RunCMake/ABI/TestBigEndian-NoLang.cmake2
-rw-r--r--Tests/RunCMake/Android/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/Android/common.cmake15
-rw-r--r--Tests/RunCMake/Android/ndk-search-order.cmake17
-rw-r--r--Tests/RunCMake/ArtifactOutputDirs/ArtifactOutputDirs.cmake27
-rw-r--r--Tests/RunCMake/ArtifactOutputDirs/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/ArtifactOutputDirs/RunCMakeTest.cmake19
-rw-r--r--Tests/RunCMake/ArtifactOutputDirs/check.cmake21
-rw-r--r--Tests/RunCMake/ArtifactOutputDirs/lib.c (renamed from Tests/RunCMake/TargetObjects/empty.cpp)2
-rw-r--r--Tests/RunCMake/ArtifactOutputDirs/main.c (renamed from Tests/Server/buildsystem1/foo.cpp)3
-rw-r--r--Tests/RunCMake/BuildDepends/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/BuildDepends/CompilerDependencies.cmake46
-rw-r--r--Tests/RunCMake/BuildDepends/CompilerDependencies.step1.cmake9
-rw-r--r--Tests/RunCMake/BuildDepends/CompilerDependencies.step2.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-result.txt (renamed from Tests/RunCMake/ExternalProject/IncludeScope-Add-result.txt)0
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt4
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake10
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake73
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDependencies.step1.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDependencies.step2.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake61
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDepfile.step1.cmake10
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDepfile.step2.cmake6
-rw-r--r--Tests/RunCMake/BuildDepends/CustomCommandDepfile.step3.cmake1
-rw-r--r--Tests/RunCMake/BuildDepends/DepfileSubdir/CMakeLists.txt22
-rw-r--r--Tests/RunCMake/BuildDepends/GenerateDepFile.cmake6
-rw-r--r--Tests/RunCMake/BuildDepends/MakeDependencies.cmake13
-rw-r--r--Tests/RunCMake/BuildDepends/MakeDependencies.step1.cmake18
-rw-r--r--Tests/RunCMake/BuildDepends/MakeDependencies.step2.cmake3
-rw-r--r--Tests/RunCMake/BuildDepends/RunCMakeTest.cmake34
-rw-r--r--Tests/RunCMake/BuildDepends/WriteDepfile.cmake8
-rw-r--r--Tests/RunCMake/CMP0026/LOCATION-and-TARGET_OBJECTS.cmake2
-rw-r--r--Tests/RunCMake/CMP0026/clear-cached-information.cmake2
-rw-r--r--Tests/RunCMake/CMP0104/CMP0104-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0106/CMP0106-NEW-stderr.txt2
-rw-r--r--Tests/RunCMake/CMP0106/CMP0106-WARN-stderr.txt4
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt (renamed from Tests/RunCMake/ExternalProject/IncludeScope-Add_Step-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt17
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-NEW.cmake1
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt (renamed from Tests/RunCMake/File_Configure/BadArg-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt22
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-OLD.cmake1
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt (renamed from Tests/RunCMake/Make/CustomCommandDepfile-ERROR-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt36
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115-WARN.cmake1
-rw-r--r--Tests/RunCMake/CMP0115/CMP0115.cmake3
-rw-r--r--Tests/RunCMake/CMP0115/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0115/RunCMakeTest.cmake12
-rw-r--r--Tests/RunCMake/CMP0115/main.c (renamed from Tests/Server/buildsystem1/subdir/empty.cpp)3
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-Mixed-stderr.txt17
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-Mixed.cmake18
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-NEW-NOWARN.cmake3
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-NEW-WARN.cmake3
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-OLD-NOWARN.cmake3
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-OLD-WARN.cmake3
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN-stderr.txt7
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN.cmake3
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-WARN-WARN-stderr.txt16
-rw-r--r--Tests/RunCMake/CMP0116/CMP0116-WARN-WARN.cmake3
-rw-r--r--Tests/RunCMake/CMP0116/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0116/Common.cmake8
-rw-r--r--Tests/RunCMake/CMP0116/RunCMakeTest.cmake52
-rw-r--r--Tests/RunCMake/CMP0116/Subdirectory/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/CMP0116/WriteDepfile.cmake3
-rw-r--r--Tests/RunCMake/CMP0116/check.cmake18
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Helper.cmake14
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test1.cmake9
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test10.cmake65
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test11.cmake65
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test12.cmake65
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test13.cmake65
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test14.cmake65
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test15.cmake65
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test2.cmake12
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test3.cmake66
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test3b.cmake66
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test4.cmake66
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test4b.cmake66
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test5.cmake78
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test6.cmake44
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test7.cmake44
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test8.cmake50
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-Common-Test9.cmake50
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-result.txt (renamed from Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test1.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test10-stderr.txt42
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test10.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test11-stderr.txt55
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test11.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test12-result.txt (renamed from Tests/RunCMake/cmake_path/CMAKE_PATH-OUTPUT_VARIABLE-no-arg-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test12-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test12.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test13-result.txt (renamed from Tests/RunCMake/cmake_path/CMAKE_PATH-invalid-output-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test13-stderr.txt64
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test13.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test14-stderr.txt42
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test14.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test15-stderr.txt55
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test15.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test2-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test2.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test3-result.txt (renamed from Tests/RunCMake/cmake_path/CMAKE_PATH-missing-output-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test3-stderr.txt87
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test3.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b-result.txt (renamed from Tests/RunCMake/cmake_path/CMAKE_PATH-unexpected-arg-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b-stderr.txt87
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test4-result.txt (renamed from Tests/RunCMake/cmake_path/CMAKE_PATH-wrong-path-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test4-stderr.txt167
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test4.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b-result.txt (renamed from Tests/RunCMake/cmake_path/COMPARE-EQUAL-wrong-path-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b-stderr.txt167
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test5-result.txt (renamed from Tests/RunCMake/cmake_path/COMPARE-NOT_EQUAL-wrong-path-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test5-stderr.txt174
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test5.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test6-stderr.txt36
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test6.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-result.txt (renamed from Tests/RunCMake/cmake_path/CONCAT-OUTPUT_VARIABLE-invalid-arg-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-stderr.txt74
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test7.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test8-stderr.txt36
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test8.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-result.txt (renamed from Tests/RunCMake/cmake_path/CONCAT-OUTPUT_VARIABLE-no-arg-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-stderr.txt74
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-NEW-Test9.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-result.txt (renamed from Tests/RunCMake/cmake_path/CONCAT-wrong-path-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test1.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-result.txt (renamed from Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-invalid-output-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test10.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-result.txt (renamed from Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-missing-output-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-stderr.txt67
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test11.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test12-result.txt (renamed from Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-unexpected-arg-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test12-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test12.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test13-result.txt (renamed from Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-wrong-path-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test13-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test13.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-result.txt (renamed from Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-invalid-output-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test14.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-result.txt (renamed from Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-missing-output-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-stderr.txt67
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test15.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test2-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test2.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test3-result.txt (renamed from Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-unexpected-arg-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test3-stderr.txt87
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test3.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b-result.txt (renamed from Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-wrong-path-result.txt)0
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b-stderr.txt87
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-stderr.txt95
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test4.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-stderr.txt95
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-stderr.txt111
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test5.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-stderr.txt45
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test6.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-stderr.txt77
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test7.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-stderr.txt45
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test8.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-stderr.txt61
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-OLD-Test9.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-stderr.txt10
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test1.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test10.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-stderr.txt90
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test11.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test12.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-stderr.txt74
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test13.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-stderr.txt51
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test14.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-stderr.txt90
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test15.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test2-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test2.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-stderr.txt87
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test3.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-stderr.txt87
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-stderr.txt212
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test4.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-stderr.txt212
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-stderr.txt213
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test5.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-stderr.txt45
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test6.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-stderr.txt100
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test7.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-stderr.txt45
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test8.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-stderr.txt84
-rw-r--r--Tests/RunCMake/CMP0118/CMP0118-WARN-Test9.cmake1
-rw-r--r--Tests/RunCMake/CMP0118/CMakeLists.txt4
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-Common.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-OLD-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-OLD-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-WARN-result.txt1
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-WARN-stderr.txt8
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0118/GenInSubdir/CMakeLists.txt9
-rw-r--r--Tests/RunCMake/CMP0118/RunCMakeTest.cmake59
-rw-r--r--Tests/RunCMake/CMP0118/source.cpp.in5
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test10/CMakeLists.txt33
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test11/CMakeLists.txt33
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test12/CMakeLists.txt33
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test13/CMakeLists.txt33
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test14/CMakeLists.txt33
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test15/CMakeLists.txt33
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test6/CMakeLists.txt16
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test7/CMakeLists.txt16
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test8/CMakeLists.txt30
-rw-r--r--Tests/RunCMake/CMP0118/subdir-Common-Test9/CMakeLists.txt30
-rw-r--r--Tests/RunCMake/CMP0119/AltExtC.zzz4
-rw-r--r--Tests/RunCMake/CMP0119/AltExtCXX.zzz3
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-Common.cmake4
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-NEW.cmake6
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-OLD-build-result.txt1
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-OLD-build-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-WARN-build-result.txt1
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-WARN-build-stderr.txt1
-rw-r--r--Tests/RunCMake/CMP0119/CMP0119-WARN.cmake2
-rw-r--r--Tests/RunCMake/CMP0119/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMP0119/RunCMakeTest.cmake17
-rw-r--r--Tests/RunCMake/CMakeLists.txt39
-rw-r--r--Tests/RunCMake/CMakePresets/CMakePresets.json.in8
-rw-r--r--Tests/RunCMake/CMakePresets/GoodSpaces-stdout.txt3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodSpacesEq-stdout.txt3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodSpacesEq.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresets-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt3
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetArgumentEq-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetArgumentEq-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/RunCMakeTest.cmake22
-rw-r--r--Tests/RunCMake/CMakePresets/validate_schema.cmake19
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/CMakeLists.txt.in3
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Good-build-build-other-check.cmake5
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Good-build-macros-check.cmake14
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Good-build-noEnvironment-check.cmake6
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Good-build-withEnvironment-check.cmake8
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Good.cmake3
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Good.json.in78
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/Invalid.json.in23
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.json.in16
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt5
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ListPresets.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in31
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.json.in15
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported.json.in7
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake76
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/TestVariable.cmake14
-rw-r--r--Tests/RunCMake/CMakePresetsBuild/check.cmake3
-rw-r--r--Tests/RunCMake/CMakePresetsTest/CMakeLists.txt.in3
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-indexFile.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt5
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt5
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt7
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt7
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt7
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt8
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-test-showOnly-stdout.txt8
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good-withEnvironment-check.cmake8
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good.cmake27
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Good.json.in175
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/Invalid.json.in23
-rw-r--r--Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.json.in16
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ListPresets-test-x-stdout.txt12
-rw-r--r--Tests/RunCMake/CMakePresetsTest/ListPresets.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.json.in15
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoTestsAction.cmake0
-rw-r--r--Tests/RunCMake/CMakePresetsTest/NoTestsAction.json.in19
-rw-r--r--Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresetsTest/PresetsUnsupported.json.in7
-rw-r--r--Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake104
-rw-r--r--Tests/RunCMake/CMakePresetsTest/check.cmake3
-rw-r--r--Tests/RunCMake/CMakeRelease/FileTable-stdout.txt44
-rw-r--r--Tests/RunCMake/CMakeRelease/FileTable.cmake21
-rw-r--r--Tests/RunCMake/CMakeRelease/RunCMakeTest.cmake10
-rw-r--r--Tests/RunCMake/CPack/CPackTestHelpers.cmake6
-rw-r--r--Tests/RunCMake/CPack/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CPack/VerifyResult.cmake5
-rw-r--r--Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake5
-rw-r--r--Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake9
-rw-r--r--Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt6
-rw-r--r--Tests/RunCMake/CPack/tests/THREADED/DEB-Prerequirements.cmake1
-rw-r--r--Tests/RunCMake/CPack/tests/THREADED/test.cmake2
-rw-r--r--Tests/RunCMake/CPack/tests/THREADED_ALL/DEB-Prerequirements.cmake1
-rw-r--r--Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake2
-rw-r--r--Tests/RunCMake/CTest/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/CTest/Site.cmake5
-rw-r--r--Tests/RunCMake/CTestCommandLine/BadCTestTestfile-stderr.txt4
-rw-r--r--Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake17
-rw-r--r--Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt4
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-result.txt1
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-stderr.txt1
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-result.txt1
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stderr.txt1
-rw-r--r--Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stdout.txt1
-rw-r--r--Tests/RunCMake/CheckModules/CMP0075-stderr.txt13
-rw-r--r--Tests/RunCMake/ClangTidy/OBJC-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/ClangTidy/OBJC-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/ClangTidy/OBJC-launch.cmake3
-rw-r--r--Tests/RunCMake/ClangTidy/OBJC.cmake3
-rw-r--r--Tests/RunCMake/ClangTidy/OBJCXX-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/ClangTidy/OBJCXX-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/ClangTidy/OBJCXX-launch.cmake3
-rw-r--r--Tests/RunCMake/ClangTidy/OBJCXX.cmake3
-rw-r--r--Tests/RunCMake/ClangTidy/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/ClangTidy/main.m4
-rw-r--r--Tests/RunCMake/ClangTidy/main.mm (renamed from Tests/Server/buildsystem1/main.cpp)1
-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/C-no-arg-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/D-no-arg-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/E_capabilities-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/E_server-arg-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_server-pipe-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_server-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/E_server-stderr.txt1
-rw-r--r--Tests/RunCMake/CommandLine/InvalidArg1-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/InvalidArg1-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/InvalidArg2-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/InvalidArg2-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake15
-rw-r--r--Tests/RunCMake/CommandLine/U-no-arg-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/W_bad-arg1-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/W_bad-arg2-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/W_bad-arg3-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/build-no-dir-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/cmake_depends-check.cmake5
-rw-r--r--Tests/RunCMake/DependencyGraph/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/ExportCompileCommands/Properties.cmake22
-rw-r--r--Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand-check.cmake32
-rw-r--r--Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand.cmake7
-rw-r--r--Tests/RunCMake/ExportCompileCommands/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/ExportCompileCommands/expected_file.c0
-rw-r--r--Tests/RunCMake/ExternalData/BadArguments-stderr.txt7
-rw-r--r--Tests/RunCMake/ExternalData/BadArguments.cmake5
-rw-r--r--Tests/RunCMake/ExternalData/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake19
-rw-r--r--Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake28
-rw-r--r--Tests/RunCMake/ExternalProject/FetchGitTags.cmake67
-rw-r--r--Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt15
-rw-r--r--Tests/RunCMake/ExternalProject/IncludeScope-Add-stderr.txt7
-rw-r--r--Tests/RunCMake/ExternalProject/IncludeScope-Add.cmake12
-rw-r--r--Tests/RunCMake/ExternalProject/IncludeScope-Add_Step-stderr.txt7
-rw-r--r--Tests/RunCMake/ExternalProject/IncludeScope-Add_Step.cmake13
-rw-r--r--Tests/RunCMake/ExternalProject/RunCMakeTest.cmake41
-rw-r--r--Tests/RunCMake/FileAPI/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-check.py2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_tgt.json8
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-check.cmake11
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-prep.cmake4
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-check.cmake11
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-prep.cmake2
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-check.cmake10
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-prep.cmake2
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1-check.py86
-rw-r--r--Tests/RunCMake/FileAPI/toolchains-v1.cmake22
-rw-r--r--Tests/RunCMake/File_Configure/AtOnly.cmake12
-rw-r--r--Tests/RunCMake/File_Configure/BadArg-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/BadArgContent-result.txt0
-rw-r--r--Tests/RunCMake/File_Configure/BadArgContent-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/BadArgContent.cmake1
-rw-r--r--Tests/RunCMake/File_Configure/BadArgOutput-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/BadArgOutput.cmake (renamed from Tests/RunCMake/File_Configure/BadArg.cmake)0
-rw-r--r--Tests/RunCMake/File_Configure/EscapeQuotes.cmake12
-rw-r--r--Tests/RunCMake/File_Configure/NewLineStyle-ValidArg.cmake11
-rw-r--r--Tests/RunCMake/File_Configure/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/File_Configure/UnrecognizedArgs-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/UnrecognizedArgs-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/UnrecognizedArgs.cmake1
-rw-r--r--Tests/RunCMake/File_Generate/CustomFilePermissions.cmake15
-rw-r--r--Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake36
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-Default.cmake35
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg.cmake7
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-NoArg-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-NoArg.cmake7
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-Unix.cmake33
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-Win32.cmake33
-rw-r--r--Tests/RunCMake/File_Generate/NoSourcePermissions.cmake10
-rw-r--r--Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake36
-rw-r--r--Tests/RunCMake/File_Generate/RunCMakeTest.cmake32
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions1-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions1-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions1.cmake5
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions2-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions2-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions2.cmake5
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions3-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions3-stderr.txt5
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions3.cmake5
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions4-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions4-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions4.cmake4
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions5-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions5-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Generate/SourcePermissions5.cmake4
-rw-r--r--Tests/RunCMake/File_Generate/UseSourcePermissions.cmake11
-rw-r--r--Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake51
-rw-r--r--Tests/RunCMake/File_Generate/VerifyContent.cmake4
-rw-r--r--Tests/RunCMake/FindOpenSSL/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/FindOpenSSL/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/FindOpenSSL/version-exact.cmake19
-rw-r--r--Tests/RunCMake/FindOpenSSL/version-range.cmake37
-rw-r--r--Tests/RunCMake/FindOpenSSL/version.cmake19
-rw-r--r--Tests/RunCMake/GNUInstallDirs/GetAbs-stderr.txt12
-rw-r--r--Tests/RunCMake/GNUInstallDirs/GetAbs.cmake11
-rw-r--r--Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/GenerateExportHeader/GEH.cmake2
-rw-r--r--Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target-check.cmake5
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target.cmake8
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target-check.cmake5
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target.cmake4
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target-check.cmake5
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target.cmake4
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt46
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt54
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest.cmake8
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTestDiscoveryMultiConfig.cmake5
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTimeout.cmake5
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTestXML.cmake5
-rw-r--r--Tests/RunCMake/GoogleTest/fake_gtest.cpp3
-rw-r--r--Tests/RunCMake/GoogleTest/xcode_sign_adhoc.cmake8
-rw-r--r--Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-NEW.cmake2
-rw-r--r--Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-OLD.cmake2
-rw-r--r--Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-WARN.cmake2
-rw-r--r--Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-common.cmake12
-rw-r--r--Tests/RunCMake/MSVCRuntimeTypeInfo/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/MSVCRuntimeTypeInfo/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt5
-rw-r--r--Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake8
-rw-r--r--Tests/RunCMake/Make/MakefileConflict.cmake5
-rw-r--r--Tests/RunCMake/Make/RunCMakeTest.cmake9
-rw-r--r--Tests/RunCMake/Make/TargetMessages-OFF-build-check.cmake3
-rw-r--r--Tests/RunCMake/Make/TargetMessages-OFF-build-stdout.txt6
-rw-r--r--Tests/RunCMake/Make/TargetMessages-ON-build-check.cmake3
-rw-r--r--Tests/RunCMake/Make/TargetMessages-ON-build-stdout.txt9
-rw-r--r--Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-check.cmake3
-rw-r--r--Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-stdout.txt6
-rw-r--r--Tests/RunCMake/Make/TargetMessages-VAR-ON-build-check.cmake3
-rw-r--r--Tests/RunCMake/Make/TargetMessages-VAR-ON-build-stdout.txt9
-rw-r--r--Tests/RunCMake/Make/TargetMessages-validation.cmake10
-rw-r--r--Tests/RunCMake/Ninja/AssumedSources.cmake1
-rw-r--r--Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake4
-rw-r--r--Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt4
-rw-r--r--Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt4
-rw-r--r--Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Ninja/RunCMakeTest.cmake13
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-again-ninja-check.cmake (renamed from Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake)0
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-result.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-stderr.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-result.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-stderr.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-result.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-stderr.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-result.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-stderr.txt1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt5
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-in-release-graph-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-ninja-stdout.txt4
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake167
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake6
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/Qt5.cmake3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake107
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/Simple-targets-debug-ninja-stdout.txt3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/Simple-targets-default-ninja-stdout.txt3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/Simple-targets-release-ninja-stdout.txt3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/echo.c21
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake15
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake13
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake6
-rw-r--r--Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake29
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-7.3.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-PGI-18.10.1.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-12.1.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-16.1.0.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-CLANG.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-10.1.168-XLClang-v.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CUDA-NVIDIA-9.2.148-GCC.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-Intel-18.0.0.20170811.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-PGI-18.10.1.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-12.1.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-XL-16.1.0.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-7.3.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-PGI-18.10.1.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-XL-14.1.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-PGI-18.10.1.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-XL-12.1.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-PGI-18.10.1.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-Fortran-PGI-18.10.1.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc_i-C-XL-12.1.0.output1
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/results/linux_pgf77-Fortran-PGI-18.10.1.output1
-rw-r--r--Tests/RunCMake/Policy/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/Policy/InvalidMaxVersion-result.txt1
-rw-r--r--Tests/RunCMake/Policy/InvalidMaxVersion-stderr.txt5
-rw-r--r--Tests/RunCMake/Policy/InvalidMaxVersion.cmake5
-rw-r--r--Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-result.txt0
-rw-r--r--Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-stderr.txt5
-rw-r--r--Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven.cmake1
-rw-r--r--Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-result.txt1
-rw-r--r--Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-stderr.txt5
-rw-r--r--Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven.cmake1
-rw-r--r--Tests/RunCMake/Policy/InvalidVersion-result.txt0
-rw-r--r--Tests/RunCMake/Policy/InvalidVersion-stderr.txt5
-rw-r--r--Tests/RunCMake/Policy/InvalidVersion.cmake5
-rw-r--r--Tests/RunCMake/Policy/MinVersionLargerThanMax-result.txt1
-rw-r--r--Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt4
-rw-r--r--Tests/RunCMake/Policy/MinVersionLargerThanMax.cmake1
-rw-r--r--Tests/RunCMake/Policy/RunCMakeTest.cmake19
-rw-r--r--Tests/RunCMake/Policy/TooManyVersionsGiven-result.txt1
-rw-r--r--Tests/RunCMake/Policy/TooManyVersionsGiven-stderr.txt4
-rw-r--r--Tests/RunCMake/Policy/TooManyVersionsGiven.cmake1
-rw-r--r--Tests/RunCMake/Policy/VersionLowerThan2_4-result.txt1
-rw-r--r--Tests/RunCMake/Policy/VersionLowerThan2_4-stderr.txt6
-rw-r--r--Tests/RunCMake/Policy/VersionLowerThan2_4.cmake1
-rw-r--r--Tests/RunCMake/Policy/VersionNotGiven-result.txt1
-rw-r--r--Tests/RunCMake/Policy/VersionNotGiven-stderr.txt4
-rw-r--r--Tests/RunCMake/Policy/VersionNotGiven.cmake1
-rw-r--r--Tests/RunCMake/Policy/VeryHighVersion-result.txt1
-rw-r--r--Tests/RunCMake/Policy/VeryHighVersion-stderr.txt7
-rw-r--r--Tests/RunCMake/Policy/VeryHighVersion.cmake1
-rw-r--r--Tests/RunCMake/PrecompileHeaders/CXXnotC.cmake15
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake131
-rw-r--r--Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/PrecompileHeaders/include/cxx_pch.h1
-rw-r--r--Tests/RunCMake/PrecompileHeaders/no_pch.c7
-rw-r--r--Tests/RunCMake/PrecompileHeaders/use_pch.cxx9
-rw-r--r--Tests/RunCMake/RunCMake.cmake5
-rw-r--r--Tests/RunCMake/Syntax/FunctionUnmatched-stderr.txt10
-rw-r--r--Tests/RunCMake/Syntax/FunctionUnmatchedForeach-stderr.txt10
-rw-r--r--Tests/RunCMake/Syntax/ImproperNesting-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/ImproperNesting-stderr.txt4
-rw-r--r--Tests/RunCMake/Syntax/ImproperNesting.cmake7
-rw-r--r--Tests/RunCMake/Syntax/MacroUnmatched-stderr.txt10
-rw-r--r--Tests/RunCMake/Syntax/MacroUnmatchedForeach-stderr.txt10
-rw-r--r--Tests/RunCMake/Syntax/NameWithSpaces-stderr.txt2
-rw-r--r--Tests/RunCMake/Syntax/NameWithTabs-stderr.txt2
-rw-r--r--Tests/RunCMake/Syntax/Override.cmake6
-rw-r--r--Tests/RunCMake/Syntax/OverrideBreak-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideContinue-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideElse-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideElseIf-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideEndForeach-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideEndFunction-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideEndIf-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideEndMacro-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideEndWhile-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideForeach-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideFunction-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideIf-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideMacro-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideReturn-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/OverrideWhile-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/ParenInENV-stderr.txt4
-rw-r--r--Tests/RunCMake/Syntax/RunCMakeTest.cmake28
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedBrace0-stderr.txt2
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedBrace1-stderr.txt2
-rw-r--r--Tests/RunCMake/TargetObjects/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/TargetObjects/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-result.txt1
-rw-r--r--Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt10
-rw-r--r--Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake12
-rw-r--r--Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt1
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetCheckProperty.cmake16
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetGenx.cmake2
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-result.txt1
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-stderr.txt4
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources.cmake2
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetPrivateSources.cmake2
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-result.txt1
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-stderr.txt4
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetPublicSources.cmake2
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetSources-result.txt1
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetSources-stderr.txt4
-rw-r--r--Tests/RunCMake/TargetSources/AddCustomTargetSources.cmake2
-rw-r--r--Tests/RunCMake/TargetSources/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/ToolchainFile/CheckLanguage-stdout.txt1
-rw-r--r--Tests/RunCMake/ToolchainFile/CheckLanguage-toolchain.cmake4
-rw-r--r--Tests/RunCMake/ToolchainFile/CheckLanguage.cmake2
-rw-r--r--Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake21
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-unix.d6
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-unix.d.txt8
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt6
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-windows.d6
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-windows.d.txt8
-rw-r--r--Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt6
-rw-r--r--Tests/RunCMake/TransformDepfile/empty.d0
-rw-r--r--Tests/RunCMake/TransformDepfile/empty.d.txt0
-rw-r--r--Tests/RunCMake/TransformDepfile/empty.tlog.txt0
-rw-r--r--Tests/RunCMake/TransformDepfile/gccdepfile.cmake16
-rw-r--r--Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt (renamed from Tests/RunCMake/CommandLine/E_server-pipe-result.txt)0
-rw-r--r--Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt1
-rw-r--r--Tests/RunCMake/TransformDepfile/invalid.d1
-rw-r--r--Tests/RunCMake/TransformDepfile/noexist.d.txt0
-rw-r--r--Tests/RunCMake/TransformDepfile/noexist.tlog.txt0
-rw-r--r--Tests/RunCMake/TransformDepfile/vstlog.cmake16
-rw-r--r--Tests/RunCMake/UnityBuild/RunCMakeTest.cmake12
-rw-r--r--Tests/RunCMake/UnityBuild/f.cxx5
-rw-r--r--Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake10
-rw-r--r--Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake11
-rw-r--r--Tests/RunCMake/UnityBuild/unitybuild_anon_ns_group_mode.cmake19
-rw-r--r--Tests/RunCMake/UnityBuild/unitybuild_anon_ns_no_unity_build.cmake11
-rw-r--r--Tests/RunCMake/UnityBuild/unitybuild_anon_ns_test_files.cmake31
-rw-r--r--Tests/RunCMake/VS10Project/CustomCommandGenex-check.cmake37
-rw-r--r--Tests/RunCMake/VS10Project/CustomCommandGenex.cmake21
-rw-r--r--Tests/RunCMake/VS10Project/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-result.txt1
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-stderr.txt6
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct.cmake2
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-result.txt1
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-stderr.txt6
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW.cmake2
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD-Direct.cmake2
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD.cmake2
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct-stderr.txt9
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct.cmake2
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-stderr.txt18
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN.cmake2
-rw-r--r--Tests/RunCMake/WriteCompilerDetectionHeader/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake14
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake7
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake3
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake14
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake7
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake3
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake14
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake8
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake2
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake43
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/func.m6
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/main.m6
-rw-r--r--Tests/RunCMake/XcodeProject/RunCMakeTest.cmake30
-rw-r--r--Tests/RunCMake/XcodeProject/SearchPaths-check.cmake76
-rw-r--r--Tests/RunCMake/XcodeProject/SearchPaths.cmake21
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeObjectLibsInTwoProjects.cmake5
-rw-r--r--Tests/RunCMake/XcodeProject/subproject_two_object_libs/CMakeLists.txt31
-rw-r--r--Tests/RunCMake/XcodeProject/subproject_two_object_libs/dummy.cpp5
-rw-r--r--Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt2
-rw-r--r--Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt53
-rw-r--r--Tests/RunCMake/add_custom_command/BadByproduct.cmake3
-rw-r--r--Tests/RunCMake/add_custom_command/BadCommand-result.txt1
-rw-r--r--Tests/RunCMake/add_custom_command/BadCommand-stderr.txt21
-rw-r--r--Tests/RunCMake/add_custom_command/BadCommand.cmake3
-rw-r--r--Tests/RunCMake/add_custom_command/BadOutput-stderr.txt53
-rw-r--r--Tests/RunCMake/add_custom_command/BadOutput.cmake3
-rw-r--r--Tests/RunCMake/add_custom_command/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt53
-rw-r--r--Tests/RunCMake/add_custom_target/BadByproduct.cmake3
-rw-r--r--Tests/RunCMake/add_custom_target/BadCommand-result.txt1
-rw-r--r--Tests/RunCMake/add_custom_target/BadCommand-stderr.txt21
-rw-r--r--Tests/RunCMake/add_custom_target/BadCommand.cmake4
-rw-r--r--Tests/RunCMake/add_custom_target/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/add_library/CMP0073-stderr.txt10
-rw-r--r--Tests/RunCMake/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-invalid-arg-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-no-arg-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/APPEND_STRING-wrong-path-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/APPEND_STRING.cmake (renamed from Tests/RunCMake/cmake_path/CONCAT.cmake)6
-rw-r--r--Tests/RunCMake/cmake_path/COMPARE.cmake8
-rw-r--r--Tests/RunCMake/cmake_path/GET-RELATIVE_PART-invalid-output-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/GET-RELATIVE_PART-missing-output-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/GET-RELATIVE_PART-unexpected-arg-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/GET-RELATIVE_PART-wrong-path-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/GET.cmake12
-rw-r--r--Tests/RunCMake/cmake_path/HASH.cmake5
-rw-r--r--Tests/RunCMake/cmake_path/HAS_ITEM.cmake20
-rw-r--r--Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-invalid-output-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-missing-output-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-unexpected-arg-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-wrong-path-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/IS_PREFIX.cmake5
-rw-r--r--Tests/RunCMake/cmake_path/PROXIMATE_PATH.cmake41
-rw-r--r--Tests/RunCMake/cmake_path/RunCMakeTest.cmake46
-rw-r--r--Tests/RunCMake/cmake_path/SET-missing-output-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/SET-unexpected-arg-result.txt1
-rw-r--r--Tests/RunCMake/cmake_path/SET.cmake (renamed from Tests/RunCMake/cmake_path/CMAKE_PATH.cmake)18
-rw-r--r--Tests/RunCMake/configure_file/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissions-result.txt0
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissions-stderr.txt0
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissions.cmake34
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-result.txt1
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-stderr.txt5
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1.cmake5
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-result.txt1
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-stderr.txt5
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2.cmake5
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-result.txt1
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-stderr.txt5
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3.cmake5
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-result.txt1
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-stderr.txt4
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4.cmake4
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-result.txt1
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-stderr.txt4
-rw-r--r--Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5.cmake6
-rw-r--r--Tests/RunCMake/configure_file/UseSourcePermissions.cmake40
-rw-r--r--Tests/RunCMake/configure_file/sourcefile.txt1
-rw-r--r--Tests/RunCMake/ctest_submit/CTestConfig.cmake.in4
-rw-r--r--Tests/RunCMake/file-RPATH/Common.cmake (renamed from Tests/CMakeTests/ELFTest.cmake.in)13
-rw-r--r--Tests/RunCMake/file-RPATH/ELF.cmake9
-rwxr-xr-x[-rw-r--r--]Tests/RunCMake/file-RPATH/ELF/elf32lsb.bin (renamed from Tests/CMakeTests/ELF/elf32lsb.bin)bin2824 -> 2824 bytes
-rwxr-xr-x[-rw-r--r--]Tests/RunCMake/file-RPATH/ELF/elf32msb.bin (renamed from Tests/CMakeTests/ELF/elf32msb.bin)bin17984 -> 17984 bytes
-rwxr-xr-x[-rw-r--r--]Tests/RunCMake/file-RPATH/ELF/elf64lsb.bin (renamed from Tests/CMakeTests/ELF/elf64lsb.bin)bin4320 -> 4320 bytes
-rwxr-xr-x[-rw-r--r--]Tests/RunCMake/file-RPATH/ELF/elf64msb.bin (renamed from Tests/CMakeTests/ELF/elf64msb.bin)bin18704 -> 18704 bytes
-rw-r--r--Tests/RunCMake/file-RPATH/RunCMakeTest.cmake9
-rw-r--r--Tests/RunCMake/file-RPATH/XCOFF.cmake7
-rw-r--r--Tests/RunCMake/file-RPATH/XCOFF/xcoff32.binbin0 -> 1706 bytes
-rw-r--r--Tests/RunCMake/file-RPATH/XCOFF/xcoff64.binbin0 -> 2291 bytes
-rw-r--r--Tests/RunCMake/get_property/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_empty-result.txt1
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_empty-stderr.txt4
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_empty.cmake1
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_missing-result.txt1
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_missing-stderr.txt4
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_missing.cmake1
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_missingWithDir-result.txt1
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_missingWithDir-stderr.txt4
-rw-r--r--Tests/RunCMake/get_property/get_directory_property_missingWithDir.cmake1
-rw-r--r--Tests/RunCMake/if/duplicate-deep-else-stderr.txt6
-rw-r--r--Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt6
-rw-r--r--Tests/RunCMake/if/duplicate-else-stderr.txt6
-rw-r--r--Tests/RunCMake/if/misplaced-elseif-stderr.txt6
-rw-r--r--Tests/RunCMake/include/ExportExportInclude-stderr.txt2
-rw-r--r--Tests/RunCMake/include/IncludeIsDirectory-result.txt1
-rw-r--r--Tests/RunCMake/include/IncludeIsDirectory-stderr.txt6
-rw-r--r--Tests/RunCMake/include/IncludeIsDirectory.cmake1
-rw-r--r--Tests/RunCMake/include/IncludeMalformed-result.txt1
-rw-r--r--Tests/RunCMake/include/IncludeMalformed-stderr.txt13
-rw-r--r--Tests/RunCMake/include/IncludeMalformed.cmake1
-rw-r--r--Tests/RunCMake/include/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/include/malformedInclude.cmake1
-rw-r--r--Tests/RunCMake/install/FILES-RENAME-all-check.cmake1
-rw-r--r--Tests/RunCMake/install/FILES-RENAME-bad-result.txt1
-rw-r--r--Tests/RunCMake/install/FILES-RENAME-bad-stderr.txt6
-rw-r--r--Tests/RunCMake/install/FILES-RENAME-bad.cmake4
-rw-r--r--Tests/RunCMake/install/FILES-RENAME.cmake4
-rw-r--r--Tests/RunCMake/install/RunCMakeTest.cmake15
-rw-r--r--Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake2
-rw-r--r--Tests/RunCMake/list/REMOVE_ITEM-NoItemArg.cmake5
-rw-r--r--Tests/RunCMake/list/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt4
-rw-r--r--Tests/RunCMake/pseudo_llvm-rc.c30
-rw-r--r--Tests/RunCMake/separate_arguments/ProgramCommand.cmake2
-rw-r--r--Tests/RunCMake/separate_arguments/ProgramCommandWithSeparateArgs.cmake2
-rw-r--r--Tests/RunCMake/target_include_directories/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/target_include_directories/include_after.cmake18
-rw-r--r--Tests/RunCMake/target_include_directories/include_before.cmake18
-rw-r--r--Tests/RunCMake/target_include_directories/include_default.cmake18
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx17
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake9
-rw-r--r--Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c12
-rw-r--r--Tests/RunCMake/try_run/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/try_run/WorkingDirArg.cmake9
-rw-r--r--Tests/RunCMake/while/EndAlone-stderr.txt7
-rw-r--r--Tests/RunCMake/while/EndAloneArgs-stderr.txt7
-rw-r--r--Tests/RunCMake/while/EndMissing-stderr.txt10
-rw-r--r--Tests/RunCMake/while/MissingArgument-stderr.txt11
-rw-r--r--Tests/RunCMake/while/MissingArgument.cmake1
-rw-r--r--Tests/Server/CMakeLists.txt28
-rw-r--r--Tests/Server/buildsystem1/CMakeLists.txt22
-rw-r--r--Tests/Server/buildsystem1/subdir/CMakeLists.txt5
-rw-r--r--Tests/Server/cmakelib.py380
-rw-r--r--Tests/Server/server-test.py105
-rw-r--r--Tests/Server/tc_buildsystem1.json27
-rw-r--r--Tests/Server/tc_cache.json24
-rw-r--r--Tests/Server/tc_globalSettings.json140
-rw-r--r--Tests/Server/tc_handshake.json75
-rw-r--r--Tests/SetLang/CMakeLists.txt8
-rw-r--r--Tests/SetLang/bar.c14
-rw-r--r--Tests/SetLang/zoom.zzz7
-rw-r--r--Tests/UseSWIG/BasicPerl/CMakeLists.txt2
-rw-r--r--Tests/UseSWIG/BasicPython/CMakeLists.txt2
-rw-r--r--Tests/UseSWIG/CMakeLists.txt24
-rw-r--r--Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt4
-rw-r--r--Tests/VSMidl/CMakeLists.txt2
-rw-r--r--Tests/VSMidl/src/CMakeLists.txt2
-rw-r--r--Tests/VSWinStorePhone/CMakeLists.txt4
-rw-r--r--Utilities/Doxygen/CMakeLists.txt2
-rw-r--r--Utilities/Release/README.rst17
-rwxr-xr-xUtilities/Release/files-sign.bash5
-rw-r--r--Utilities/Release/files-v1.json.in106
-rw-r--r--Utilities/Release/files-v1.rst166
-rwxr-xr-xUtilities/Release/files.bash84
-rw-r--r--Utilities/Release/linux/aarch64/Dockerfile4
-rw-r--r--Utilities/Release/linux/aarch64/cache.txt2
-rw-r--r--Utilities/Release/linux/x86_64/Dockerfile4
-rw-r--r--Utilities/Release/linux/x86_64/cache.txt2
-rw-r--r--Utilities/Release/win/x86/cache-i386.txt2
-rw-r--r--Utilities/Release/win/x86/cache-x86_64.txt2
-rwxr-xr-xUtilities/Scripts/regenerate-parsers.bash7
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rw-r--r--Utilities/Sphinx/CMakeLists.txt2
-rw-r--r--Utilities/Sphinx/cmake.py21
-rw-r--r--Utilities/Sphinx/conf.py.in1
-rwxr-xr-xUtilities/Sphinx/create_identifiers.py1
-rw-r--r--Utilities/Sphinx/static/cmake.css6
-rw-r--r--Utilities/cmbzip2/CMakeLists.txt2
-rw-r--r--Utilities/cmcurl/CMake/CMakeConfigurableFile.in2
-rw-r--r--Utilities/cmcurl/CMake/CurlSymbolHiding.cmake4
-rw-r--r--Utilities/cmcurl/CMake/CurlTests.c4
-rw-r--r--Utilities/cmcurl/CMake/FindBearSSL.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindBrotli.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindCARES.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindGSS.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindLibSSH2.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindMbedTLS.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNGHTTP2.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNGHTTP3.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNGTCP2.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNSS.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindQUICHE.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindWolfSSL.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindZstd.cmake2
-rw-r--r--Utilities/cmcurl/CMake/Macros.cmake13
-rw-r--r--Utilities/cmcurl/CMake/OtherTests.cmake2
-rw-r--r--Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake2
-rw-r--r--Utilities/cmcurl/CMake/Utilities.cmake2
-rw-r--r--Utilities/cmcurl/CMake/cmake_uninstall.cmake.in2
-rw-r--r--Utilities/cmcurl/CMake/curl-config.cmake.in2
-rw-r--r--Utilities/cmcurl/CMakeLists.txt115
-rw-r--r--Utilities/cmcurl/COPYING2
-rw-r--r--Utilities/cmcurl/include/curl/curl.h207
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h8
-rw-r--r--Utilities/cmcurl/include/curl/easy.h2
-rw-r--r--Utilities/cmcurl/include/curl/mprintf.h4
-rw-r--r--Utilities/cmcurl/include/curl/multi.h2
-rw-r--r--Utilities/cmcurl/include/curl/options.h68
-rw-r--r--Utilities/cmcurl/include/curl/stdcheaders.h4
-rw-r--r--Utilities/cmcurl/include/curl/system.h4
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h9
-rw-r--r--Utilities/cmcurl/include/curl/urlapi.h4
-rw-r--r--Utilities/cmcurl/lib/CMakeLists.txt13
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc353
-rw-r--r--Utilities/cmcurl/lib/altsvc.c36
-rw-r--r--Utilities/cmcurl/lib/altsvc.h13
-rw-r--r--Utilities/cmcurl/lib/amigaos.c4
-rw-r--r--Utilities/cmcurl/lib/amigaos.h4
-rw-r--r--Utilities/cmcurl/lib/arpa_telnet.h4
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c167
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c160
-rw-r--r--Utilities/cmcurl/lib/asyn.h16
-rw-r--r--Utilities/cmcurl/lib/base64.c7
-rw-r--r--Utilities/cmcurl/lib/c-hyper.c908
-rw-r--r--Utilities/cmcurl/lib/c-hyper.h56
-rw-r--r--Utilities/cmcurl/lib/conncache.c79
-rw-r--r--Utilities/cmcurl/lib/conncache.h48
-rw-r--r--Utilities/cmcurl/lib/connect.c337
-rw-r--r--Utilities/cmcurl/lib/connect.h25
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c178
-rw-r--r--Utilities/cmcurl/lib/content_encoding.h16
-rw-r--r--Utilities/cmcurl/lib/cookie.c13
-rw-r--r--Utilities/cmcurl/lib/cookie.h8
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c6
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.h2
-rw-r--r--Utilities/cmcurl/lib/curl_base64.h4
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake26
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.c4
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.h4
-rw-r--r--Utilities/cmcurl/lib/curl_des.c4
-rw-r--r--Utilities/cmcurl/lib/curl_des.h4
-rw-r--r--Utilities/cmcurl/lib/curl_endian.c4
-rw-r--r--Utilities/cmcurl/lib/curl_endian.h4
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.c4
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.h4
-rw-r--r--Utilities/cmcurl/lib/curl_get_line.c9
-rw-r--r--Utilities/cmcurl/lib/curl_get_line.h4
-rw-r--r--Utilities/cmcurl/lib/curl_gethostname.c6
-rw-r--r--Utilities/cmcurl/lib/curl_gethostname.h6
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c8
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.h4
-rw-r--r--Utilities/cmcurl/lib/curl_hmac.h2
-rw-r--r--Utilities/cmcurl/lib/curl_krb5.h (renamed from Utilities/cmcurl/lib/curl_sec.h)20
-rw-r--r--Utilities/cmcurl/lib/curl_ldap.h4
-rw-r--r--Utilities/cmcurl/lib/curl_md4.h2
-rw-r--r--Utilities/cmcurl/lib/curl_md5.h2
-rw-r--r--Utilities/cmcurl/lib/curl_memory.h4
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.c4
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.h4
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.c2
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.h2
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c18
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.h10
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c31
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.h10
-rw-r--r--Utilities/cmcurl/lib/curl_path.c15
-rw-r--r--Utilities/cmcurl/lib/curl_path.h6
-rw-r--r--Utilities/cmcurl/lib/curl_printf.h4
-rw-r--r--Utilities/cmcurl/lib/curl_range.c7
-rw-r--r--Utilities/cmcurl/lib/curl_range.h7
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.c56
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.h4
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c38
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.h16
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h36
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h2
-rw-r--r--Utilities/cmcurl/lib/curl_sha256.h5
-rw-r--r--Utilities/cmcurl/lib/curl_sspi.c2
-rw-r--r--Utilities/cmcurl/lib/curl_sspi.h4
-rw-r--r--Utilities/cmcurl/lib/curl_threads.c8
-rw-r--r--Utilities/cmcurl/lib/curl_threads.h4
-rw-r--r--Utilities/cmcurl/lib/curlx.h2
-rw-r--r--Utilities/cmcurl/lib/dict.c104
-rw-r--r--Utilities/cmcurl/lib/dict.h4
-rw-r--r--Utilities/cmcurl/lib/doh.c107
-rw-r--r--Utilities/cmcurl/lib/doh.h8
-rw-r--r--Utilities/cmcurl/lib/dotdot.c2
-rw-r--r--Utilities/cmcurl/lib/dotdot.h4
-rw-r--r--Utilities/cmcurl/lib/dynbuf.c50
-rw-r--r--Utilities/cmcurl/lib/dynbuf.h27
-rw-r--r--Utilities/cmcurl/lib/easy.c92
-rw-r--r--Utilities/cmcurl/lib/easygetopt.c96
-rw-r--r--Utilities/cmcurl/lib/easyif.h2
-rw-r--r--Utilities/cmcurl/lib/easyoptions.c354
-rw-r--r--Utilities/cmcurl/lib/easyoptions.h35
-rw-r--r--Utilities/cmcurl/lib/escape.c4
-rw-r--r--Utilities/cmcurl/lib/escape.h2
-rw-r--r--Utilities/cmcurl/lib/file.c111
-rw-r--r--Utilities/cmcurl/lib/file.h4
-rw-r--r--Utilities/cmcurl/lib/fileinfo.c4
-rw-r--r--Utilities/cmcurl/lib/fileinfo.h6
-rw-r--r--Utilities/cmcurl/lib/formdata.c2
-rw-r--r--Utilities/cmcurl/lib/formdata.h12
-rw-r--r--Utilities/cmcurl/lib/ftp.c1404
-rw-r--r--Utilities/cmcurl/lib/ftp.h17
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c38
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.h4
-rw-r--r--Utilities/cmcurl/lib/getenv.c2
-rw-r--r--Utilities/cmcurl/lib/getinfo.c7
-rw-r--r--Utilities/cmcurl/lib/getinfo.h4
-rw-r--r--Utilities/cmcurl/lib/gopher.c76
-rw-r--r--Utilities/cmcurl/lib/gopher.h7
-rw-r--r--Utilities/cmcurl/lib/hash.c86
-rw-r--r--Utilities/cmcurl/lib/hash.h50
-rw-r--r--Utilities/cmcurl/lib/hmac.c2
-rw-r--r--Utilities/cmcurl/lib/hostasyn.c22
-rw-r--r--Utilities/cmcurl/lib/hostcheck.c4
-rw-r--r--Utilities/cmcurl/lib/hostcheck.h4
-rw-r--r--Utilities/cmcurl/lib/hostip.c118
-rw-r--r--Utilities/cmcurl/lib/hostip.h35
-rw-r--r--Utilities/cmcurl/lib/hostip4.c13
-rw-r--r--Utilities/cmcurl/lib/hostip6.c32
-rw-r--r--Utilities/cmcurl/lib/hostsyn.c4
-rw-r--r--Utilities/cmcurl/lib/hsts.c522
-rw-r--r--Utilities/cmcurl/lib/hsts.h65
-rw-r--r--Utilities/cmcurl/lib/http.c2491
-rw-r--r--Utilities/cmcurl/lib/http.h90
-rw-r--r--Utilities/cmcurl/lib/http2.c367
-rw-r--r--Utilities/cmcurl/lib/http2.h17
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.c394
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.h29
-rw-r--r--Utilities/cmcurl/lib/http_chunks.c45
-rw-r--r--Utilities/cmcurl/lib/http_chunks.h23
-rw-r--r--Utilities/cmcurl/lib/http_digest.c12
-rw-r--r--Utilities/cmcurl/lib/http_digest.h9
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c25
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.h11
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c36
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.h8
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c412
-rw-r--r--Utilities/cmcurl/lib/http_proxy.h8
-rw-r--r--Utilities/cmcurl/lib/idn_win32.c2
-rw-r--r--Utilities/cmcurl/lib/if2ip.c2
-rw-r--r--Utilities/cmcurl/lib/if2ip.h4
-rw-r--r--Utilities/cmcurl/lib/imap.c511
-rw-r--r--Utilities/cmcurl/lib/imap.h7
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.h4
-rw-r--r--Utilities/cmcurl/lib/inet_pton.c4
-rw-r--r--Utilities/cmcurl/lib/inet_pton.h4
-rw-r--r--Utilities/cmcurl/lib/krb5.c607
-rw-r--r--Utilities/cmcurl/lib/ldap.c150
-rw-r--r--Utilities/cmcurl/lib/libcurl.rc8
-rw-r--r--Utilities/cmcurl/lib/llist.c14
-rw-r--r--Utilities/cmcurl/lib/llist.h30
-rw-r--r--Utilities/cmcurl/lib/md4.c2
-rw-r--r--Utilities/cmcurl/lib/md5.c2
-rw-r--r--Utilities/cmcurl/lib/memdebug.c53
-rw-r--r--Utilities/cmcurl/lib/memdebug.h2
-rw-r--r--Utilities/cmcurl/lib/mime.c5
-rw-r--r--Utilities/cmcurl/lib/mime.h6
-rw-r--r--Utilities/cmcurl/lib/mprintf.c57
-rw-r--r--Utilities/cmcurl/lib/mqtt.c189
-rw-r--r--Utilities/cmcurl/lib/mqtt.h4
-rw-r--r--Utilities/cmcurl/lib/multi.c311
-rw-r--r--Utilities/cmcurl/lib/multihandle.h24
-rw-r--r--Utilities/cmcurl/lib/multiif.h6
-rw-r--r--Utilities/cmcurl/lib/netrc.c4
-rw-r--r--Utilities/cmcurl/lib/netrc.h4
-rw-r--r--Utilities/cmcurl/lib/non-ascii.c4
-rw-r--r--Utilities/cmcurl/lib/non-ascii.h4
-rw-r--r--Utilities/cmcurl/lib/nonblock.c4
-rw-r--r--Utilities/cmcurl/lib/nonblock.h4
-rw-r--r--Utilities/cmcurl/lib/nwlib.c2
-rw-r--r--Utilities/cmcurl/lib/nwos.c4
-rw-r--r--Utilities/cmcurl/lib/openldap.c102
-rw-r--r--Utilities/cmcurl/lib/parsedate.c59
-rw-r--r--Utilities/cmcurl/lib/parsedate.h4
-rw-r--r--Utilities/cmcurl/lib/pingpong.c127
-rw-r--r--Utilities/cmcurl/lib/pingpong.h48
-rw-r--r--Utilities/cmcurl/lib/pop3.c374
-rw-r--r--Utilities/cmcurl/lib/pop3.h8
-rw-r--r--Utilities/cmcurl/lib/progress.c37
-rw-r--r--Utilities/cmcurl/lib/progress.h10
-rw-r--r--Utilities/cmcurl/lib/psl.c4
-rw-r--r--Utilities/cmcurl/lib/psl.h4
-rw-r--r--Utilities/cmcurl/lib/quic.h19
-rw-r--r--Utilities/cmcurl/lib/rand.c4
-rw-r--r--Utilities/cmcurl/lib/rand.h4
-rw-r--r--Utilities/cmcurl/lib/rename.c6
-rw-r--r--Utilities/cmcurl/lib/rename.h2
-rw-r--r--Utilities/cmcurl/lib/rtsp.c151
-rw-r--r--Utilities/cmcurl/lib/rtsp.h10
-rw-r--r--Utilities/cmcurl/lib/security.c579
-rw-r--r--Utilities/cmcurl/lib/select.c194
-rw-r--r--Utilities/cmcurl/lib/select.h25
-rw-r--r--Utilities/cmcurl/lib/sendf.c252
-rw-r--r--Utilities/cmcurl/lib/sendf.h19
-rw-r--r--Utilities/cmcurl/lib/setopt.c335
-rw-r--r--Utilities/cmcurl/lib/setopt.h2
-rw-r--r--Utilities/cmcurl/lib/setup-os400.h2
-rw-r--r--Utilities/cmcurl/lib/setup-vms.h2
-rw-r--r--Utilities/cmcurl/lib/setup-win32.h5
-rw-r--r--Utilities/cmcurl/lib/sha256.c35
-rw-r--r--Utilities/cmcurl/lib/share.c13
-rw-r--r--Utilities/cmcurl/lib/share.h12
-rw-r--r--Utilities/cmcurl/lib/sigpipe.h4
-rw-r--r--Utilities/cmcurl/lib/slist.c4
-rw-r--r--Utilities/cmcurl/lib/slist.h4
-rw-r--r--Utilities/cmcurl/lib/smb.c276
-rw-r--r--Utilities/cmcurl/lib/smb.h11
-rw-r--r--Utilities/cmcurl/lib/smtp.c416
-rw-r--r--Utilities/cmcurl/lib/smtp.h8
-rw-r--r--Utilities/cmcurl/lib/sockaddr.h4
-rw-r--r--Utilities/cmcurl/lib/socketpair.c6
-rw-r--r--Utilities/cmcurl/lib/socketpair.h4
-rw-r--r--Utilities/cmcurl/lib/socks.c295
-rw-r--r--Utilities/cmcurl/lib/socks.h34
-rw-r--r--Utilities/cmcurl/lib/socks_gssapi.c32
-rw-r--r--Utilities/cmcurl/lib/socks_sspi.c44
-rw-r--r--Utilities/cmcurl/lib/speedcheck.c8
-rw-r--r--Utilities/cmcurl/lib/speedcheck.h4
-rw-r--r--Utilities/cmcurl/lib/splay.c10
-rw-r--r--Utilities/cmcurl/lib/splay.h16
-rw-r--r--Utilities/cmcurl/lib/strcase.c2
-rw-r--r--Utilities/cmcurl/lib/strcase.h2
-rw-r--r--Utilities/cmcurl/lib/strdup.c2
-rw-r--r--Utilities/cmcurl/lib/strdup.h4
-rw-r--r--Utilities/cmcurl/lib/strerror.c48
-rw-r--r--Utilities/cmcurl/lib/strerror.h2
-rw-r--r--Utilities/cmcurl/lib/strtok.c2
-rw-r--r--Utilities/cmcurl/lib/strtok.h4
-rw-r--r--Utilities/cmcurl/lib/strtoofft.c4
-rw-r--r--Utilities/cmcurl/lib/strtoofft.h4
-rw-r--r--Utilities/cmcurl/lib/system_win32.c15
-rw-r--r--Utilities/cmcurl/lib/system_win32.h2
-rw-r--r--Utilities/cmcurl/lib/telnet.c342
-rw-r--r--Utilities/cmcurl/lib/telnet.h4
-rw-r--r--Utilities/cmcurl/lib/tftp.c158
-rw-r--r--Utilities/cmcurl/lib/tftp.h4
-rw-r--r--Utilities/cmcurl/lib/timeval.c2
-rw-r--r--Utilities/cmcurl/lib/timeval.h4
-rw-r--r--Utilities/cmcurl/lib/transfer.c240
-rw-r--r--Utilities/cmcurl/lib/transfer.h23
-rw-r--r--Utilities/cmcurl/lib/url.c499
-rw-r--r--Utilities/cmcurl/lib/url.h28
-rw-r--r--Utilities/cmcurl/lib/urlapi-int.h6
-rw-r--r--Utilities/cmcurl/lib/urlapi.c62
-rw-r--r--Utilities/cmcurl/lib/urldata.h294
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/cram.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.c16
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.h4
-rw-r--r--Utilities/cmcurl/lib/vauth/digest_sspi.c17
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_gssapi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c3
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.h4
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/oauth2.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_gssapi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.h4
-rw-r--r--Utilities/cmcurl/lib/version.c50
-rw-r--r--Utilities/cmcurl/lib/version_win32.c2
-rw-r--r--Utilities/cmcurl/lib/version_win32.h2
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.c343
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.h9
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.c148
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.h5
-rw-r--r--Utilities/cmcurl/lib/vquic/vquic.c2
-rw-r--r--Utilities/cmcurl/lib/vquic/vquic.h2
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh.c558
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh2.c1004
-rw-r--r--Utilities/cmcurl/lib/vssh/ssh.h37
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.c249
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c140
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c116
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c253
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c154
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.c139
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.h6
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c303
-rw-r--r--Utilities/cmcurl/lib/vtls/nssg.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c556
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c291
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h15
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c23
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c183
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c202
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h76
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c179
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.h4
-rw-r--r--Utilities/cmcurl/lib/warnless.c23
-rw-r--r--Utilities/cmcurl/lib/warnless.h6
-rw-r--r--Utilities/cmcurl/lib/wildcard.c4
-rw-r--r--Utilities/cmcurl/lib/wildcard.h14
-rw-r--r--Utilities/cmcurl/lib/x509asn1.c10
-rw-r--r--Utilities/cmcurl/lib/x509asn1.h8
-rw-r--r--Utilities/cmexpat/CMakeLists.txt2
-rw-r--r--Utilities/cmjsoncpp/CMakeLists.txt2
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_reader.cpp2027
-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.txt10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_random.c8
-rw-r--r--Utilities/cmliblzma/CMakeLists.txt2
-rw-r--r--Utilities/cmlibrhash/CMakeLists.txt2
-rw-r--r--Utilities/cmlibuv/CMakeLists.txt2
-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/optional56
-rwxr-xr-xbootstrap106
2237 files changed, 57354 insertions, 31858 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 11e172632..5e513fbd1 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -4,9 +4,6 @@ bugprone-*,\
-bugprone-macro-parentheses,\
-bugprone-misplaced-widening-cast,\
-bugprone-narrowing-conversions,\
--bugprone-reserved-identifier,\
--bugprone-signed-char-misuse,\
--bugprone-suspicious-include,\
-bugprone-too-small-loop-variable,\
google-readability-casting,\
misc-*,\
@@ -20,8 +17,6 @@ modernize-*,\
-modernize-use-trailing-return-type,\
-modernize-use-transparent-functors,\
performance-*,\
--performance-no-automatic-move,\
--performance-trivially-destructible,\
readability-*,\
-readability-convert-member-functions-to-static,\
-readability-function-size,\
@@ -29,15 +24,9 @@ readability-*,\
-readability-implicit-bool-conversion,\
-readability-inconsistent-declaration-parameter-name,\
-readability-magic-numbers,\
--readability-make-member-function-const,\
-readability-named-parameter,\
--readability-qualified-auto,\
--readability-redundant-access-specifiers,\
-readability-redundant-declaration,\
--readability-redundant-string-init,\
--readability-simplify-boolean-expr,\
-readability-uppercase-literal-suffix,\
--readability-use-anyofallof,\
"
HeaderFilterRegex: 'Source/cm[^/]*\.(h|hxx|cxx)$'
CheckOptions:
diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el
index caaf0d52f..ddc7b409b 100644
--- a/Auxiliary/cmake-mode.el
+++ b/Auxiliary/cmake-mode.el
@@ -27,6 +27,9 @@
;; cmake-command-help Written by James Bigler
;;
+(require 'rst)
+(require 'rx)
+
(defcustom cmake-mode-cmake-executable "cmake"
"*The name of the cmake executable.
@@ -188,6 +191,61 @@ the indentation. Otherwise it retains the same position on the line"
)
)
+
+;------------------------------------------------------------------------------
+
+;;
+;; Navigation / marking by function or macro
+;;
+
+(defconst cmake--regex-defun-start
+ (rx line-start
+ (zero-or-more space)
+ (or "function" "macro")
+ (zero-or-more space)
+ "("))
+
+(defconst cmake--regex-defun-end
+ (rx line-start
+ (zero-or-more space)
+ "end"
+ (or "function" "macro")
+ (zero-or-more space)
+ "(" (zero-or-more (not-char ")")) ")"))
+
+(defun cmake-beginning-of-defun ()
+ "Move backward to the beginning of a CMake function or macro.
+
+Return t unless search stops due to beginning of buffer."
+ (interactive)
+ (when (not (region-active-p))
+ (push-mark))
+ (let ((case-fold-search t))
+ (when (re-search-backward cmake--regex-defun-start nil 'move)
+ t)))
+
+(defun cmake-end-of-defun ()
+ "Move forward to the end of a CMake function or macro.
+
+Return t unless search stops due to end of buffer."
+ (interactive)
+ (when (not (region-active-p))
+ (push-mark))
+ (let ((case-fold-search t))
+ (when (re-search-forward cmake--regex-defun-end nil 'move)
+ (forward-line)
+ t)))
+
+(defun cmake-mark-defun ()
+ "Mark the current CMake function or macro.
+
+This puts the mark at the end, and point at the beginning."
+ (interactive)
+ (cmake-end-of-defun)
+ (push-mark nil :nomsg :activate)
+ (cmake-beginning-of-defun))
+
+
;------------------------------------------------------------------------------
;;
@@ -240,6 +298,12 @@ the indentation. Otherwise it retains the same position on the line"
; Setup comment syntax.
(set (make-local-variable 'comment-start) "#"))
+;; Default cmake-mode key bindings
+(define-key cmake-mode-map "\e\C-a" #'cmake-beginning-of-defun)
+(define-key cmake-mode-map "\e\C-e" #'cmake-end-of-defun)
+(define-key cmake-mode-map "\e\C-h" #'cmake-mark-defun)
+
+
; Help mode starts here
@@ -258,7 +322,27 @@ optional argument topic will be appended to the argument list."
(save-selected-window
(select-window (display-buffer buffer 'not-this-window))
(cmake-mode)
- (read-only-mode 1))
+ (read-only-mode 1)
+ (view-mode 1))
+ )
+ )
+
+;;;###autoload
+(defun cmake-command-run-help (type &optional topic buffer)
+ "`cmake-command-run' but rendered in `rst-mode'."
+ (interactive "s")
+ (let* ((bufname (if buffer buffer (concat "*CMake" type (if topic "-") topic "*")))
+ (buffer (if (get-buffer bufname) (get-buffer bufname) (generate-new-buffer bufname)))
+ (command (concat cmake-mode-cmake-executable " " type " " topic))
+ ;; Turn of resizing of mini-windows for shell-command.
+ (resize-mini-windows nil)
+ )
+ (shell-command command buffer)
+ (save-selected-window
+ (select-window (display-buffer buffer 'not-this-window))
+ (rst-mode)
+ (read-only-mode 1)
+ (view-mode 1))
)
)
@@ -266,7 +350,7 @@ optional argument topic will be appended to the argument list."
(defun cmake-help-list-commands ()
"Prints out a list of the cmake commands."
(interactive)
- (cmake-command-run "--help-command-list")
+ (cmake-command-run-help "--help-command-list")
)
(defvar cmake-commands '() "List of available topics for --help-command.")
@@ -292,7 +376,7 @@ and store the result as a list in LISTVAR."
(if (not (symbol-value listvar))
(let ((temp-buffer-name "*CMake Temporary*"))
(save-window-excursion
- (cmake-command-run (concat "--help-" listname "-list") nil temp-buffer-name)
+ (cmake-command-run-help (concat "--help-" listname "-list") nil temp-buffer-name)
(with-current-buffer temp-buffer-name
; FIXME: Ignore first line if it is "cmake version ..." from CMake < 3.0.
(set listvar (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n" t)))))
@@ -326,25 +410,25 @@ and store the result as a list in LISTVAR."
(defun cmake-help-command ()
"Prints out the help message for the command the cursor is on."
(interactive)
- (cmake-command-run "--help-command" (cmake-help-type "command") "*CMake Help*"))
+ (cmake-command-run-help "--help-command" (cmake-help-type "command") "*CMake Help*"))
;;;###autoload
(defun cmake-help-module ()
"Prints out the help message for the module the cursor is on."
(interactive)
- (cmake-command-run "--help-module" (cmake-help-type "module") "*CMake Help*"))
+ (cmake-command-run-help "--help-module" (cmake-help-type "module") "*CMake Help*"))
;;;###autoload
(defun cmake-help-variable ()
"Prints out the help message for the variable the cursor is on."
(interactive)
- (cmake-command-run "--help-variable" (cmake-help-type "variable") "*CMake Help*"))
+ (cmake-command-run-help "--help-variable" (cmake-help-type "variable") "*CMake Help*"))
;;;###autoload
(defun cmake-help-property ()
"Prints out the help message for the property the cursor is on."
(interactive)
- (cmake-command-run "--help-property" (cmake-help-type "property") "*CMake Help*"))
+ (cmake-command-run-help "--help-property" (cmake-help-type "property") "*CMake Help*"))
;;;###autoload
(defun cmake-help ()
@@ -367,13 +451,13 @@ and store the result as a list in LISTVAR."
(if (string= input "")
(error "No argument given")
(if (member input command-list)
- (cmake-command-run "--help-command" input "*CMake Help*")
+ (cmake-command-run-help "--help-command" input "*CMake Help*")
(if (member input variable-list)
- (cmake-command-run "--help-variable" input "*CMake Help*")
+ (cmake-command-run-help "--help-variable" input "*CMake Help*")
(if (member input module-list)
- (cmake-command-run "--help-module" input "*CMake Help*")
+ (cmake-command-run-help "--help-module" input "*CMake Help*")
(if (member input property-list)
- (cmake-command-run "--help-property" input "*CMake Help*")
+ (cmake-command-run-help "--help-property" input "*CMake Help*")
(error "Not a know help topic.") ; this really should not happen
))))))
)
diff --git a/Auxiliary/vim/extract-upper-case.pl b/Auxiliary/vim/extract-upper-case.pl
index 204b49662..11791991d 100755
--- a/Auxiliary/vim/extract-upper-case.pl
+++ b/Auxiliary/vim/extract-upper-case.pl
@@ -3,6 +3,8 @@
use strict;
use warnings;
use POSIX qw(strftime);
+use JSON;
+use File::Basename;
#my $cmake = "/home/pboettch/devel/upstream/cmake/build/bin/cmake";
my $cmake = "cmake";
@@ -96,6 +98,28 @@ close(CMAKE);
# transform all properties in a hash
my %properties = map { $_ => 1 } @properties;
+# read in manually written files
+my $modules_dir = dirname(__FILE__) . "/modules";
+opendir(DIR, $modules_dir) || die "can't opendir $modules_dir: $!";
+my @json_files = grep { /\.json$/ && -f "$modules_dir/$_" } readdir(DIR);
+closedir DIR;
+
+foreach my $file (@json_files) {
+ local $/; # Enable 'slurp' mode
+ open my $fh, "<", $modules_dir."/".$file;
+ my $json = <$fh>;
+ close $fh;
+
+ my $mod = decode_json($json);
+ foreach my $var (@{$mod->{variables}}) {
+ $variables{$var} = 1;
+ }
+
+ while (my ($cmd, $keywords) = each %{$mod->{commands}}) {
+ $keywords{$cmd} = [ sort @{$keywords} ];
+ }
+}
+
# version
open(CMAKE, "$cmake --version|");
my $version = 'unknown';
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index 2dd3174ab..955beaea1 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -1,13 +1,13 @@
" Vim syntax file
" Program: CMake - Cross-Platform Makefile Generator
-" Version: cmake version 3.14.20190529-g067a4f
+" Version: cmake version 3.19.20201028-gdab947f
" Language: CMake
" Author: Andy Cedilnik <andy.cedilnik@kitware.com>,
" Nicholas Hutchinson <nshutchinson@gmail.com>,
" Patrick Boettcher <patrick.boettcher@posteo.de>
" Maintainer: Dimitri Merejkowsky <d.merej@gmail.com>
" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
-" Last Change: 2019 May 29
+" Last Change: 2020 oct. 28
"
" Licence: The CMake license applies to this file. See
" https://cmake.org/licensing
@@ -44,7 +44,9 @@ syn keyword cmakeProperty contained
\ ADDITIONAL_CLEAN_FILES
\ ADDITIONAL_MAKE_CLEAN_FILES
\ ADVANCED
+ \ AIX_EXPORT_ALL_SYMBOLS
\ ALIASED_TARGET
+ \ ALIAS_GLOBAL
\ ALLOW_DUPLICATE_CUSTOM_TARGETS
\ ANDROID_ANT_ADDITIONAL_OPTIONS
\ ANDROID_API
@@ -79,6 +81,7 @@ syn keyword cmakeProperty contained
\ AUTOMOC_EXECUTABLE
\ AUTOMOC_MACRO_NAMES
\ AUTOMOC_MOC_OPTIONS
+ \ AUTOMOC_PATH_PREFIX
\ AUTOMOC_SOURCE_GROUP
\ AUTOMOC_TARGETS_FOLDER
\ AUTORCC
@@ -100,8 +103,8 @@ syn keyword cmakeProperty contained
\ CACHE_VARIABLES
\ CLEAN_NO_CUSTOM
\ CMAKE_CONFIGURE_DEPENDS
- \ CMAKE_CXX_KNOWN_FEATURES
\ CMAKE_CUDA_KNOWN_FEATURES
+ \ CMAKE_CXX_KNOWN_FEATURES
\ CMAKE_C_KNOWN_FEATURES
\ CMAKE_ROLE
\ COMMON_LANGUAGE_RUNTIME
@@ -123,9 +126,11 @@ syn keyword cmakeProperty contained
\ CPACK_START_MENU_SHORTCUTS
\ CPACK_WIX_ACL
\ CROSSCOMPILING_EMULATOR
+ \ CUDA_ARCHITECTURES
\ CUDA_EXTENSIONS
\ CUDA_PTX_COMPILATION
\ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_RUNTIME_LIBRARY
\ CUDA_SEPARABLE_COMPILATION
\ CUDA_STANDARD
\ CUDA_STANDARD_REQUIRED
@@ -142,8 +147,11 @@ syn keyword cmakeProperty contained
\ DEPENDS
\ DEPLOYMENT_ADDITIONAL_FILES
\ DEPLOYMENT_REMOTE_DIRECTORY
+ \ DEPRECATION
\ DISABLED
\ DISABLED_FEATURES
+ \ DISABLE_PRECOMPILE_HEADERS
+ \ DOTNET_TARGET_FRAMEWORK
\ DOTNET_TARGET_FRAMEWORK_VERSION
\ ECLIPSE_EXTRA_CPROJECT_CONTENTS
\ ECLIPSE_EXTRA_NATURES
@@ -202,6 +210,7 @@ syn keyword cmakeProperty contained
\ INCLUDE_DIRECTORIES
\ INCLUDE_REGULAR_EXPRESSION
\ INSTALL_NAME_DIR
+ \ INSTALL_REMOVE_ENVIRONMENT_RPATH
\ INSTALL_RPATH
\ INSTALL_RPATH_USE_LINK_PATH
\ INTERFACE_AUTOUIC_OPTIONS
@@ -214,11 +223,14 @@ syn keyword cmakeProperty contained
\ INTERFACE_LINK_LIBRARIES
\ INTERFACE_LINK_OPTIONS
\ INTERFACE_POSITION_INDEPENDENT_CODE
+ \ INTERFACE_PRECOMPILE_HEADERS
\ INTERFACE_SOURCES
\ INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
\ INTERPROCEDURAL_OPTIMIZATION
\ IN_TRY_COMPILE
\ IOS_INSTALL_COMBINED
+ \ ISPC_HEADER_DIRECTORY
+ \ ISPC_INSTRUCTION_SETS
\ JOB_POOLS
\ JOB_POOL_COMPILE
\ JOB_POOL_LINK
@@ -242,6 +254,8 @@ syn keyword cmakeProperty contained
\ LINK_WHAT_YOU_USE
\ LISTFILE_STACK
\ LOCATION
+ \ MACHO_COMPATIBILITY_VERSION
+ \ MACHO_CURRENT_VERSION
\ MACOSX_BUNDLE
\ MACOSX_BUNDLE_INFO_PLIST
\ MACOSX_FRAMEWORK_INFO_PLIST
@@ -255,18 +269,29 @@ syn keyword cmakeProperty contained
\ NAME
\ NO_SONAME
\ NO_SYSTEM_FROM_IMPORTED
+ \ OBJCXX_EXTENSIONS
+ \ OBJCXX_STANDARD
+ \ OBJCXX_STANDARD_REQUIRED
+ \ OBJC_EXTENSIONS
+ \ OBJC_STANDARD
+ \ OBJC_STANDARD_REQUIRED
\ OBJECT_DEPENDS
\ OBJECT_OUTPUTS
+ \ OPTIMIZE_DEPENDENCIES
\ OSX_ARCHITECTURES
\ OUTPUT_NAME
\ PACKAGES_FOUND
\ PACKAGES_NOT_FOUND
\ PARENT_DIRECTORY
\ PASS_REGULAR_EXPRESSION
+ \ PCH_INSTANTIATE_TEMPLATES
+ \ PCH_WARN_INVALID
\ PDB_NAME
\ PDB_OUTPUT_DIRECTORY
\ POSITION_INDEPENDENT_CODE
\ POST_INSTALL_SCRIPT
+ \ PRECOMPILE_HEADERS
+ \ PRECOMPILE_HEADERS_REUSE_FROM
\ PREDEFINED_TARGETS_FOLDER
\ PREFIX
\ PRE_INSTALL_SCRIPT
@@ -278,6 +303,7 @@ syn keyword cmakeProperty contained
\ REPORT_UNDEFINED_PROPERTIES
\ REQUIRED_FILES
\ RESOURCE
+ \ RESOURCE_GROUPS
\ RESOURCE_LOCK
\ RULE_LAUNCH_COMPILE
\ RULE_LAUNCH_CUSTOM
@@ -291,8 +317,10 @@ syn keyword cmakeProperty contained
\ SKIP_AUTORCC
\ SKIP_AUTOUIC
\ SKIP_BUILD_RPATH
+ \ SKIP_PRECOMPILE_HEADERS
\ SKIP_REGULAR_EXPRESSION
\ SKIP_RETURN_CODE
+ \ SKIP_UNITY_BUILD_INCLUSION
\ SOURCES
\ SOURCE_DIR
\ SOVERSION
@@ -304,6 +332,7 @@ syn keyword cmakeProperty contained
\ SYMBOLIC
\ Swift_DEPENDENCIES_FILE
\ Swift_DIAGNOSTICS_FILE
+ \ Swift_LANGUAGE_VERSION
\ Swift_MODULE_DIRECTORY
\ Swift_MODULE_NAME
\ TARGET_ARCHIVES_MAY_BE_SHARED_LIBS
@@ -315,6 +344,12 @@ syn keyword cmakeProperty contained
\ TIMEOUT
\ TIMEOUT_AFTER_MATCH
\ TYPE
+ \ UNITY_BUILD
+ \ UNITY_BUILD_BATCH_SIZE
+ \ UNITY_BUILD_CODE_AFTER_INCLUDE
+ \ UNITY_BUILD_CODE_BEFORE_INCLUDE
+ \ UNITY_BUILD_MODE
+ \ UNITY_GROUP
\ USE_FOLDERS
\ VALUE
\ VARIABLES
@@ -329,9 +364,11 @@ syn keyword cmakeProperty contained
\ VS_DEPLOYMENT_CONTENT
\ VS_DEPLOYMENT_LOCATION
\ VS_DESKTOP_EXTENSIONS_VERSION
+ \ VS_DOTNET_DOCUMENTATION_FILE
\ VS_DOTNET_REFERENCES
\ VS_DOTNET_REFERENCES_COPY_LOCAL
\ VS_DOTNET_TARGET_FRAMEWORK_VERSION
+ \ VS_DPI_AWARE
\ VS_GLOBAL_KEYWORD
\ VS_GLOBAL_PROJECT_TYPES
\ VS_GLOBAL_ROOTNAMESPACE
@@ -342,6 +379,8 @@ syn keyword cmakeProperty contained
\ VS_KEYWORD
\ VS_MOBILE_EXTENSIONS_VERSION
\ VS_NO_SOLUTION_DEPLOY
+ \ VS_PACKAGE_REFERENCES
+ \ VS_PLATFORM_TOOLSET
\ VS_PROJECT_IMPORT
\ VS_RESOURCE_GENERATOR
\ VS_SCC_AUXPATH
@@ -349,6 +388,7 @@ syn keyword cmakeProperty contained
\ VS_SCC_PROJECTNAME
\ VS_SCC_PROVIDER
\ VS_SDK_REFERENCES
+ \ VS_SETTINGS
\ VS_SHADER_DISABLE_OPTIMIZATIONS
\ VS_SHADER_ENABLE_DEBUG
\ VS_SHADER_ENTRYPOINT
@@ -358,6 +398,7 @@ syn keyword cmakeProperty contained
\ VS_SHADER_OUTPUT_HEADER_FILE
\ VS_SHADER_TYPE
\ VS_SHADER_VARIABLE_NAME
+ \ VS_SOLUTION_DEPLOY
\ VS_STARTUP_PROJECT
\ VS_TOOL_OVERRIDE
\ VS_USER_PROPS
@@ -376,11 +417,13 @@ syn keyword cmakeProperty contained
\ XCODE_FILE_ATTRIBUTES
\ XCODE_GENERATE_SCHEME
\ XCODE_LAST_KNOWN_FILE_TYPE
+ \ XCODE_LINK_BUILD_PHASE_MODE
\ XCODE_PRODUCT_TYPE
\ XCODE_SCHEME_ADDRESS_SANITIZER
\ XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
\ XCODE_SCHEME_ARGUMENTS
\ XCODE_SCHEME_DEBUG_AS_ROOT
+ \ XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING
\ XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
\ XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
\ XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
@@ -395,6 +438,7 @@ syn keyword cmakeProperty contained
\ XCODE_SCHEME_THREAD_SANITIZER_STOP
\ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
\ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ XCODE_SCHEME_WORKING_DIRECTORY
\ XCODE_SCHEME_ZOMBIE_OBJECTS
\ XCTEST
@@ -405,6 +449,7 @@ syn keyword cmakeVariable contained
\ BUILD_SHARED_LIBS
\ CACHE
\ CMAKE_ABSOLUTE_DESTINATION_FILES
+ \ CMAKE_AIX_EXPORT_ALL_SYMBOLS
\ CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS
\ CMAKE_ANDROID_API
\ CMAKE_ANDROID_API_MIN
@@ -485,6 +530,9 @@ syn keyword cmakeVariable contained
\ CMAKE_ASM_LINKER_WRAPPER_FLAG
\ CMAKE_ASM_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_ASM_LINK_EXECUTABLE
+ \ CMAKE_ASM_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_ASM_LINK_LIBRARY_FLAG
+ \ CMAKE_ASM_LINK_LIBRARY_SUFFIX
\ CMAKE_ASM_MASM
\ CMAKE_ASM_MASM_ANDROID_TOOLCHAIN_MACHINE
\ CMAKE_ASM_MASM_ANDROID_TOOLCHAIN_PREFIX
@@ -535,6 +583,9 @@ syn keyword cmakeVariable contained
\ CMAKE_ASM_MASM_LINKER_WRAPPER_FLAG
\ CMAKE_ASM_MASM_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_ASM_MASM_LINK_EXECUTABLE
+ \ CMAKE_ASM_MASM_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_ASM_MASM_LINK_LIBRARY_FLAG
+ \ CMAKE_ASM_MASM_LINK_LIBRARY_SUFFIX
\ CMAKE_ASM_MASM_OUTPUT_EXTENSION
\ CMAKE_ASM_MASM_PLATFORM_ID
\ CMAKE_ASM_MASM_SIMULATE_ID
@@ -594,6 +645,9 @@ syn keyword cmakeVariable contained
\ CMAKE_ASM_NASM_LINKER_WRAPPER_FLAG
\ CMAKE_ASM_NASM_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_ASM_NASM_LINK_EXECUTABLE
+ \ CMAKE_ASM_NASM_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_ASM_NASM_LINK_LIBRARY_FLAG
+ \ CMAKE_ASM_NASM_LINK_LIBRARY_SUFFIX
\ CMAKE_ASM_NASM_OUTPUT_EXTENSION
\ CMAKE_ASM_NASM_PLATFORM_ID
\ CMAKE_ASM_NASM_SIMULATE_ID
@@ -620,6 +674,7 @@ syn keyword cmakeVariable contained
\ CMAKE_AUTOMOC_DEPEND_FILTERS
\ CMAKE_AUTOMOC_MACRO_NAMES
\ CMAKE_AUTOMOC_MOC_OPTIONS
+ \ CMAKE_AUTOMOC_PATH_PREFIX
\ CMAKE_AUTOMOC_RELAXED_MODE
\ CMAKE_AUTORCC
\ CMAKE_AUTORCC_OPTIONS
@@ -640,6 +695,7 @@ syn keyword cmakeVariable contained
\ CMAKE_CACHE_MINOR_VERSION
\ CMAKE_CACHE_PATCH_VERSION
\ CMAKE_CFG_INTDIR
+ \ CMAKE_CLANG_VFS_OVERLAY
\ CMAKE_CL_64
\ CMAKE_CODEBLOCKS_COMPILER_ID
\ CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES
@@ -655,6 +711,7 @@ syn keyword cmakeVariable contained
\ CMAKE_CPACK_COMMAND
\ CMAKE_CROSSCOMPILING
\ CMAKE_CROSSCOMPILING_EMULATOR
+ \ CMAKE_CROSS_CONFIGS
\ CMAKE_CSharp
\ CMAKE_CSharp_ANDROID_TOOLCHAIN_MACHINE
\ CMAKE_CSharp_ANDROID_TOOLCHAIN_PREFIX
@@ -705,6 +762,9 @@ syn keyword cmakeVariable contained
\ CMAKE_CSharp_LINKER_WRAPPER_FLAG
\ CMAKE_CSharp_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_CSharp_LINK_EXECUTABLE
+ \ CMAKE_CSharp_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_CSharp_LINK_LIBRARY_FLAG
+ \ CMAKE_CSharp_LINK_LIBRARY_SUFFIX
\ CMAKE_CSharp_OUTPUT_EXTENSION
\ CMAKE_CSharp_PLATFORM_ID
\ CMAKE_CSharp_SIMULATE_ID
@@ -714,11 +774,13 @@ syn keyword cmakeVariable contained
\ CMAKE_CSharp_STANDARD_INCLUDE_DIRECTORIES
\ CMAKE_CSharp_STANDARD_LIBRARIES
\ CMAKE_CSharp_VISIBILITY_PRESET
+ \ CMAKE_CTEST_ARGUMENTS
\ CMAKE_CTEST_COMMAND
\ CMAKE_CUDA
\ CMAKE_CUDA_ANDROID_TOOLCHAIN_MACHINE
\ CMAKE_CUDA_ANDROID_TOOLCHAIN_PREFIX
\ CMAKE_CUDA_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_CUDA_ARCHITECTURES
\ CMAKE_CUDA_ARCHIVE_APPEND
\ CMAKE_CUDA_ARCHIVE_CREATE
\ CMAKE_CUDA_ARCHIVE_FINISH
@@ -728,7 +790,6 @@ syn keyword cmakeVariable contained
\ CMAKE_CUDA_COMPILER_AR
\ CMAKE_CUDA_COMPILER_ARCHITECTURE_ID
\ CMAKE_CUDA_COMPILER_EXTERNAL_TOOLCHAIN
- \ CMAKE_CUDA_COMPILE_FEATURES
\ CMAKE_CUDA_COMPILER_ID
\ CMAKE_CUDA_COMPILER_LAUNCHER
\ CMAKE_CUDA_COMPILER_LOADED
@@ -737,6 +798,7 @@ syn keyword cmakeVariable contained
\ CMAKE_CUDA_COMPILER_TARGET
\ CMAKE_CUDA_COMPILER_VERSION
\ CMAKE_CUDA_COMPILER_VERSION_INTERNAL
+ \ CMAKE_CUDA_COMPILE_FEATURES
\ CMAKE_CUDA_COMPILE_OBJECT
\ CMAKE_CUDA_CPPCHECK
\ CMAKE_CUDA_CPPLINT
@@ -768,8 +830,13 @@ syn keyword cmakeVariable contained
\ CMAKE_CUDA_LINKER_WRAPPER_FLAG
\ CMAKE_CUDA_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_CUDA_LINK_EXECUTABLE
+ \ CMAKE_CUDA_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_CUDA_LINK_LIBRARY_FLAG
+ \ CMAKE_CUDA_LINK_LIBRARY_SUFFIX
\ CMAKE_CUDA_OUTPUT_EXTENSION
\ CMAKE_CUDA_PLATFORM_ID
+ \ CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CMAKE_CUDA_RUNTIME_LIBRARY
\ CMAKE_CUDA_SEPARABLE_COMPILATION
\ CMAKE_CUDA_SIMULATE_ID
\ CMAKE_CUDA_SIMULATE_VERSION
@@ -782,6 +849,10 @@ syn keyword cmakeVariable contained
\ CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES
\ CMAKE_CUDA_VISIBILITY_PRESET
\ CMAKE_CURRENT_BINARY_DIR
+ \ CMAKE_CURRENT_FUNCTION
+ \ CMAKE_CURRENT_FUNCTION_LIST_DIR
+ \ CMAKE_CURRENT_FUNCTION_LIST_FILE
+ \ CMAKE_CURRENT_FUNCTION_LIST_LINE
\ CMAKE_CURRENT_LIST_DIR
\ CMAKE_CURRENT_LIST_FILE
\ CMAKE_CURRENT_LIST_LINE
@@ -838,6 +909,9 @@ syn keyword cmakeVariable contained
\ CMAKE_CXX_LINKER_WRAPPER_FLAG
\ CMAKE_CXX_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_CXX_LINK_EXECUTABLE
+ \ CMAKE_CXX_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_CXX_LINK_LIBRARY_FLAG
+ \ CMAKE_CXX_LINK_LIBRARY_SUFFIX
\ CMAKE_CXX_OUTPUT_EXTENSION
\ CMAKE_CXX_PLATFORM_ID
\ CMAKE_CXX_SIMULATE_ID
@@ -900,6 +974,9 @@ syn keyword cmakeVariable contained
\ CMAKE_C_LINKER_WRAPPER_FLAG
\ CMAKE_C_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_C_LINK_EXECUTABLE
+ \ CMAKE_C_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_C_LINK_LIBRARY_FLAG
+ \ CMAKE_C_LINK_LIBRARY_SUFFIX
\ CMAKE_C_OUTPUT_EXTENSION
\ CMAKE_C_PLATFORM_ID
\ CMAKE_C_SIMULATE_ID
@@ -913,9 +990,13 @@ syn keyword cmakeVariable contained
\ CMAKE_C_VISIBILITY_PRESET
\ CMAKE_DEBUG_POSTFIX
\ CMAKE_DEBUG_TARGET_PROPERTIES
+ \ CMAKE_DEFAULT_BUILD_TYPE
+ \ CMAKE_DEFAULT_CONFIGS
\ CMAKE_DEPENDS_IN_PROJECT_ONLY
\ CMAKE_DIRECTORY_LABELS
+ \ CMAKE_DISABLE_PRECOMPILE_HEADERS
\ CMAKE_DL_LIBS
+ \ CMAKE_DOTNET_TARGET_FRAMEWORK
\ CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
\ CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES
\ CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT
@@ -936,6 +1017,7 @@ syn keyword cmakeVariable contained
\ CMAKE_EXTRA_GENERATOR
\ CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES
\ CMAKE_FIND_APPBUNDLE
+ \ CMAKE_FIND_DEBUG_MODE
\ CMAKE_FIND_FRAMEWORK
\ CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX
\ CMAKE_FIND_LIBRARY_PREFIXES
@@ -960,6 +1042,7 @@ syn keyword cmakeVariable contained
\ CMAKE_FIND_USE_PACKAGE_REGISTRY
\ CMAKE_FIND_USE_PACKAGE_ROOT_PATH
\ CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH
+ \ CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY
\ CMAKE_FOLDER
\ CMAKE_FRAMEWORK
\ CMAKE_FRAMEWORK_PATH
@@ -1014,6 +1097,9 @@ syn keyword cmakeVariable contained
\ CMAKE_Fortran_LINKER_WRAPPER_FLAG
\ CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_Fortran_LINK_EXECUTABLE
+ \ CMAKE_Fortran_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_Fortran_LINK_LIBRARY_FLAG
+ \ CMAKE_Fortran_LINK_LIBRARY_SUFFIX
\ CMAKE_Fortran_MODDIR_DEFAULT
\ CMAKE_Fortran_MODDIR_FLAG
\ CMAKE_Fortran_MODOUT_FLAG
@@ -1048,7 +1134,6 @@ syn keyword cmakeVariable contained
\ CMAKE_HOST_UNIX
\ CMAKE_HOST_WIN32
\ CMAKE_IGNORE_PATH
- \ CMAKE_ISPC_HEADER_DIRECTORY
\ CMAKE_IMPORT_LIBRARY_PREFIX
\ CMAKE_IMPORT_LIBRARY_SUFFIX
\ CMAKE_INCLUDE_CURRENT_DIR
@@ -1062,11 +1147,14 @@ syn keyword cmakeVariable contained
\ CMAKE_INSTALL_NAME_DIR
\ CMAKE_INSTALL_PREFIX
\ CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
+ \ CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH
\ CMAKE_INSTALL_RPATH
\ CMAKE_INSTALL_RPATH_USE_LINK_PATH
\ CMAKE_INTERNAL_PLATFORM_ABI
\ CMAKE_INTERPROCEDURAL_OPTIMIZATION
\ CMAKE_IOS_INSTALL_COMBINED
+ \ CMAKE_ISPC_HEADER_DIRECTORY
+ \ CMAKE_ISPC_INSTRUCTION_SETS
\ CMAKE_JOB_POOLS
\ CMAKE_JOB_POOL_COMPILE
\ CMAKE_JOB_POOL_LINK
@@ -1121,6 +1209,9 @@ syn keyword cmakeVariable contained
\ CMAKE_Java_LINKER_WRAPPER_FLAG
\ CMAKE_Java_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_Java_LINK_EXECUTABLE
+ \ CMAKE_Java_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_Java_LINK_LIBRARY_FLAG
+ \ CMAKE_Java_LINK_LIBRARY_SUFFIX
\ CMAKE_Java_OUTPUT_EXTENSION
\ CMAKE_Java_PLATFORM_ID
\ CMAKE_Java_SIMULATE_ID
@@ -1151,6 +1242,10 @@ syn keyword cmakeVariable contained
\ CMAKE_MAKE_PROGRAM
\ CMAKE_MATCH_COUNT
\ CMAKE_MAXIMUM_RECURSION_DEPTH
+ \ CMAKE_MESSAGE_CONTEXT
+ \ CMAKE_MESSAGE_CONTEXT_SHOW
+ \ CMAKE_MESSAGE_INDENT
+ \ CMAKE_MESSAGE_LOG_LEVEL
\ CMAKE_MFC_FLAG
\ CMAKE_MINIMUM_REQUIRED_VERSION
\ CMAKE_MINOR_VERSION
@@ -1165,12 +1260,23 @@ syn keyword cmakeVariable contained
\ CMAKE_NOT_USING_CONFIG_FLAGS
\ CMAKE_NO_BUILTIN_CHRPATH
\ CMAKE_NO_SYSTEM_FROM_IMPORTED
+ \ CMAKE_OBJCXX_CLANG_TIDY
+ \ CMAKE_OBJCXX_EXTENSIONS
+ \ CMAKE_OBJCXX_STANDARD
+ \ CMAKE_OBJCXX_STANDARD_REQUIRED
+ \ CMAKE_OBJC_CLANG_TIDY
+ \ CMAKE_OBJC_EXTENSIONS
+ \ CMAKE_OBJC_STANDARD
+ \ CMAKE_OBJC_STANDARD_REQUIRED
\ CMAKE_OBJECT_PATH_MAX
+ \ CMAKE_OPTIMIZE_DEPENDENCIES
\ CMAKE_OSX_ARCHITECTURES
\ CMAKE_OSX_DEPLOYMENT_TARGET
\ CMAKE_OSX_SYSROOT
\ CMAKE_PARENT_LIST_FILE
\ CMAKE_PATCH_VERSION
+ \ CMAKE_PCH_INSTANTIATE_TEMPLATES
+ \ CMAKE_PCH_WARN_INVALID
\ CMAKE_PDB_OUTPUT_DIRECTORY
\ CMAKE_POSITION_INDEPENDENT_CODE
\ CMAKE_PREFIX_PATH
@@ -1236,6 +1342,9 @@ syn keyword cmakeVariable contained
\ CMAKE_RC_LINKER_WRAPPER_FLAG
\ CMAKE_RC_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_RC_LINK_EXECUTABLE
+ \ CMAKE_RC_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_RC_LINK_LIBRARY_FLAG
+ \ CMAKE_RC_LINK_LIBRARY_SUFFIX
\ CMAKE_RC_OUTPUT_EXTENSION
\ CMAKE_RC_PLATFORM_ID
\ CMAKE_RC_SIMULATE_ID
@@ -1335,7 +1444,11 @@ syn keyword cmakeVariable contained
\ CMAKE_Swift_LINKER_WRAPPER_FLAG
\ CMAKE_Swift_LINKER_WRAPPER_FLAG_SEP
\ CMAKE_Swift_LINK_EXECUTABLE
+ \ CMAKE_Swift_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_Swift_LINK_LIBRARY_FLAG
+ \ CMAKE_Swift_LINK_LIBRARY_SUFFIX
\ CMAKE_Swift_MODULE_DIRECTORY
+ \ CMAKE_Swift_NUM_THREADS
\ CMAKE_Swift_OUTPUT_EXTENSION
\ CMAKE_Swift_PLATFORM_ID
\ CMAKE_Swift_SIMULATE_ID
@@ -1350,6 +1463,8 @@ syn keyword cmakeVariable contained
\ CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
\ CMAKE_TRY_COMPILE_TARGET_TYPE
\ CMAKE_TWEAK_VERSION
+ \ CMAKE_UNITY_BUILD
+ \ CMAKE_UNITY_BUILD_BATCH_SIZE
\ CMAKE_USER_MAKE_RULES_OVERRIDE
\ CMAKE_USER_MAKE_RULES_OVERRIDE_ASM
\ CMAKE_USER_MAKE_RULES_OVERRIDE_ASM_MASM
@@ -1378,6 +1493,7 @@ syn keyword cmakeVariable contained
\ CMAKE_VS_PLATFORM_NAME_DEFAULT
\ CMAKE_VS_PLATFORM_TOOLSET
\ CMAKE_VS_PLATFORM_TOOLSET_CUDA
+ \ CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR
\ CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
\ CMAKE_VS_PLATFORM_TOOLSET_VERSION
\ CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
@@ -1388,19 +1504,24 @@ syn keyword cmakeVariable contained
\ CMAKE_VS_SDK_REFERENCE_DIRECTORIES
\ CMAKE_VS_SDK_SOURCE_DIRECTORIES
\ CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
+ \ CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM
\ CMAKE_VS_WINRT_BY_DEFAULT
\ CMAKE_WARN_DEPRECATED
\ CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
\ CMAKE_WIN32_EXECUTABLE
\ CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
+ \ CMAKE_XCODE_BUILD_SYSTEM
\ CMAKE_XCODE_GENERATE_SCHEME
\ CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY
+ \ CMAKE_XCODE_LINK_BUILD_PHASE_MODE
\ CMAKE_XCODE_PLATFORM_TOOLSET
\ CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER
\ CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+ \ CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING
\ CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
\ CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
\ CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ \ CMAKE_XCODE_SCHEME_ENVIRONMENT
\ CMAKE_XCODE_SCHEME_GUARD_MALLOC
\ CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
\ CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
@@ -1410,13 +1531,13 @@ syn keyword cmakeVariable contained
\ CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP
\ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
\ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ CMAKE_XCODE_SCHEME_WORKING_DIRECTORY
\ CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
\ CPACK_ABSOLUTE_DESTINATION_FILES
\ CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
\ CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
\ CPACK_INCLUDE_TOPLEVEL_DIRECTORY
\ CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
- \ CPACK_INSTALL_SCRIPT
\ CPACK_PACKAGING_INSTALL_PREFIX
\ CPACK_SET_DESTDIR
\ CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
@@ -1476,6 +1597,7 @@ syn keyword cmakeVariable contained
\ CTEST_P4_COMMAND
\ CTEST_P4_OPTIONS
\ CTEST_P4_UPDATE_OPTIONS
+ \ CTEST_RESOURCE_SPEC_FILE
\ CTEST_RUN_CURRENT_SCRIPT
\ CTEST_SCP_COMMAND
\ CTEST_SITE
@@ -1493,6 +1615,283 @@ syn keyword cmakeVariable contained
\ CTEST_UPDATE_VERSION_OVERRIDE
\ CTEST_USE_LAUNCHERS
\ CYGWIN
+ \ DOXYGEN_ABBREVIATE_BRIEF
+ \ DOXYGEN_ALIASES
+ \ DOXYGEN_ALLEXTERNALS
+ \ DOXYGEN_ALLOW_UNICODE_NAMES
+ \ DOXYGEN_ALPHABETICAL_INDEX
+ \ DOXYGEN_ALWAYS_DETAILED_SEC
+ \ DOXYGEN_AUTOLINK_SUPPORT
+ \ DOXYGEN_BINARY_TOC
+ \ DOXYGEN_BRIEF_MEMBER_DESC
+ \ DOXYGEN_BUILTIN_STL_SUPPORT
+ \ DOXYGEN_CALLER_GRAPH
+ \ DOXYGEN_CALL_GRAPH
+ \ DOXYGEN_CASE_SENSE_NAMES
+ \ DOXYGEN_CHM_FILE
+ \ DOXYGEN_CHM_INDEX_ENCODING
+ \ DOXYGEN_CITE_BIB_FILES
+ \ DOXYGEN_CLANG_ASSISTED_PARSING
+ \ DOXYGEN_CLANG_DATABASE_PATH
+ \ DOXYGEN_CLANG_OPTIONS
+ \ DOXYGEN_CLASS_DIAGRAMS
+ \ DOXYGEN_CLASS_GRAPH
+ \ DOXYGEN_COLLABORATION_GRAPH
+ \ DOXYGEN_COLS_IN_ALPHA_INDEX
+ \ DOXYGEN_COMPACT_LATEX
+ \ DOXYGEN_COMPACT_RTF
+ \ DOXYGEN_CPP_CLI_SUPPORT
+ \ DOXYGEN_CREATE_SUBDIRS
+ \ DOXYGEN_DIAFILE_DIRS
+ \ DOXYGEN_DIA_PATH
+ \ DOXYGEN_DIRECTORY_GRAPH
+ \ DOXYGEN_DISABLE_INDEX
+ \ DOXYGEN_DISTRIBUTE_GROUP_DOC
+ \ DOXYGEN_DOCBOOK_OUTPUT
+ \ DOXYGEN_DOCBOOK_PROGRAMLISTING
+ \ DOXYGEN_DOCSET_BUNDLE_ID
+ \ DOXYGEN_DOCSET_FEEDNAME
+ \ DOXYGEN_DOCSET_PUBLISHER_ID
+ \ DOXYGEN_DOCSET_PUBLISHER_NAME
+ \ DOXYGEN_DOTFILE_DIRS
+ \ DOXYGEN_DOT_CLEANUP
+ \ DOXYGEN_DOT_FONTNAME
+ \ DOXYGEN_DOT_FONTPATH
+ \ DOXYGEN_DOT_FONTSIZE
+ \ DOXYGEN_DOT_GRAPH_MAX_NODES
+ \ DOXYGEN_DOT_IMAGE_FORMAT
+ \ DOXYGEN_DOT_MULTI_TARGETS
+ \ DOXYGEN_DOT_NUM_THREADS
+ \ DOXYGEN_DOT_PATH
+ \ DOXYGEN_DOT_TRANSPARENT
+ \ DOXYGEN_DOXYFILE_ENCODING
+ \ DOXYGEN_ECLIPSE_DOC_ID
+ \ DOXYGEN_ENABLED_SECTIONS
+ \ DOXYGEN_ENABLE_PREPROCESSING
+ \ DOXYGEN_ENUM_VALUES_PER_LINE
+ \ DOXYGEN_EXAMPLE_PATH
+ \ DOXYGEN_EXAMPLE_PATTERNS
+ \ DOXYGEN_EXAMPLE_RECURSIVE
+ \ DOXYGEN_EXCLUDE
+ \ DOXYGEN_EXCLUDE_PATTERNS
+ \ DOXYGEN_EXCLUDE_SYMBOLS
+ \ DOXYGEN_EXCLUDE_SYMLINKS
+ \ DOXYGEN_EXPAND_AS_DEFINED
+ \ DOXYGEN_EXPAND_ONLY_PREDEF
+ \ DOXYGEN_EXTENSION_MAPPING
+ \ DOXYGEN_EXTERNAL_GROUPS
+ \ DOXYGEN_EXTERNAL_PAGES
+ \ DOXYGEN_EXTERNAL_SEARCH
+ \ DOXYGEN_EXTERNAL_SEARCH_ID
+ \ DOXYGEN_EXTRACT_ALL
+ \ DOXYGEN_EXTRACT_ANON_NSPACES
+ \ DOXYGEN_EXTRACT_LOCAL_CLASSES
+ \ DOXYGEN_EXTRACT_LOCAL_METHODS
+ \ DOXYGEN_EXTRACT_PACKAGE
+ \ DOXYGEN_EXTRACT_PRIVATE
+ \ DOXYGEN_EXTRACT_PRIV_VIRTUAL
+ \ DOXYGEN_EXTRACT_STATIC
+ \ DOXYGEN_EXTRA_PACKAGES
+ \ DOXYGEN_EXTRA_SEARCH_MAPPINGS
+ \ DOXYGEN_EXT_LINKS_IN_WINDOW
+ \ DOXYGEN_FILE_PATTERNS
+ \ DOXYGEN_FILE_VERSION_FILTER
+ \ DOXYGEN_FILTER_PATTERNS
+ \ DOXYGEN_FILTER_SOURCE_FILES
+ \ DOXYGEN_FILTER_SOURCE_PATTERNS
+ \ DOXYGEN_FORCE_LOCAL_INCLUDES
+ \ DOXYGEN_FORMULA_FONTSIZE
+ \ DOXYGEN_FORMULA_TRANSPARENT
+ \ DOXYGEN_FULL_PATH_NAMES
+ \ DOXYGEN_GENERATE_AUTOGEN_DEF
+ \ DOXYGEN_GENERATE_BUGLIST
+ \ DOXYGEN_GENERATE_CHI
+ \ DOXYGEN_GENERATE_DEPRECATEDLIST
+ \ DOXYGEN_GENERATE_DOCBOOK
+ \ DOXYGEN_GENERATE_DOCSET
+ \ DOXYGEN_GENERATE_ECLIPSEHELP
+ \ DOXYGEN_GENERATE_HTML
+ \ DOXYGEN_GENERATE_HTMLHELP
+ \ DOXYGEN_GENERATE_LATEX
+ \ DOXYGEN_GENERATE_LEGEND
+ \ DOXYGEN_GENERATE_MAN
+ \ DOXYGEN_GENERATE_PERLMOD
+ \ DOXYGEN_GENERATE_QHP
+ \ DOXYGEN_GENERATE_RTF
+ \ DOXYGEN_GENERATE_TAGFILE
+ \ DOXYGEN_GENERATE_TESTLIST
+ \ DOXYGEN_GENERATE_TODOLIST
+ \ DOXYGEN_GENERATE_TREEVIEW
+ \ DOXYGEN_GENERATE_XML
+ \ DOXYGEN_GRAPHICAL_HIERARCHY
+ \ DOXYGEN_GROUP_GRAPHS
+ \ DOXYGEN_GROUP_NESTED_COMPOUNDS
+ \ DOXYGEN_HAVE_DOT
+ \ DOXYGEN_HHC_LOCATION
+ \ DOXYGEN_HIDE_COMPOUND_REFERENCE
+ \ DOXYGEN_HIDE_FRIEND_COMPOUNDS
+ \ DOXYGEN_HIDE_IN_BODY_DOCS
+ \ DOXYGEN_HIDE_SCOPE_NAMES
+ \ DOXYGEN_HIDE_UNDOC_CLASSES
+ \ DOXYGEN_HIDE_UNDOC_MEMBERS
+ \ DOXYGEN_HIDE_UNDOC_RELATIONS
+ \ DOXYGEN_HTML_COLORSTYLE_GAMMA
+ \ DOXYGEN_HTML_COLORSTYLE_HUE
+ \ DOXYGEN_HTML_COLORSTYLE_SAT
+ \ DOXYGEN_HTML_DYNAMIC_MENUS
+ \ DOXYGEN_HTML_DYNAMIC_SECTIONS
+ \ DOXYGEN_HTML_EXTRA_FILES
+ \ DOXYGEN_HTML_EXTRA_STYLESHEET
+ \ DOXYGEN_HTML_FILE_EXTENSION
+ \ DOXYGEN_HTML_FOOTER
+ \ DOXYGEN_HTML_HEADER
+ \ DOXYGEN_HTML_INDEX_NUM_ENTRIES
+ \ DOXYGEN_HTML_OUTPUT
+ \ DOXYGEN_HTML_STYLESHEET
+ \ DOXYGEN_HTML_TIMESTAMP
+ \ DOXYGEN_IDL_PROPERTY_SUPPORT
+ \ DOXYGEN_IGNORE_PREFIX
+ \ DOXYGEN_IMAGE_PATH
+ \ DOXYGEN_INCLUDED_BY_GRAPH
+ \ DOXYGEN_INCLUDE_FILE_PATTERNS
+ \ DOXYGEN_INCLUDE_GRAPH
+ \ DOXYGEN_INCLUDE_PATH
+ \ DOXYGEN_INHERIT_DOCS
+ \ DOXYGEN_INLINE_GROUPED_CLASSES
+ \ DOXYGEN_INLINE_INFO
+ \ DOXYGEN_INLINE_INHERITED_MEMB
+ \ DOXYGEN_INLINE_SIMPLE_STRUCTS
+ \ DOXYGEN_INLINE_SOURCES
+ \ DOXYGEN_INPUT
+ \ DOXYGEN_INPUT_ENCODING
+ \ DOXYGEN_INPUT_FILTER
+ \ DOXYGEN_INTERACTIVE_SVG
+ \ DOXYGEN_INTERNAL_DOCS
+ \ DOXYGEN_JAVADOC_AUTOBRIEF
+ \ DOXYGEN_JAVADOC_BANNER
+ \ DOXYGEN_LATEX_BATCHMODE
+ \ DOXYGEN_LATEX_BIB_STYLE
+ \ DOXYGEN_LATEX_CMD_NAME
+ \ DOXYGEN_LATEX_EMOJI_DIRECTORY
+ \ DOXYGEN_LATEX_EXTRA_FILES
+ \ DOXYGEN_LATEX_EXTRA_STYLESHEET
+ \ DOXYGEN_LATEX_FOOTER
+ \ DOXYGEN_LATEX_HEADER
+ \ DOXYGEN_LATEX_HIDE_INDICES
+ \ DOXYGEN_LATEX_MAKEINDEX_CMD
+ \ DOXYGEN_LATEX_OUTPUT
+ \ DOXYGEN_LATEX_SOURCE_CODE
+ \ DOXYGEN_LATEX_TIMESTAMP
+ \ DOXYGEN_LAYOUT_FILE
+ \ DOXYGEN_LOOKUP_CACHE_SIZE
+ \ DOXYGEN_MACRO_EXPANSION
+ \ DOXYGEN_MAKEINDEX_CMD_NAME
+ \ DOXYGEN_MAN_EXTENSION
+ \ DOXYGEN_MAN_LINKS
+ \ DOXYGEN_MAN_OUTPUT
+ \ DOXYGEN_MAN_SUBDIR
+ \ DOXYGEN_MARKDOWN_SUPPORT
+ \ DOXYGEN_MATHJAX_CODEFILE
+ \ DOXYGEN_MATHJAX_EXTENSIONS
+ \ DOXYGEN_MATHJAX_FORMAT
+ \ DOXYGEN_MATHJAX_RELPATH
+ \ DOXYGEN_MAX_DOT_GRAPH_DEPTH
+ \ DOXYGEN_MAX_INITIALIZER_LINES
+ \ DOXYGEN_MSCFILE_DIRS
+ \ DOXYGEN_MULTILINE_CPP_IS_BRIEF
+ \ DOXYGEN_OPTIMIZE_FOR_FORTRAN
+ \ DOXYGEN_OPTIMIZE_OUTPUT_FOR_C
+ \ DOXYGEN_OPTIMIZE_OUTPUT_JAVA
+ \ DOXYGEN_OPTIMIZE_OUTPUT_SLICE
+ \ DOXYGEN_OPTIMIZE_OUTPUT_VHDL
+ \ DOXYGEN_OUTPUT_DIRECTORY
+ \ DOXYGEN_OUTPUT_LANGUAGE
+ \ DOXYGEN_OUTPUT_TEXT_DIRECTION
+ \ DOXYGEN_PAPER_TYPE
+ \ DOXYGEN_PDF_HYPERLINKS
+ \ DOXYGEN_PERLMOD_LATEX
+ \ DOXYGEN_PERLMOD_MAKEVAR_PREFIX
+ \ DOXYGEN_PERLMOD_PRETTY
+ \ DOXYGEN_PLANTUML_CFG_FILE
+ \ DOXYGEN_PLANTUML_INCLUDE_PATH
+ \ DOXYGEN_PLANTUML_JAR_PATH
+ \ DOXYGEN_PREDEFINED
+ \ DOXYGEN_PROJECT_BRIEF
+ \ DOXYGEN_PROJECT_LOGO
+ \ DOXYGEN_PROJECT_NAME
+ \ DOXYGEN_PROJECT_NUMBER
+ \ DOXYGEN_QCH_FILE
+ \ DOXYGEN_QHG_LOCATION
+ \ DOXYGEN_QHP_CUST_FILTER_ATTRS
+ \ DOXYGEN_QHP_CUST_FILTER_NAME
+ \ DOXYGEN_QHP_NAMESPACE
+ \ DOXYGEN_QHP_SECT_FILTER_ATTRS
+ \ DOXYGEN_QHP_VIRTUAL_FOLDER
+ \ DOXYGEN_QT_AUTOBRIEF
+ \ DOXYGEN_QUIET
+ \ DOXYGEN_RECURSIVE
+ \ DOXYGEN_REFERENCED_BY_RELATION
+ \ DOXYGEN_REFERENCES_LINK_SOURCE
+ \ DOXYGEN_REFERENCES_RELATION
+ \ DOXYGEN_REPEAT_BRIEF
+ \ DOXYGEN_RTF_EXTENSIONS_FILE
+ \ DOXYGEN_RTF_HYPERLINKS
+ \ DOXYGEN_RTF_OUTPUT
+ \ DOXYGEN_RTF_SOURCE_CODE
+ \ DOXYGEN_RTF_STYLESHEET_FILE
+ \ DOXYGEN_SEARCHDATA_FILE
+ \ DOXYGEN_SEARCHENGINE
+ \ DOXYGEN_SEARCHENGINE_URL
+ \ DOXYGEN_SEARCH_INCLUDES
+ \ DOXYGEN_SEPARATE_MEMBER_PAGES
+ \ DOXYGEN_SERVER_BASED_SEARCH
+ \ DOXYGEN_SHORT_NAMES
+ \ DOXYGEN_SHOW_FILES
+ \ DOXYGEN_SHOW_GROUPED_MEMB_INC
+ \ DOXYGEN_SHOW_INCLUDE_FILES
+ \ DOXYGEN_SHOW_NAMESPACES
+ \ DOXYGEN_SHOW_USED_FILES
+ \ DOXYGEN_SIP_SUPPORT
+ \ DOXYGEN_SKIP_FUNCTION_MACROS
+ \ DOXYGEN_SORT_BRIEF_DOCS
+ \ DOXYGEN_SORT_BY_SCOPE_NAME
+ \ DOXYGEN_SORT_GROUP_NAMES
+ \ DOXYGEN_SORT_MEMBERS_CTORS_1ST
+ \ DOXYGEN_SORT_MEMBER_DOCS
+ \ DOXYGEN_SOURCE_BROWSER
+ \ DOXYGEN_SOURCE_TOOLTIPS
+ \ DOXYGEN_STRICT_PROTO_MATCHING
+ \ DOXYGEN_STRIP_CODE_COMMENTS
+ \ DOXYGEN_STRIP_FROM_INC_PATH
+ \ DOXYGEN_STRIP_FROM_PATH
+ \ DOXYGEN_SUBGROUPING
+ \ DOXYGEN_TAB_SIZE
+ \ DOXYGEN_TAGFILES
+ \ DOXYGEN_TCL_SUBST
+ \ DOXYGEN_TEMPLATE_RELATIONS
+ \ DOXYGEN_TOC_EXPAND
+ \ DOXYGEN_TOC_INCLUDE_HEADINGS
+ \ DOXYGEN_TREEVIEW_WIDTH
+ \ DOXYGEN_TYPEDEF_HIDES_STRUCT
+ \ DOXYGEN_UML_LIMIT_NUM_FIELDS
+ \ DOXYGEN_UML_LOOK
+ \ DOXYGEN_USE_HTAGS
+ \ DOXYGEN_USE_MATHJAX
+ \ DOXYGEN_USE_MDFILE_AS_MAINPAGE
+ \ DOXYGEN_USE_PDFLATEX
+ \ DOXYGEN_VERBATIM_HEADERS
+ \ DOXYGEN_VERBATIM_VARS
+ \ DOXYGEN_VERSION
+ \ DOXYGEN_WARNINGS
+ \ DOXYGEN_WARN_AS_ERROR
+ \ DOXYGEN_WARN_FORMAT
+ \ DOXYGEN_WARN_IF_DOC_ERROR
+ \ DOXYGEN_WARN_IF_UNDOCUMENTED
+ \ DOXYGEN_WARN_LOGFILE
+ \ DOXYGEN_WARN_NO_PARAMDOC
+ \ DOXYGEN_XML_NS_MEMB_FILE_SCOPE
+ \ DOXYGEN_XML_OUTPUT
+ \ DOXYGEN_XML_PROGRAMLISTING
\ ENV
\ EXECUTABLE_OUTPUT_PATH
\ GHS-MULTI
@@ -1541,9 +1940,11 @@ syn keyword cmakeKWExternalProject contained
\ BUILD_BYPRODUCTS
\ BUILD_COMMAND
\ BUILD_IN_SOURCE
+ \ CHECKOUT
\ CMAKE_ARGS
\ CMAKE_CACHE_ARGS
\ CMAKE_CACHE_DEFAULT_ARGS
+ \ CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY
\ CMAKE_TLS_CAINFO
\ CMAKE_TLS_VERIFY
\ COMMENT
@@ -1568,14 +1969,17 @@ syn keyword cmakeKWExternalProject contained
\ EP_STEP_TARGETS
\ EP_UPDATE_DISCONNECTED
\ EXCLUDE_FROM_ALL
+ \ FALSE
\ FORCE
\ GHS
\ GIT_CONFIG
\ GIT_PROGRESS
\ GIT_REMOTE_NAME
+ \ GIT_REMOTE_UPDATE_STRATEGY
\ GIT_REPOSITORY
\ GIT_SHALLOW
\ GIT_SUBMODULES
+ \ GIT_SUBMODULES_RECURSE
\ GIT_TAG
\ HG_REPOSITORY
\ HG_TAG
@@ -1583,6 +1987,7 @@ syn keyword cmakeKWExternalProject contained
\ HTTP_PASSWORD
\ HTTP_USERNAME
\ IGNORED
+ \ INACTIVITY_TIMEOUT
\ INDEPENDENT_STEP_TARGETS
\ INSTALL_COMMAND
\ INSTALL_DIR
@@ -1609,6 +2014,8 @@ syn keyword cmakeKWExternalProject contained
\ PATCH_COMMAND
\ PREFIX
\ PROPERTY
+ \ REBASE
+ \ REBASE_CHECKOUT
\ REQUIRED
\ SOURCE_DIR
\ SOURCE_SUBDIR
@@ -1633,6 +2040,7 @@ syn keyword cmakeKWExternalProject contained
\ UPDATE_DISCONNECTED
\ URL
\ URL_HASH
+ \ URL_MD5
\ USES_TERMINAL_BUILD
\ USES_TERMINAL_CONFIGURE
\ USES_TERMINAL_DOWNLOAD
@@ -1671,12 +2079,16 @@ syn keyword cmakeKWadd_custom_command contained
\ MAIN_DEPENDENCY
\ NOT
\ OUTPUT
+ \ PATH
\ POST_BUILD
\ PRE_BUILD
\ PRE_LINK
\ SYMBOLIC
\ TARGET_FILE
+ \ TARGET_LINKER_FILE
+ \ TARGET_PDB_FILE
\ TARGET_PROPERTY
+ \ TARGET_SONAME_FILE
\ USES_TERMINAL
\ VERBATIM
\ WORKING_DIRECTORY
@@ -1695,8 +2107,13 @@ syn keyword cmakeKWadd_custom_target contained
\ JOB_POOL
\ JOB_POOLS
\ JOIN
+ \ PATH
\ SOURCES
+ \ TARGET_FILE
+ \ TARGET_LINKER_FILE
+ \ TARGET_PDB_FILE
\ TARGET_PROPERTY
+ \ TARGET_SONAME_FILE
\ USES_TERMINAL
\ VERBATIM
\ WORKING_DIRECTORY
@@ -1710,6 +2127,7 @@ syn keyword cmakeKWadd_dependencies contained
syn keyword cmakeKWadd_executable contained
\ ALIAS
+ \ ALIAS_GLOBAL
\ CONFIG
\ EXCLUDE_FROM_ALL
\ GLOBAL
@@ -1725,6 +2143,7 @@ syn keyword cmakeKWadd_executable contained
syn keyword cmakeKWadd_library contained
\ ALIAS
+ \ ALIAS_GLOBAL
\ ARCHIVE_OUTPUT_DIRECTORY
\ CLI
\ CONFIG
@@ -1735,11 +2154,15 @@ syn keyword cmakeKWadd_library contained
\ HEADER_FILE_ONLY
\ IMPORTED
\ IMPORTED_
+ \ IMPORTED_IMPLIB
+ \ IMPORTED_IMPLIB_
\ IMPORTED_LOCATION
\ IMPORTED_LOCATION_
\ IMPORTED_OBJECTS
\ IMPORTED_OBJECTS_
+ \ INTERFACE
\ INTERFACE_
+ \ INTERFACE_SOURCES
\ LIBRARY_OUTPUT_DIRECTORY
\ MODULE
\ OBJECT
@@ -1749,17 +2172,23 @@ syn keyword cmakeKWadd_library contained
\ POST_BUILD
\ PRE_BUILD
\ PRE_LINK
- \ PUBLIC_HEADER
+ \ PRIVATE
+ \ PUBLIC
\ RUNTIME_OUTPUT_DIRECTORY
\ SHARED
+ \ SOURCES
\ STATIC
\ TARGET_OBJECTS
\ UNKNOWN
syn keyword cmakeKWadd_link_options contained
\ CMAKE_
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_SEPARABLE_COMPILATION
+ \ DEVICE_LINK
\ GCC
\ GNU
+ \ HOST_LINK
\ LANG
\ LINKER
\ LINK_OPTIONS
@@ -1775,6 +2204,7 @@ syn keyword cmakeKWadd_subdirectory contained
syn keyword cmakeKWadd_test contained
\ BUILD_TESTING
\ COMMAND
+ \ COMMAND_EXPAND_LISTS
\ CONFIGURATIONS
\ FAIL_REGULAR_EXPRESSION
\ NAME
@@ -1816,6 +2246,23 @@ syn keyword cmakeKWcmake_host_system_information contained
\ TOTAL_PHYSICAL_MEMORY
\ TOTAL_VIRTUAL_MEMORY
+syn keyword cmakeKWcmake_language contained
+ \ AND
+ \ CALL
+ \ CANCEL_CALL
+ \ CODE
+ \ DEFER
+ \ DIRECTORY
+ \ EVAL
+ \ FALSE
+ \ GET_CALL_IDS
+ \ ID
+ \ ID_VAR
+ \ OR
+ \ STATUS
+ \ TRUE
+ \ WRITE
+
syn keyword cmakeKWcmake_minimum_required contained
\ FATAL_ERROR
\ VERSION
@@ -1845,6 +2292,72 @@ syn keyword cmakeKWcmake_parse_arguments contained
\ _KEYWORDS_MISSING_VALUES
\ _UNPARSED_ARGUMENTS
+syn keyword cmakeKWcmake_path contained
+ \ ABSOLUTE_PATH
+ \ AND
+ \ APPEND
+ \ BASE_DIRECTORY
+ \ CMAKE_PATH
+ \ COMPARE
+ \ CONCAT
+ \ CONVERT
+ \ ELSEIF
+ \ ENDIF
+ \ EXTENSION
+ \ EXTENSION_DEF
+ \ FALSE
+ \ FILENAME_DEF
+ \ GET
+ \ GET_EXTENSION
+ \ GET_FILENAME
+ \ GET_PARENT_PATH
+ \ GET_RELATIVE_PATH
+ \ GET_ROOT_DIRECTORY
+ \ GET_ROOT_NAME
+ \ GET_ROOT_PATH
+ \ GET_STEM
+ \ HASH
+ \ HAS_EXTENSION
+ \ HAS_FILENAME
+ \ HAS_PARENT_PATH
+ \ HAS_RELATIVE_PATH
+ \ HAS_ROOT_DIRECTORY
+ \ HAS_ROOT_NAME
+ \ HAS_ROOT_PATH
+ \ HAS_STEM
+ \ IF
+ \ IS_ABSOLUTE
+ \ IS_PREFIX
+ \ IS_RELATIVE
+ \ LAST_ONLY
+ \ MATCHES
+ \ NATIVE_PATH
+ \ NORMALIZE
+ \ NORMAL_PATH
+ \ NOT
+ \ NOT_EQUAL
+ \ OP
+ \ OS
+ \ OUTPUT_VARIABLE
+ \ PARENT_PATH
+ \ PROXIMATE_PATH
+ \ REAL_PATH
+ \ RELATIVE_PATH
+ \ REMOVE_EXTENSION
+ \ REMOVE_FILENAME
+ \ REPLACE_EXTENSION
+ \ REPLACE_FILENAME
+ \ RETURN
+ \ ROOT_DIRECTORY
+ \ ROOT_NAME
+ \ ROOT_PATH
+ \ STEM
+ \ STREQUAL
+ \ TO_CMAKE_PATH_LIST
+ \ TO_NATIVE_PATH_LIST
+ \ TRUE
+ \ XOR
+
syn keyword cmakeKWcmake_policy contained
\ CMAKE_POLICY_DEFAULT_CMP
\ CMP
@@ -1862,10 +2375,13 @@ syn keyword cmakeKWconfigure_file contained
\ CRLF
\ DOS
\ ESCAPE_QUOTES
+ \ FILE_PERMISSIONS
\ FOO_ENABLE
\ FOO_STRING
\ LF
\ NEWLINE_STYLE
+ \ NO_SOURCE_PERMISSIONS
+ \ USE_SOURCE_PERMISSIONS
\ VAR
syn keyword cmakeKWcreate_test_sourcelist contained
@@ -1935,6 +2451,7 @@ syn keyword cmakeKWctest_run_script contained
syn keyword cmakeKWctest_start contained
\ APPEND
+ \ GROUP
\ QUIET
\ TAG
\ TRACK
@@ -1957,6 +2474,7 @@ syn keyword cmakeKWctest_submit contained
\ SUBMIT_URL
syn keyword cmakeKWctest_test contained
+ \ AFTER_TIMEOUT
\ APPEND
\ BUILD
\ CAPTURE_CMAKE_ERROR
@@ -1972,12 +2490,17 @@ syn keyword cmakeKWctest_test contained
\ ON
\ PARALLEL_LEVEL
\ QUIET
+ \ REPEAT
+ \ RESOURCE_SPEC_FILE
\ RETURN_VALUE
\ SCHEDULE_RANDOM
\ START
+ \ STOP_ON_FAILURE
\ STOP_TIME
\ STRIDE
\ TEST_LOAD
+ \ UNTIL_FAIL
+ \ UNTIL_PASS
syn keyword cmakeKWctest_update contained
\ CAPTURE_CMAKE_ERROR
@@ -2005,9 +2528,18 @@ syn keyword cmakeKWdefine_property contained
\ TEST
\ VARIABLE
+syn keyword cmakeKWdoxygen_add_docs contained
+ \ ALL
+ \ COMMENT
+ \ USE_STAMP_FILE
+ \ WORKING_DIRECTORY
+
syn keyword cmakeKWenable_language contained
\ ASM
\ CUDA
+ \ ISPC
+ \ OBJC
+ \ OBJCXX
\ OPTIONAL
syn keyword cmakeKWenable_testing contained
@@ -2020,15 +2552,20 @@ syn keyword cmakeKWexec_program contained
syn keyword cmakeKWexecute_process contained
\ ANSI
+ \ ANY
\ AUTO
\ COMMAND
\ COMMAND_ECHO
+ \ COMMAND_ERROR_IS_FATAL
+ \ ECHO_ERROR_VARIABLE
+ \ ECHO_OUTPUT_VARIABLE
\ ENCODING
\ ERROR_FILE
\ ERROR_QUIET
\ ERROR_STRIP_TRAILING_WHITESPACE
\ ERROR_VARIABLE
\ INPUT_FILE
+ \ LAST
\ NONE
\ OEM
\ OUTPUT_FILE
@@ -2070,63 +2607,107 @@ syn keyword cmakeKWexport_library_dependencies contained
syn keyword cmakeKWfile contained
\ ALGO
\ APPEND
+ \ ARCHIVE_CREATE
+ \ ARCHIVE_EXTRACT
\ ASCII
+ \ BASE_DIRECTORY
+ \ BUNDLE_EXECUTABLE
+ \ CHMOD
+ \ CHMOD_RECURSE
+ \ CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND
+ \ CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM
+ \ CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL
+ \ CMAKE_OBJDUMP
\ CMAKE_TLS_CAINFO
\ CMAKE_TLS_VERIFY
+ \ CODE
+ \ COMPILE_FEATURES
+ \ COMPRESSION
+ \ COMPRESSION_LEVEL
\ CONDITION
- \ CONFIG
+ \ CONFIGURE
\ CONFIGURE_DEPENDS
+ \ CONFLICTING_DEPENDENCIES_PREFIX
\ CONTENT
+ \ CONVERT
\ COPY
\ COPY_ON_ERROR
\ CREATE_LINK
+ \ CRLF
\ DESTINATION
+ \ DIRECTORIES
\ DIRECTORY_PERMISSIONS
+ \ DLL
+ \ DOS
\ DOWNLOAD
\ ENCODING
- \ EXCLUDE
+ \ ESCAPE_QUOTES
+ \ EXECUTABLES
\ EXPECTED_HASH
\ FILES_MATCHING
\ FILE_PERMISSIONS
\ FOLLOW_SYMLINKS
\ FOLLOW_SYMLINK_CHAIN
+ \ FORMAT
\ FUNCTION
\ GENERATE
+ \ GET_RUNTIME_DEPENDENCIES
\ GLOB
\ GLOB_RECURSE
+ \ GROUP_EXECUTE
+ \ GROUP_READ
+ \ GROUP_WRITE
\ GUARD
\ HASH
\ HEX
\ HTTPHEADER
\ IGNORED
\ INACTIVITY_TIMEOUT
+ \ INPUT
\ INSTALL
\ IS_ABSOLUTE
\ LENGTH_MAXIMUM
\ LENGTH_MINIMUM
\ LF
+ \ LIBRARIES
\ LIMIT
\ LIMIT_COUNT
\ LIMIT_INPUT
\ LIMIT_OUTPUT
\ LIST_DIRECTORIES
+ \ LIST_ONLY
\ LOCK
\ LOG
\ MAKE_DIRECTORY
+ \ MODULES
+ \ MTIME
+ \ MYLIBRARY
\ NETRC
\ NETRC_FILE
\ NEWLINE_CONSUME
+ \ NEWLINE_STYLE
\ NOT
\ NO_HEX_CONVERSION
\ NO_SOURCE_PERMISSIONS
\ OFFSET
- \ OLD
+ \ ONLY
\ OPTIONAL
\ OUTPUT
+ \ OWNER_EXECUTE
+ \ OWNER_READ
+ \ OWNER_WRITE
+ \ PATHS
\ PATTERN
+ \ PATTERNS
+ \ PERMISSIONS
+ \ POST_EXCLUDE_REGEXES
+ \ POST_INCLUDE_REGEXES
+ \ PRE_EXCLUDE_REGEXES
+ \ PRE_INCLUDE_REGEXES
\ PROCESS
\ READ
\ READ_SYMLINK
+ \ REAL_PATH
\ REGEX
\ RELATIVE_PATH
\ RELEASE
@@ -2134,33 +2715,51 @@ syn keyword cmakeKWfile contained
\ REMOVE_RECURSE
\ RENAME
\ REQUIRED
+ \ RESOLVED_DEPENDENCIES_VAR
\ RESULT
\ RESULT_VARIABLE
+ \ RPATH
+ \ RUNPATH
+ \ SCRIPT
+ \ SHARED
\ SHOW_PROGRESS
\ SIZE
\ SSL
+ \ STATIC
\ STATUS
\ STRINGS
\ SYMBOLIC
+ \ TARGET
+ \ TARGET_PROPERTY
\ TIMESTAMP
\ TLS_CAINFO
\ TLS_VERIFY
\ TOUCH
\ TOUCH_NOCREATE
\ TO_CMAKE_PATH
+ \ TO_CMAKE_PATH_LIST
\ TO_NATIVE_PATH
+ \ TO_NATIVE_PATH_LIST
+ \ UNRESOLVED_DEPENDENCIES_VAR
\ UPLOAD
\ URL
\ USERPWD
\ USE_SOURCE_PERMISSIONS
\ UTC
\ UTF
+ \ VERBOSE
+ \ WORLD_EXECUTE
+ \ WORLD_READ
+ \ WORLD_WRITE
\ WRITE
+ \ XZ
+ \ _FILENAMES
syn keyword cmakeKWfind_file contained
\ CMAKE_FIND_ROOT_PATH_BOTH
\ DOC
\ DVAR
+ \ FALSE
\ HINTS
\ INCLUDE
\ NAMES
@@ -2174,14 +2773,16 @@ syn keyword cmakeKWfind_file contained
\ ONLY_CMAKE_FIND_ROOT_PATH
\ PATHS
\ PATH_SUFFIXES
+ \ REQUIRED
\ VAR
syn keyword cmakeKWfind_library contained
\ CMAKE_FIND_ROOT_PATH_BOTH
\ DOC
\ DVAR
+ \ FALSE
\ HINTS
- \ LIB
+ \ INCLUDE
\ NAMES
\ NAMES_PER_DIR
\ NO_CMAKE_ENVIRONMENT_PATH
@@ -2194,6 +2795,7 @@ syn keyword cmakeKWfind_library contained
\ ONLY_CMAKE_FIND_ROOT_PATH
\ PATHS
\ PATH_SUFFIXES
+ \ REQUIRED
\ VAR
syn keyword cmakeKWfind_package contained
@@ -2207,8 +2809,12 @@ syn keyword cmakeKWfind_package contained
\ DEC
\ DVAR
\ EXACT
+ \ EXCLUDE
+ \ FALSE
+ \ FIND_PACKAGE_VERSION_FORMAT
\ FRAMEWORK
\ HINTS
+ \ INCLUDE
\ MODULE
\ NAMES
\ NATURAL
@@ -2228,12 +2834,26 @@ syn keyword cmakeKWfind_package contained
\ OPTIONAL_COMPONENTS
\ PACKAGE_FIND_NAME
\ PACKAGE_FIND_VERSION
+ \ PACKAGE_FIND_VERSION_COMPLETE
\ PACKAGE_FIND_VERSION_COUNT
\ PACKAGE_FIND_VERSION_MAJOR
+ \ PACKAGE_FIND_VERSION_MAX
+ \ PACKAGE_FIND_VERSION_MAX_COUNT
+ \ PACKAGE_FIND_VERSION_MAX_MAJOR
+ \ PACKAGE_FIND_VERSION_MAX_MINOR
+ \ PACKAGE_FIND_VERSION_MAX_PATCH
+ \ PACKAGE_FIND_VERSION_MAX_TWEAK
\ PACKAGE_FIND_VERSION_MINOR
+ \ PACKAGE_FIND_VERSION_MIN_COUNT
+ \ PACKAGE_FIND_VERSION_MIN_MAJOR
+ \ PACKAGE_FIND_VERSION_MIN_MINOR
+ \ PACKAGE_FIND_VERSION_MIN_PATCH
+ \ PACKAGE_FIND_VERSION_MIN_TWEAK
\ PACKAGE_FIND_VERSION_PATCH
+ \ PACKAGE_FIND_VERSION_RANGE
+ \ PACKAGE_FIND_VERSION_RANGE_MAX
+ \ PACKAGE_FIND_VERSION_RANGE_MIN
\ PACKAGE_FIND_VERSION_TWEAK
- \ PACKAGE_VERSION
\ PACKAGE_VERSION_COMPATIBLE
\ PACKAGE_VERSION_EXACT
\ PACKAGE_VERSION_UNSUITABLE
@@ -2258,6 +2878,7 @@ syn keyword cmakeKWfind_path contained
\ CMAKE_FIND_ROOT_PATH_BOTH
\ DOC
\ DVAR
+ \ FALSE
\ HINTS
\ INCLUDE
\ NAMES
@@ -2271,12 +2892,14 @@ syn keyword cmakeKWfind_path contained
\ ONLY_CMAKE_FIND_ROOT_PATH
\ PATHS
\ PATH_SUFFIXES
+ \ REQUIRED
\ VAR
syn keyword cmakeKWfind_program contained
\ CMAKE_FIND_ROOT_PATH_BOTH
\ DOC
\ DVAR
+ \ FALSE
\ HINTS
\ NAMES
\ NAMES_PER_DIR
@@ -2290,22 +2913,26 @@ syn keyword cmakeKWfind_program contained
\ ONLY_CMAKE_FIND_ROOT_PATH
\ PATHS
\ PATH_SUFFIXES
+ \ REQUIRED
\ VAR
syn keyword cmakeKWfltk_wrap_ui contained
\ FLTK
syn keyword cmakeKWforeach contained
+ \ APPEND
\ IN
\ ITEMS
\ LISTS
\ RANGE
\ STATUS
+ \ ZIP_LISTS
syn keyword cmakeKWfunction contained
\ ARGC
\ ARGN
\ ARGV
+ \ CALL
\ FOO
\ PARENT_SCOPE
@@ -2333,6 +2960,7 @@ syn keyword cmakeKWget_filename_component contained
\ PROGRAM
\ PROGRAM_ARGS
\ REALPATH
+ \ REAL_PATH
syn keyword cmakeKWget_property contained
\ BRIEF_DOCS
@@ -2345,13 +2973,15 @@ syn keyword cmakeKWget_property contained
\ SET
\ SOURCE
\ TARGET
+ \ TARGET_DIRECTORY
\ TEST
\ VARIABLE
syn keyword cmakeKWget_source_file_property contained
+ \ DIRECTORY
\ INHERITED
\ LOCATION
- \ VAR
+ \ TARGET_DIRECTORY
syn keyword cmakeKWget_target_property contained
\ INHERITED
@@ -2427,6 +3057,7 @@ syn keyword cmakeKWinclude_guard contained
syn keyword cmakeKWinstall contained
\ AFTER
+ \ AIX
\ APT
\ ARCHIVE
\ BEFORE
@@ -2460,6 +3091,7 @@ syn keyword cmakeKWinstall contained
\ DIRECTORY_PERMISSIONS
\ DLL
\ DOC
+ \ ENABLE_EXPORTS
\ EXCLUDE_FROM_ALL
\ EXPORT
\ EXPORT_ANDROID_MK
@@ -2565,6 +3197,7 @@ syn keyword cmakeKWlist contained
\ INTERNAL
\ JOIN
\ LENGTH
+ \ NATURAL
\ ORDER
\ OUTPUT_VARIABLE
\ PARENT_SCOPE
@@ -2600,6 +3233,7 @@ syn keyword cmakeKWmacro contained
\ ARGC
\ ARGN
\ ARGV
+ \ CALL
\ DEFINED
\ FOO
\ GREATER
@@ -2616,12 +3250,18 @@ syn keyword cmakeKWmath contained
\ OUTPUT_FORMAT
syn keyword cmakeKWmessage contained
+ \ APPEND
\ AUTHOR_WARNING
+ \ CHECK_
+ \ CHECK_FAIL
+ \ CHECK_PASS
+ \ CHECK_START
\ DEBUG
\ DEPRECATION
\ FATAL_ERROR
\ GUI
\ NOTICE
+ \ POP_BACK
\ SEND_ERROR
\ STATUS
\ TRACE
@@ -2638,15 +3278,18 @@ syn keyword cmakeKWproject contained
\ CUDA
\ DESCRIPTION
\ HOMEPAGE_URL
+ \ ISPC
\ LANGUAGES
\ NAME
\ NONE
+ \ OBJC
+ \ OBJCXX
\ PROJECT
\ VERSION
\ _BINARY_DIR
\ _DESCRIPTION
\ _HOMEPAGE_URL
- \ _INCLUDE
+ \ _INCLUDE_BEFORE
\ _SOURCE_DIR
\ _VERSION
\ _VERSION_MAJOR
@@ -2664,9 +3307,14 @@ syn keyword cmakeKWremove contained
\ VALUE
\ VAR
+syn keyword cmakeKWreturn contained
+ \ DEFER
+
syn keyword cmakeKWseparate_arguments contained
\ MSDN
\ NATIVE_COMMAND
+ \ PROGRAM
+ \ SEPARATE_ARGS
\ UNIX_COMMAND
\ WINDOWS_COMMAND
@@ -2695,12 +3343,15 @@ syn keyword cmakeKWset_property contained
\ PROPERTY
\ SOURCE
\ TARGET
+ \ TARGET_DIRECTORY
\ TEST
\ WIX
syn keyword cmakeKWset_source_files_properties contained
+ \ DIRECTORY
\ PROPERTIES
\ SOURCE
+ \ TARGET_DIRECTORY
syn keyword cmakeKWset_target_properties contained
\ PROPERTIES
@@ -2710,6 +3361,9 @@ syn keyword cmakeKWset_tests_properties contained
\ PROPERTIES
\ TEST
+syn keyword cmakeKWsite_name contained
+ \ HOSTNAME
+
syn keyword cmakeKWsource_group contained
\ FILES
\ PREFIX
@@ -2719,20 +3373,27 @@ syn keyword cmakeKWsource_group contained
syn keyword cmakeKWstring contained
\ ALPHABET
\ APPEND
+ \ ARRAY
\ ASCII
+ \ BOOLEAN
\ CMAKE_MATCH_
\ COMPARE
\ CONCAT
\ CONFIGURE
\ EQUAL
+ \ ERROR_VARIABLE
\ ESCAPE_QUOTES
\ FIND
\ GENEX_STRIP
+ \ GET
\ GREATER
\ GREATER_EQUAL
\ GUID
\ HASH
+ \ HEX
\ JOIN
+ \ JSON
+ \ JSONLENGTH
\ LENGTH
\ LESS
\ LESS_EQUAL
@@ -2740,17 +3401,24 @@ syn keyword cmakeKWstring contained
\ MATCH
\ MATCHALL
\ MATCHES
+ \ MEMBER
\ NAMESPACE
\ NOTEQUAL
+ \ NULL
+ \ NUMBER
+ \ OBJECT
+ \ OFF
\ ONLY
\ PREPEND
\ RANDOM
\ RANDOM_SEED
\ REGEX
+ \ REMOVE
\ REPEAT
\ REPLACE
\ REVERSE
\ RFC
+ \ SET
\ SHA
\ SOURCE_DATE_EPOCH
\ STRIP
@@ -2853,8 +3521,12 @@ syn keyword cmakeKWtarget_link_options contained
\ ALIAS
\ BEFORE
\ CMAKE_
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_SEPARABLE_COMPILATION
+ \ DEVICE_LINK
\ GCC
\ GNU
+ \ HOST_LINK
\ IMPORTED
\ INTERFACE
\ INTERFACE_LINK_OPTIONS
@@ -2870,9 +3542,23 @@ syn keyword cmakeKWtarget_link_options contained
\ _LINKER_WRAPPER_FLAG_SEP
syn keyword cmakeKWtarget_precompile_headers contained
+ \ ALIAS
+ \ ANGLE
+ \ BUILD_INTERFACE
+ \ COMPILE_LANGUAGE
+ \ DISABLE_PRECOMPILE_HEADERS
+ \ EXPORT
+ \ FI
+ \ GCC
+ \ IMPORTED
\ INTERFACE
+ \ INTERFACE_PRECOMPILE_HEADERS
+ \ PRECOMPILE_HEADERS
+ \ PRECOMPILE_HEADERS_REUSE_FROM
\ PRIVATE
\ PUBLIC
+ \ REUSE_FROM
+ \ SKIP_PRECOMPILE_HEADERS
syn keyword cmakeKWtarget_sources contained
\ ALIAS
@@ -2911,6 +3597,12 @@ syn keyword cmakeKWtry_compile contained
\ LINK_OPTIONS
\ MULTI
\ NOT
+ \ OBJCXX_EXTENSIONS
+ \ OBJCXX_STANDARD
+ \ OBJCXX_STANDARD_REQUIRED
+ \ OBJC_EXTENSIONS
+ \ OBJC_STANDARD
+ \ OBJC_STANDARD_REQUIRED
\ OUTPUT_VARIABLE
\ PRIVATE
\ SOURCES
@@ -2956,7 +3648,14 @@ syn keyword cmakeKWvariable_requires contained
\ TEST_VARIABLE
syn keyword cmakeKWvariable_watch contained
+ \ APPEND
\ COMMAND
+ \ DEFINED
+ \ MODIFIED_ACCESS
+ \ READ_ACCESS
+ \ REMOVED_ACCESS
+ \ UNKNOWN_MODIFIED_ACCESS
+ \ UNKNOWN_READ_ACCESS
syn keyword cmakeKWwrite_file contained
\ APPEND
@@ -2988,39 +3687,49 @@ syn keyword cmakeGeneratorExpressions contained
\ CONFIGURATION
\ CUDA_COMPILER_ID
\ CUDA_COMPILER_VERSION
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_SEPARABLE_COMPILATION
\ CUSTOM_KEYS
\ CXX_COMPILER_ID
\ CXX_COMPILER_VERSION
+ \ CXX_CONFIG
\ CXX_STANDARD
\ C_COMPILER_ID
\ C_COMPILER_VERSION
\ C_STANDARD
\ DEBUG_MODE
\ DEBUG_POSTFIX
+ \ DEVICE_LINK
+ \ DLL
\ EXCLUDE
\ EXPORT
\ FALSE
\ FILTER
\ FOO_EXTRA_THINGS
- \ Fortran_COMPILER_ID
- \ Fortran_COMPILER_VERSION
\ GENERATE
\ GENEX_EVAL
\ GNU
+ \ HOST_LINK
\ IF
\ IGNORE
\ IMPORT_PREFIX
\ IMPORT_SUFFIX
\ INCLUDE_DIRECTORIES
\ INSTALL_INTERFACE
+ \ INSTALL_NAME_DIR
\ INSTALL_PREFIX
+ \ INTERFACE
\ INTERFACE_LINK_LIBRARIES
\ IN_LIST
+ \ ISPC_COMPILER_ID
+ \ ISPC_COMPILER_VERSION
\ JOIN
\ LANG
\ LANG_COMPILER_ID
\ LIBRARY_OUTPUT_NAME
\ LIBRARY_OUTPUT_NAME_
+ \ LINK_LANGUAGE
+ \ LINK_LANG_AND_ID
\ LINK_LIBRARIES
\ LINK_ONLY
\ LOWER_CASE
@@ -3028,6 +3737,10 @@ syn keyword cmakeGeneratorExpressions contained
\ MAP_IMPORTED_CONFIG_
\ NO
\ NOT
+ \ OBJCXX_COMPILER_ID
+ \ OBJCXX_COMPILER_VERSION
+ \ OBJC_COMPILER_ID
+ \ OBJC_COMPILER_VERSION
\ OFF
\ OLD_COMPILER
\ OUTPUT_NAME
@@ -3046,6 +3759,7 @@ syn keyword cmakeGeneratorExpressions contained
\ SDK
\ SEMICOLON
\ SHELL_PATH
+ \ STATIC
\ STREQUAL
\ TARGET_BUNDLE_CONTENT_DIR
\ TARGET_BUNDLE_DIR
@@ -3100,8 +3814,10 @@ syn keyword cmakeCommand
\ break
\ build_command
\ cmake_host_system_information
+ \ cmake_language
\ cmake_minimum_required
\ cmake_parse_arguments
+ \ cmake_path
\ cmake_policy
\ configure_file
\ continue
@@ -3258,8 +3974,10 @@ hi def link cmakeKWadd_subdirectory ModeMsg
hi def link cmakeKWadd_test ModeMsg
hi def link cmakeKWbuild_command ModeMsg
hi def link cmakeKWcmake_host_system_information ModeMsg
+hi def link cmakeKWcmake_language ModeMsg
hi def link cmakeKWcmake_minimum_required ModeMsg
hi def link cmakeKWcmake_parse_arguments ModeMsg
+hi def link cmakeKWcmake_path ModeMsg
hi def link cmakeKWcmake_policy ModeMsg
hi def link cmakeKWconfigure_file ModeMsg
hi def link cmakeKWcreate_test_sourcelist ModeMsg
@@ -3274,6 +3992,7 @@ hi def link cmakeKWctest_test ModeMsg
hi def link cmakeKWctest_update ModeMsg
hi def link cmakeKWctest_upload ModeMsg
hi def link cmakeKWdefine_property ModeMsg
+hi def link cmakeKWdoxygen_add_docs ModeMsg
hi def link cmakeKWenable_language ModeMsg
hi def link cmakeKWenable_testing ModeMsg
hi def link cmakeKWexec_program ModeMsg
@@ -3318,6 +4037,7 @@ hi def link cmakeKWproject ModeMsg
hi def link cmakeKWqt_wrap_cpp ModeMsg
hi def link cmakeKWqt_wrap_ui ModeMsg
hi def link cmakeKWremove ModeMsg
+hi def link cmakeKWreturn ModeMsg
hi def link cmakeKWseparate_arguments ModeMsg
hi def link cmakeKWset ModeMsg
hi def link cmakeKWset_directory_properties ModeMsg
@@ -3325,6 +4045,7 @@ hi def link cmakeKWset_property ModeMsg
hi def link cmakeKWset_source_files_properties ModeMsg
hi def link cmakeKWset_target_properties ModeMsg
hi def link cmakeKWset_tests_properties ModeMsg
+hi def link cmakeKWsite_name ModeMsg
hi def link cmakeKWsource_group ModeMsg
hi def link cmakeKWstring ModeMsg
hi def link cmakeKWsubdirs ModeMsg
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2d860d4a8..a2fcf2e37 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.15 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.1...3.18 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)
diff --git a/Copyright.txt b/Copyright.txt
index b867d0178..7f5129361 100644
--- a/Copyright.txt
+++ b/Copyright.txt
@@ -1,5 +1,5 @@
CMake - Cross Platform Makefile Generator
-Copyright 2000-2020 Kitware, Inc. and Contributors
+Copyright 2000-2021 Kitware, Inc. and Contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -65,8 +65,8 @@ The following individuals and institutions are among the Contributors:
* Jan Woetzel
* Julien Schueller
* Kelly Thompson <kgt@lanl.gov>
-* Laurent Montel <montel@kde.org>
* Konstantin Podsvirov <konstantin@podsvirov.pro>
+* Laurent Montel <montel@kde.org>
* Mario Bensi <mbensi@ipsquad.net>
* Martin Gräßlin <mgraesslin@kde.org>
* Mathieu Malaterre <mathieu.malaterre@gmail.com>
diff --git a/Help/command/DEVICE_LINK_OPTIONS.txt b/Help/command/DEVICE_LINK_OPTIONS.txt
index 3f0226fdc..1297cd054 100644
--- a/Help/command/DEVICE_LINK_OPTIONS.txt
+++ b/Help/command/DEVICE_LINK_OPTIONS.txt
@@ -1,11 +1,12 @@
-When a device link step is involved, which is controlled by
-:prop_tgt:`CUDA_SEPARABLE_COMPILATION` and
-:prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and policy :policy:`CMP0105`,
-the raw options will be delivered to the host and device link steps (wrapped in
-``-Xcompiler`` or equivalent for device link). Options wrapped with
-``$<DEVICE_LINK:...>``
-:manual:`generator expression <cmake-generator-expressions(7)>` will be used
-only for the device link step. Options wrapped with ``$<HOST_LINK:...>``
-:manual:`generator expression <cmake-generator-expressions(7)>` will be used
-only for the host link step.
+.. versionadded:: 3.18
+ When a device link step is involved, which is controlled by
+ :prop_tgt:`CUDA_SEPARABLE_COMPILATION` and
+ :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and policy :policy:`CMP0105`,
+ the raw options will be delivered to the host and device link steps (wrapped in
+ ``-Xcompiler`` or equivalent for device link). Options wrapped with
+ ``$<DEVICE_LINK:...>``
+ :manual:`generator expression <cmake-generator-expressions(7)>` will be used
+ only for the device link step. Options wrapped with ``$<HOST_LINK:...>``
+ :manual:`generator expression <cmake-generator-expressions(7)>` will be used
+ only for the host link step.
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index 4a62c5b5b..97eecfca3 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -33,9 +33,6 @@ 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``.
-The ``REQUIRED`` option stops processing with an error message if nothing
-is found, otherwise the search will be attempted again the
-next time |FIND_XXX| is invoked with the same variable.
Options include:
@@ -60,7 +57,11 @@ Options include:
Specify the documentation string for the ``<VAR>`` cache entry.
``REQUIRED``
- Stop processing with an error message if nothing is found.
+ .. versionadded:: 3.18
+
+ Stop processing with an error message if nothing is found, otherwise
+ the search will be attempted again the next time |FIND_XXX| is invoked
+ with the same variable.
If ``NO_DEFAULT_PATH`` is specified, then no additional paths are
added to the search.
@@ -84,20 +85,21 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
|prefix_XXX_SUBDIR| for each ``<prefix>`` in
:variable:`CMAKE_SYSTEM_PREFIX_PATH`
-1. If called from within a find module or any other script loaded by a call to
- :command:`find_package(<PackageName>)`, search prefixes unique to the
- current package being found. Specifically, look in the
- :variable:`<PackageName>_ROOT` CMake variable and the
- :envvar:`<PackageName>_ROOT` environment variable.
- The package root variables are maintained as a stack, so if called from
- nested find modules or config packages, root paths from the parent's find
- module or config package will be searched after paths from the current
- module or package. In other words, the search order would be
- ``<CurrentPackage>_ROOT``, ``ENV{<CurrentPackage>_ROOT}``,
- ``<ParentPackage>_ROOT``, ``ENV{<ParentPackage>_ROOT}``, etc.
- This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting
- the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``.
- See policy :policy:`CMP0074`.
+1. .. versionadded:: 3.12
+ If called from within a find module or any other script loaded by a call to
+ :command:`find_package(<PackageName>)`, search prefixes unique to the
+ current package being found. Specifically, look in the
+ :variable:`<PackageName>_ROOT` CMake variable and the
+ :envvar:`<PackageName>_ROOT` environment variable.
+ The package root variables are maintained as a stack, so if called from
+ nested find modules or config packages, root paths from the parent's find
+ module or config package will be searched after paths from the current
+ module or package. In other words, the search order would be
+ ``<CurrentPackage>_ROOT``, ``ENV{<CurrentPackage>_ROOT}``,
+ ``<ParentPackage>_ROOT``, ``ENV{<ParentPackage>_ROOT}``, etc.
+ This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting
+ the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``.
+ See policy :policy:`CMP0074`.
* |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX|
@@ -151,6 +153,10 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
or in the short-hand version of the command.
These are typically hard-coded guesses.
+.. versionadded:: 3.16
+ Added ``CMAKE_FIND_USE_<CATEGORY>_PATH`` variables to globally disable
+ various search locations.
+
.. |FIND_ARGS_XXX| replace:: <VAR> NAMES name
On macOS the :variable:`CMAKE_FIND_FRAMEWORK` and
diff --git a/Help/command/OPTIONS_SHELL.txt b/Help/command/OPTIONS_SHELL.txt
index 0f8ec323c..4051ffe16 100644
--- a/Help/command/OPTIONS_SHELL.txt
+++ b/Help/command/OPTIONS_SHELL.txt
@@ -1,9 +1,11 @@
The final set of compile or link 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.
-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``.
+
+.. 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``.
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index 231f9dad4..183bb72fc 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -46,11 +46,19 @@ The options are:
Append the ``COMMAND`` and ``DEPENDS`` option values to the custom
command for the first output specified. There must have already
been a previous call to this command with the same output.
+
+ If the previous call specified the output via a generator expression,
+ the output specified by the current call must match in at least one
+ configuration after evaluating generator expressions. In this case,
+ the appended commands and dependencies apply to all configurations.
+
The ``COMMENT``, ``MAIN_DEPENDENCY``, and ``WORKING_DIRECTORY``
options are currently ignored when APPEND is given, but may be
used in the future.
``BYPRODUCTS``
+ .. versionadded:: 3.2
+
Specify the files the command is expected to produce but whose
modification time may or may not be newer than the dependencies.
If a byproduct name is a relative path it will be interpreted
@@ -71,6 +79,10 @@ The options are:
The :ref:`Makefile Generators` will remove ``BYPRODUCTS`` and other
:prop_sf:`GENERATED` files during ``make clean``.
+ .. versionadded:: 3.20
+ Arguments to ``BYPRODUCTS`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
``COMMAND``
Specify the command-line(s) to execute at build time.
If more than one ``COMMAND`` is specified they will be executed in order,
@@ -88,18 +100,19 @@ The options are:
* The target is not being cross-compiled (i.e. the
:variable:`CMAKE_CROSSCOMPILING` variable is not set to true).
- * The target is being cross-compiled and an emulator is provided (i.e.
- its :prop_tgt:`CROSSCOMPILING_EMULATOR` target property is set).
- In this case, the contents of :prop_tgt:`CROSSCOMPILING_EMULATOR` will be
- prepended to the command before the location of the target executable.
+ * .. versionadded:: 3.6
+ The target is being cross-compiled and an emulator is provided (i.e.
+ its :prop_tgt:`CROSSCOMPILING_EMULATOR` target property is set).
+ In this case, the contents of :prop_tgt:`CROSSCOMPILING_EMULATOR` will be
+ prepended to the command before the location of the target executable.
If neither of the above conditions are met, it is assumed that the
command name is a program to be found on the ``PATH`` at build time.
Arguments to ``COMMAND`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
- Use the ``TARGET_FILE`` generator expression to refer to the location of
- a target later in the command line (i.e. as a command argument rather
+ Use the :genex:`TARGET_FILE` generator expression to refer to the location
+ of a target later in the command line (i.e. as a command argument rather
than as the command to execute).
Whenever one of the following target based generator expressions are used as
@@ -153,18 +166,23 @@ The options are:
If any dependency is an ``OUTPUT`` of another custom command in the same
directory (``CMakeLists.txt`` file), CMake automatically brings the other
custom command into the target in which this command is built.
- A target-level dependency is added if any dependency is listed as
- ``BYPRODUCTS`` of a target or any of its build events in the same
- directory to ensure the byproducts will be available.
+
+ .. versionadded:: 3.16
+ A target-level dependency is added if any dependency is listed as
+ ``BYPRODUCTS`` of a target or any of its build events in the same
+ directory to ensure the byproducts will be available.
If ``DEPENDS`` is not specified, the command will run whenever
the ``OUTPUT`` is missing; if the command does not actually
create the ``OUTPUT``, the rule will always run.
- Arguments to ``DEPENDS`` may use
- :manual:`generator expressions <cmake-generator-expressions(7)>`.
+ .. versionadded:: 3.1
+ Arguments to ``DEPENDS`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
``COMMAND_EXPAND_LISTS``
+ .. versionadded:: 3.8
+
Lists in ``COMMAND`` arguments will be expanded, including those
created with
:manual:`generator expressions <cmake-generator-expressions(7)>`,
@@ -183,7 +201,13 @@ The options are:
Note that the ``IMPLICIT_DEPENDS`` option is currently supported
only for Makefile generators and will be ignored by other generators.
+ .. note::
+
+ This option cannot be specified at the same time as ``DEPFILE`` option.
+
``JOB_POOL``
+ .. versionadded:: 3.15
+
Specify a :prop_gbl:`pool <JOB_POOLS>` for the :generator:`Ninja`
generator. Incompatible with ``USES_TERMINAL``, which implies
the ``console`` pool.
@@ -210,7 +234,13 @@ The options are:
as a file on disk it should be marked with the :prop_sf:`SYMBOLIC`
source file property.
+ .. versionadded:: 3.20
+ Arguments to ``OUTPUT`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
``USES_TERMINAL``
+ .. versionadded:: 3.2
+
The command will be given direct access to the terminal if possible.
With the :generator:`Ninja` generator, this places the command in
the ``console`` :prop_gbl:`pool <JOB_POOLS>`.
@@ -230,14 +260,72 @@ The options are:
If it is a relative path it will be interpreted relative to the
build tree directory corresponding to the current source directory.
- Arguments to ``WORKING_DIRECTORY`` may use
- :manual:`generator expressions <cmake-generator-expressions(7)>`.
+ .. versionadded:: 3.13
+ Arguments to ``WORKING_DIRECTORY`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
``DEPFILE``
- Specify a ``.d`` depfile for the :generator:`Ninja` generator.
+ .. 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 Ninja is an error.
+ Using ``DEPFILE`` with other generators than :generator:`Ninja` or
+ :ref:`Makefile Generators` is an error.
+
+ .. versionadded:: 3.20
+ Added the support of :ref:`Makefile Generators`.
+
+ 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`).
+
+ .. note::
+
+ For :ref:`Makefile Generators`, this option cannot be specified at the
+ same time as ``IMPLICIT_DEPENDS`` option.
+
+Examples: Generating Files
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Custom commands may be used to generate source files.
+For example, the code:
+
+.. code-block:: cmake
+
+ add_custom_command(
+ OUTPUT out.c
+ COMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
+ -o out.c
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
+ VERBATIM)
+ add_library(myLib out.c)
+
+adds a custom command to run ``someTool`` to generate ``out.c`` and then
+compile the generated source as part of a library. The generation rule
+will re-run whenever ``in.txt`` changes.
+
+.. versionadded:: 3.20
+ One may use generator expressions to specify per-configuration outputs.
+ For example, the code:
+
+ .. code-block:: cmake
+
+ add_custom_command(
+ OUTPUT "out-$<CONFIG>.c"
+ COMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
+ -o "out-$<CONFIG>.c"
+ -c "$<CONFIG>"
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
+ VERBATIM)
+ add_library(myLib "out-$<CONFIG>.c")
+
+ adds a custom command to run ``someTool`` to generate ``out-<config>.c``,
+ where ``<config>`` is the build configuration, and then compile the generated
+ source as part of a library.
Build Events
^^^^^^^^^^^^
@@ -288,3 +376,49 @@ of the following is specified:
configuration and no "empty-string-command" will be added.
This allows to add individual build events for every configuration.
+
+Examples: Build Events
+^^^^^^^^^^^^^^^^^^^^^^
+
+A ``POST_BUILD`` event may be used to post-process a binary after linking.
+For example, the code:
+
+.. code-block:: cmake
+
+ add_executable(myExe myExe.c)
+ add_custom_command(
+ TARGET myExe POST_BUILD
+ COMMAND someHasher -i "$<TARGET_FILE:myExe>"
+ -o "$<TARGET_FILE:myExe>.hash"
+ VERBATIM)
+
+will run ``someHasher`` to produce a ``.hash`` file next to the executable
+after linking.
+
+.. versionadded:: 3.20
+ One may use generator expressions to specify per-configuration byproducts.
+ For example, the code:
+
+ .. code-block:: cmake
+
+ add_library(myPlugin MODULE myPlugin.c)
+ add_custom_command(
+ TARGET myPlugin POST_BUILD
+ COMMAND someHasher -i "$<TARGET_FILE:myPlugin>"
+ --as-code "myPlugin-hash-$<CONFIG>.c"
+ BYPRODUCTS "myPlugin-hash-$<CONFIG>.c"
+ VERBATIM)
+ add_executable(myExe myExe.c "myPlugin-hash-$<CONFIG>.c")
+
+ will run ``someHasher`` after linking ``myPlugin``, e.g. to produce a ``.c``
+ file containing code to check the hash of ``myPlugin`` that the ``myExe``
+ executable can use to verify it before loading.
+
+Ninja Multi-Config
+^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.20
+
+ ``add_custom_command`` supports the :generator:`Ninja Multi-Config`
+ generator's cross-config capabilities. See the generator documentation
+ for more information.
diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst
index 2eb0c8864..22d3f294d 100644
--- a/Help/command/add_custom_target.rst
+++ b/Help/command/add_custom_target.rst
@@ -32,6 +32,8 @@ The options are:
called ``ALL``).
``BYPRODUCTS``
+ .. versionadded:: 3.2
+
Specify the files the command is expected to produce but whose
modification time may or may not be updated on subsequent builds.
If a byproduct name is a relative path it will be interpreted
@@ -52,6 +54,10 @@ The options are:
The :ref:`Makefile Generators` will remove ``BYPRODUCTS`` and other
:prop_sf:`GENERATED` files during ``make clean``.
+ .. versionadded:: 3.20
+ Arguments to ``BYPRODUCTS`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
``COMMAND``
Specify the command-line(s) to execute at build time.
If more than one ``COMMAND`` is specified they will be executed in order,
@@ -67,18 +73,19 @@ The options are:
* The target is not being cross-compiled (i.e. the
:variable:`CMAKE_CROSSCOMPILING` variable is not set to true).
- * The target is being cross-compiled and an emulator is provided (i.e.
- its :prop_tgt:`CROSSCOMPILING_EMULATOR` target property is set).
- In this case, the contents of :prop_tgt:`CROSSCOMPILING_EMULATOR` will be
- prepended to the command before the location of the target executable.
+ * .. versionadded:: 3.6
+ The target is being cross-compiled and an emulator is provided (i.e.
+ its :prop_tgt:`CROSSCOMPILING_EMULATOR` target property is set).
+ In this case, the contents of :prop_tgt:`CROSSCOMPILING_EMULATOR` will be
+ prepended to the command before the location of the target executable.
If neither of the above conditions are met, it is assumed that the
command name is a program to be found on the ``PATH`` at build time.
Arguments to ``COMMAND`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
- Use the ``TARGET_FILE`` generator expression to refer to the location of
- a target later in the command line (i.e. as a command argument rather
+ Use the :genex:`TARGET_FILE` generator expression to refer to the location
+ of a target later in the command line (i.e. as a command argument rather
than as the command to execute).
Whenever one of the following target based generator expressions are used as
@@ -103,14 +110,18 @@ The options are:
:command:`add_custom_command` command calls in the same directory
(``CMakeLists.txt`` file). They will be brought up to date when
the target is built.
- A target-level dependency is added if any dependency is a byproduct
- of a target or any of its build events in the same directory to ensure
- the byproducts will be available before this target is built.
+
+ .. versionchanged:: 3.16
+ A target-level dependency is added if any dependency is a byproduct
+ of a target or any of its build events in the same directory to ensure
+ the byproducts will be available before this target is built.
Use the :command:`add_dependencies` command to add dependencies
on other targets.
``COMMAND_EXPAND_LISTS``
+ .. versionadded:: 3.8
+
Lists in ``COMMAND`` arguments will be expanded, including those
created with
:manual:`generator expressions <cmake-generator-expressions(7)>`,
@@ -119,6 +130,8 @@ The options are:
to be properly expanded.
``JOB_POOL``
+ .. versionadded:: 3.15
+
Specify a :prop_gbl:`pool <JOB_POOLS>` for the :generator:`Ninja`
generator. Incompatible with ``USES_TERMINAL``, which implies
the ``console`` pool.
@@ -141,6 +154,8 @@ The options are:
tool-specific special characters.
``USES_TERMINAL``
+ .. versionadded:: 3.2
+
The command will be given direct access to the terminal if possible.
With the :generator:`Ninja` generator, this places the command in
the ``console`` :prop_gbl:`pool <JOB_POOLS>`.
@@ -150,5 +165,15 @@ The options are:
If it is a relative path it will be interpreted relative to the
build tree directory corresponding to the current source directory.
- Arguments to ``WORKING_DIRECTORY`` may use
- :manual:`generator expressions <cmake-generator-expressions(7)>`.
+ .. versionadded:: 3.13
+ Arguments to ``WORKING_DIRECTORY`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+Ninja Multi-Config
+^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.20
+
+ ``add_custom_target`` supports the :generator:`Ninja Multi-Config`
+ generator's cross-config capabilities. See the generator documentation
+ for more information.
diff --git a/Help/command/add_dependencies.rst b/Help/command/add_dependencies.rst
index de219a508..14c018303 100644
--- a/Help/command/add_dependencies.rst
+++ b/Help/command/add_dependencies.rst
@@ -17,6 +17,9 @@ Dependencies added to an :ref:`imported target <Imported Targets>`
or an :ref:`interface library <Interface Libraries>` are followed
transitively in its place since the target itself does not build.
+.. versionadded:: 3.3
+ Allow adding dependencies to interface libraries.
+
See the ``DEPENDS`` option of :command:`add_custom_target` and
:command:`add_custom_command` commands for adding file-level
dependencies in custom rules. See the :prop_sf:`OBJECT_DEPENDS`
diff --git a/Help/command/add_executable.rst b/Help/command/add_executable.rst
index e073228de..dde94293e 100644
--- a/Help/command/add_executable.rst
+++ b/Help/command/add_executable.rst
@@ -17,13 +17,21 @@ Normal Executables
[source1] [source2 ...])
Adds an executable target called ``<name>`` to be built from the source
-files listed in the command invocation. (The source files can be omitted
-here if they are added later using :command:`target_sources`.) The
+files listed in the command invocation. The
``<name>`` corresponds to the logical target name and must be globally
unique within a project. The actual file name of the executable built is
constructed based on conventions of the native platform (such as
``<name>.exe`` or just ``<name>``).
+.. versionadded:: 3.1
+ Source arguments to ``add_executable`` may use "generator expressions" with
+ the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+ manual for available expressions.
+
+.. versionadded:: 3.11
+ The source files can be omitted if they are added later using
+ :command:`target_sources`.
+
By default the executable file will be created in the build tree
directory corresponding to the source tree directory in which the
command was invoked. See documentation of the
@@ -43,10 +51,8 @@ If ``EXCLUDE_FROM_ALL`` is given the corresponding property will be set on
the created target. See documentation of the :prop_tgt:`EXCLUDE_FROM_ALL`
target property for details.
-Source arguments to ``add_executable`` 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.
+See the :manual:`cmake-buildsystem(7)` manual for more on defining
+buildsystem properties.
See also :prop_sf:`HEADER_FILE_ONLY` on what to do if some sources are
pre-processed, and you want to have the original sources reachable from
@@ -85,10 +91,14 @@ be used to refer to ``<target>`` in subsequent commands. The ``<name>``
does not appear in the generated buildsystem as a make target. The
``<target>`` may not be an ``ALIAS``.
-An ``ALIAS`` to a non-``GLOBAL`` :ref:`Imported Target <Imported Targets>`
-has scope in the directory in which the alias is created and below.
-The :prop_tgt:`ALIAS_GLOBAL` target property can be used to check if the
-alias is global or not.
+.. versionadded:: 3.11
+ An ``ALIAS`` can target a ``GLOBAL`` :ref:`Imported Target <Imported Targets>`
+
+.. versionadded:: 3.18
+ An ``ALIAS`` can target a non-``GLOBAL`` Imported Target. Such alias is
+ scoped to the directory in which it is created and subdirectories.
+ The :prop_tgt:`ALIAS_GLOBAL` target property can be used to check if the
+ alias is global or not.
``ALIAS`` targets can be used as targets to read properties
from, executables for custom commands and custom targets. They can also be
diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst
index b7dfabc8e..d3fbdcf19 100644
--- a/Help/command/add_library.rst
+++ b/Help/command/add_library.rst
@@ -17,13 +17,21 @@ Normal Libraries
[<source>...])
Adds a library target called ``<name>`` to be built from the source files
-listed in the command invocation. (The source files can be omitted here
-if they are added later using :command:`target_sources`.) The ``<name>``
+listed in the command invocation. The ``<name>``
corresponds to the logical target name and must be globally unique within
a project. The actual file name of the library built is constructed based
on conventions of the native platform (such as ``lib<name>.a`` or
``<name>.lib``).
+.. versionadded:: 3.1
+ Source arguments to ``add_library`` may use "generator expressions" with
+ the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+ manual for available expressions.
+
+.. versionadded:: 3.11
+ The source files can be omitted if they are added later using
+ :command:`target_sources`.
+
``STATIC``, ``SHARED``, or ``MODULE`` may be given to specify the type of
library to be created. ``STATIC`` libraries are archives of object files
for use when linking other targets. ``SHARED`` libraries are linked
@@ -34,9 +42,13 @@ type is ``STATIC`` or ``SHARED`` based on whether the current value of the
variable :variable:`BUILD_SHARED_LIBS` is ``ON``. For ``SHARED`` and
``MODULE`` libraries the :prop_tgt:`POSITION_INDEPENDENT_CODE` target
property is set to ``ON`` automatically.
-A ``SHARED`` or ``STATIC`` library may be marked with the :prop_tgt:`FRAMEWORK`
+A ``SHARED`` library may be marked with the :prop_tgt:`FRAMEWORK`
target property to create an macOS Framework.
+.. versionadded:: 3.8
+ A ``STATIC`` library may be marked with the :prop_tgt:`FRAMEWORK`
+ target property to create a static Framework.
+
If a library does not export any symbols, it must not be declared as a
``SHARED`` library. For example, a Windows resource DLL or a managed C++/CLI
DLL that exports no unmanaged symbols would need to be a ``MODULE`` library.
@@ -55,10 +67,8 @@ If ``EXCLUDE_FROM_ALL`` is given the corresponding property will be set on
the created target. See documentation of the :prop_tgt:`EXCLUDE_FROM_ALL`
target property for details.
-Source arguments to ``add_library`` 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.
+See the :manual:`cmake-buildsystem(7)` manual for more on defining
+buildsystem properties.
See also :prop_sf:`HEADER_FILE_ONLY` on what to do if some sources are
pre-processed, and you want to have the original sources reachable from
@@ -93,6 +103,9 @@ systems (such as Xcode) may not like targets that have only object files, so
consider adding at least one real source file to any target that references
``$<TARGET_OBJECTS:objlib>``.
+.. versionadded:: 3.12
+ Object libraries can be linked to with :command:`target_link_libraries`.
+
Interface Libraries
^^^^^^^^^^^^^^^^^^^
@@ -121,23 +134,28 @@ like any other target.
An interface library created with the above signature has no source files
itself and is not included as a target in the generated buildsystem.
-Since CMake 3.19, an interface library target may be created with
-source files:
+.. versionadded:: 3.15
+ An interface library can have :prop_tgt:`PUBLIC_HEADER` and
+ :prop_tgt:`PRIVATE_HEADER` properties. The headers specified by those
+ properties can be installed using the :command:`install(TARGETS)` command.
-.. code-block:: cmake
+.. versionadded:: 3.19
+ An interface library target may be created with source files:
+
+ .. code-block:: cmake
- add_library(<name> INTERFACE [<source>...] [EXCLUDE_FROM_ALL])
+ add_library(<name> INTERFACE [<source>...] [EXCLUDE_FROM_ALL])
-Source files may be listed directly in the ``add_library`` call or added
-later by calls to :command:`target_sources` with the ``PRIVATE`` or
-``PUBLIC`` keywords.
+ Source files may be listed directly in the ``add_library`` call or added
+ later by calls to :command:`target_sources` with the ``PRIVATE`` or
+ ``PUBLIC`` keywords.
-If an interface library has source files (i.e. the :prop_tgt:`SOURCES`
-target property is set), it will appear in the generated buildsystem
-as a build target much like a target defined by the
-:command:`add_custom_target` command. It does not compile any sources,
-but does contain build rules for custom commands created by the
-:command:`add_custom_command` command.
+ If an interface library has source files (i.e. the :prop_tgt:`SOURCES`
+ target property is set), it will appear in the generated buildsystem
+ as a build target much like a target defined by the
+ :command:`add_custom_target` command. It does not compile any sources,
+ but does contain build rules for custom commands created by the
+ :command:`add_custom_command` command.
.. note::
In most command signatures where the ``INTERFACE`` keyword appears,
@@ -211,10 +229,14 @@ used to refer to ``<target>`` in subsequent commands. The ``<name>`` does
not appear in the generated buildsystem as a make target. The ``<target>``
may not be an ``ALIAS``.
-An ``ALIAS`` to a non-``GLOBAL`` :ref:`Imported Target <Imported Targets>`
-has scope in the directory in which the alias is created and below.
-The :prop_tgt:`ALIAS_GLOBAL` target property can be used to check if the
-alias is global or not.
+.. versionadded:: 3.11
+ An ``ALIAS`` can target a ``GLOBAL`` :ref:`Imported Target <Imported Targets>`
+
+.. versionadded:: 3.18
+ An ``ALIAS`` can target a non-``GLOBAL`` Imported Target. Such alias is
+ scoped to the directory in which it is created and below.
+ The :prop_tgt:`ALIAS_GLOBAL` target property can be used to check if the
+ alias is global or not.
``ALIAS`` targets can be used as linkable targets and as targets to
read properties from. They can also be tested for existence with the
diff --git a/Help/command/add_test.rst b/Help/command/add_test.rst
index 2b4d082d1..95cd0374e 100644
--- a/Help/command/add_test.rst
+++ b/Help/command/add_test.rst
@@ -31,6 +31,8 @@ if necessary. See policy :policy:`CMP0110`. The options are:
current source directory.
``COMMAND_EXPAND_LISTS``
+ .. versionadded:: 3.16
+
Lists in ``COMMAND`` arguments will be expanded, including those
created with
:manual:`generator expressions <cmake-generator-expressions(7)>`.
@@ -43,6 +45,9 @@ unless the :prop_test:`PASS_REGULAR_EXPRESSION`,
:prop_test:`FAIL_REGULAR_EXPRESSION` or
:prop_test:`SKIP_REGULAR_EXPRESSION` test property is used.
+.. versionadded:: 3.16
+ Added :prop_test:`SKIP_REGULAR_EXPRESSION` property.
+
The ``COMMAND`` and ``WORKING_DIRECTORY`` options may use "generator
expressions" with the syntax ``$<...>``. See the
:manual:`cmake-generator-expressions(7)` manual for available expressions.
@@ -52,7 +57,7 @@ Example usage:
.. code-block:: cmake
add_test(NAME mytest
- COMMAND testDriver --config $<CONFIGURATION>
+ COMMAND testDriver --config $<CONFIG>
--exe $<TARGET_FILE:myexe>)
This creates a test ``mytest`` whose command runs a ``testDriver`` tool
diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst
index 2e9563aab..2b902a915 100644
--- a/Help/command/cmake_host_system_information.rst
+++ b/Help/command/cmake_host_system_information.rst
@@ -24,6 +24,14 @@ Key Description
``AVAILABLE_VIRTUAL_MEMORY`` Available virtual memory in MiB [#mebibytes]_
``TOTAL_PHYSICAL_MEMORY`` Total physical memory in MiB [#mebibytes]_
``AVAILABLE_PHYSICAL_MEMORY`` Available physical memory in MiB [#mebibytes]_
+============================= ================================================
+
+.. versionadded:: 3.10
+ Additional ``<key>`` values are available:
+
+============================= ================================================
+Key Description
+============================= ================================================
``IS_64BIT`` One if processor is 64Bit
``HAS_FPU`` One if processor has floating point unit
``HAS_MMX`` One if processor supports MMX instructions
diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst
index f3326b832..c3b3e7370 100644
--- a/Help/command/cmake_minimum_required.rst
+++ b/Help/command/cmake_minimum_required.rst
@@ -7,6 +7,9 @@ Require a minimum version of cmake.
cmake_minimum_required(VERSION <min>[...<max>] [FATAL_ERROR])
+.. versionadded:: 3.12
+ The optional ``<max>`` version.
+
Sets the minimum required version of cmake for a project.
Also updates the policy settings as explained below.
diff --git a/Help/command/cmake_parse_arguments.rst b/Help/command/cmake_parse_arguments.rst
index 8803ec8bd..7c85da610 100644
--- a/Help/command/cmake_parse_arguments.rst
+++ b/Help/command/cmake_parse_arguments.rst
@@ -1,8 +1,6 @@
cmake_parse_arguments
---------------------
-.. versionadded:: 3.5
-
Parse function or macro arguments.
.. code-block:: cmake
@@ -13,6 +11,10 @@ Parse function or macro arguments.
cmake_parse_arguments(PARSE_ARGV <N> <prefix> <options>
<one_value_keywords> <multi_value_keywords>)
+.. versionadded:: 3.5
+ This command is implemented natively. Previously, it has been defined in the
+ module :module:`CMakeParseArguments`.
+
This command is for use in macros or functions.
It processes the arguments given to that macro or function,
and defines a set of variables which hold the values of the
@@ -21,11 +23,12 @@ respective options.
The first signature reads processes arguments passed in the ``<args>...``.
This may be used in either a :command:`macro` or a :command:`function`.
-The ``PARSE_ARGV`` signature is only for use in a :command:`function`
-body. In this case the arguments that are parsed come from the
-``ARGV#`` variables of the calling function. The parsing starts with
-the ``<N>``-th argument, where ``<N>`` is an unsigned integer. This allows for
-the values to have special characters like ``;`` in them.
+.. versionadded:: 3.7
+ The ``PARSE_ARGV`` signature is only for use in a :command:`function`
+ body. In this case the arguments that are parsed come from the
+ ``ARGV#`` variables of the calling function. The parsing starts with
+ the ``<N>``-th argument, where ``<N>`` is an unsigned integer.
+ This allows for the values to have special characters like ``;`` in them.
The ``<options>`` argument contains all options for the respective macro,
i.e. keywords which can be used when calling the macro without any value
@@ -40,12 +43,11 @@ The ``<multi_value_keywords>`` argument contains all keywords for this
macro which can be followed by more than one value, like e.g. the
``TARGETS`` or ``FILES`` keywords of the :command:`install` command.
-.. note::
-
- All keywords shall be unique. I.e. every keyword shall only be specified
- once in either ``<options>``, ``<one_value_keywords>`` or
- ``<multi_value_keywords>``. A warning will be emitted if uniqueness is
- violated.
+.. versionchanged:: 3.5
+ All keywords shall be unique. I.e. every keyword shall only be specified
+ once in either ``<options>``, ``<one_value_keywords>`` or
+ ``<multi_value_keywords>``. A warning will be emitted if uniqueness is
+ violated.
When done, ``cmake_parse_arguments`` will consider for each of the
keywords listed in ``<options>``, ``<one_value_keywords>`` and
@@ -61,10 +63,12 @@ All remaining arguments are collected in a variable
were recognized. This can be checked afterwards to see
whether your macro was called with unrecognized parameters.
-``<one_value_keywords>`` and ``<multi_value_keywords>`` that were given no
-values at all are collected in a variable ``<prefix>_KEYWORDS_MISSING_VALUES``
-that will be undefined if all keywords received values. This can be checked
-to see if there were keywords without any values given.
+.. versionadded:: 3.15
+ ``<one_value_keywords>`` and ``<multi_value_keywords>`` that were given no
+ values at all are collected in a variable
+ ``<prefix>_KEYWORDS_MISSING_VALUES`` that will be undefined if all keywords
+ received values. This can be checked to see if there were keywords without
+ any values given.
Consider the following example macro, ``my_install()``, which takes similar
arguments to the real :command:`install` command:
diff --git a/Help/command/cmake_path.rst b/Help/command/cmake_path.rst
new file mode 100644
index 000000000..a8999f35b
--- /dev/null
+++ b/Help/command/cmake_path.rst
@@ -0,0 +1,784 @@
+cmake_path
+----------
+
+.. versionadded:: 3.20
+
+This command is for the manipulation of paths. Only syntactic aspects of
+paths are handled, there is no interaction of any kind with any underlying
+file system. The path may represent a non-existing path or even one that
+is not allowed to exist on the current file system or platform.
+For operations that do interact with the filesystem, see the :command:`file`
+command.
+
+.. note::
+
+ The ``cmake_path`` command handles paths in the format of the build system
+ (i.e. the host platform), not the target system. When cross-compiling,
+ if the path contains elements that are not representable on the host
+ platform (e.g. a drive letter when the host is not Windows), the results
+ will be unpredictable.
+
+Synopsis
+^^^^^^^^
+
+.. parsed-literal::
+
+ `Conventions`_
+
+ `Path Structure And Terminology`_
+
+ `Normalization`_
+
+ `Decomposition`_
+ cmake_path(`GET`_ <path-var> :ref:`ROOT_NAME <GET_ROOT_NAME>` <out-var>)
+ cmake_path(`GET`_ <path-var> :ref:`ROOT_DIRECTORY <GET_ROOT_DIRECTORY>` <out-var>)
+ cmake_path(`GET`_ <path-var> :ref:`ROOT_PATH <GET_ROOT_PATH>` <out-var>)
+ cmake_path(`GET`_ <path-var> :ref:`FILENAME <GET_FILENAME>` <out-var>)
+ cmake_path(`GET`_ <path-var> :ref:`EXTENSION <GET_EXTENSION>` [LAST_ONLY] <out-var>)
+ cmake_path(`GET`_ <path-var> :ref:`STEM <GET_STEM>` [LAST_ONLY] <out-var>)
+ cmake_path(`GET`_ <path-var> :ref:`RELATIVE_PART <GET_RELATIVE_PART>` <out-var>)
+ cmake_path(`GET`_ <path-var> :ref:`PARENT_PATH <GET_PARENT_PATH>` <out-var>)
+
+ `Query`_
+ cmake_path(`HAS_ROOT_NAME`_ <path-var> <out-var>)
+ cmake_path(`HAS_ROOT_DIRECTORY`_ <path-var> <out-var>)
+ cmake_path(`HAS_ROOT_PATH`_ <path-var> <out-var>)
+ cmake_path(`HAS_FILENAME`_ <path-var> <out-var>)
+ cmake_path(`HAS_EXTENSION`_ <path-var> <out-var>)
+ cmake_path(`HAS_STEM`_ <path-var> <out-var>)
+ cmake_path(`HAS_RELATIVE_PART`_ <path-var> <out-var>)
+ cmake_path(`HAS_PARENT_PATH`_ <path-var> <out-var>)
+ cmake_path(`IS_ABSOLUTE`_ <path-var> <out-var>)
+ cmake_path(`IS_RELATIVE`_ <path-var> <out-var>)
+ cmake_path(`IS_PREFIX`_ <path-var> <input> [NORMALIZE] <out-var>)
+ cmake_path(`COMPARE`_ <input1> <OP> <input2> <out-var>)
+
+ `Modification`_
+ cmake_path(:ref:`SET <cmake_path-SET>` <path-var> [NORMALIZE] <input>)
+ cmake_path(`APPEND`_ <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
+ cmake_path(`APPEND_STRING`_ <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
+ cmake_path(`REMOVE_FILENAME`_ <path-var> [OUTPUT_VARIABLE <out-var>])
+ cmake_path(`REPLACE_FILENAME`_ <path-var> <input> [OUTPUT_VARIABLE <out-var>])
+ cmake_path(`REMOVE_EXTENSION`_ <path-var> [LAST_ONLY] [OUTPUT_VARIABLE <out-var>])
+ cmake_path(`REPLACE_EXTENSION`_ <path-var> [LAST_ONLY] <input> [OUTPUT_VARIABLE <out-var>])
+
+ `Generation`_
+ cmake_path(`NORMAL_PATH`_ <path-var> [OUTPUT_VARIABLE <out-var>])
+ cmake_path(`RELATIVE_PATH`_ <path-var> [BASE_DIRECTORY <input>] [OUTPUT_VARIABLE <out-var>])
+ cmake_path(`ABSOLUTE_PATH`_ <path-var> [BASE_DIRECTORY <input>] [NORMALIZE] [OUTPUT_VARIABLE <out-var>])
+
+ `Native Conversion`_
+ cmake_path(`NATIVE_PATH`_ <path-var> [NORMALIZE] <out-var>)
+ cmake_path(`CONVERT`_ <input> `TO_CMAKE_PATH_LIST`_ <out-var>)
+ cmake_path(`CONVERT`_ <input> `TO_NATIVE_PATH_LIST`_ <out-var>)
+
+ `Hashing`_
+ cmake_path(`HASH`_ <path-var> <out-var>)
+
+Conventions
+^^^^^^^^^^^
+
+The following conventions are used in this command's documentation:
+
+``<path-var>``
+ Always the name of a variable. For commands that expect a ``<path-var>``
+ as input, the variable must exist and it is expected to hold a single path.
+
+``<input>``
+ A string literal which may contain a path, path fragment, or multiple paths
+ with a special separator depending on the command. See the description of
+ each command to see how this is interpreted.
+
+``<input>...``
+ Zero or more string literal arguments.
+
+``<out-var>``
+ The name of a variable into which the result of a command will be written.
+
+
+Path Structure And Terminology
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A path has the following structure (all components are optional, with some
+constraints):
+
+::
+
+ root-name root-directory-separator (item-name directory-separator)* filename
+
+``root-name``
+ Identifies the root on a filesystem with multiple roots (such as ``"C:"``
+ or ``"//myserver"``). It is optional.
+
+``root-directory-separator``
+ A directory separator that, if present, indicates that this path is
+ absolute. If it is missing and the first element other than the
+ ``root-name`` is an ``item-name``, then the path is relative.
+
+``item-name``
+ A sequence of characters that aren't directory separators. This name may
+ identify a file, a hard link, a symbolic link, or a directory. Two special
+ cases are recognized:
+
+ * The item name consisting of a single dot character ``.`` is a
+ directory name that refers to the current directory.
+
+ * The item name consisting of two dot characters ``..`` is a
+ directory name that refers to the parent directory.
+
+ The ``(...)*`` pattern shown above is to indicate that there can be zero
+ or more item names, with multiple items separated by a
+ ``directory-separator``. The ``()*`` characters are not part of the path.
+
+``directory-separator``
+ The only recognized directory separator is a forward slash character ``/``.
+ If this character is repeated, it is treated as a single directory
+ separator. In other words, ``/usr///////lib`` is the same as ``/usr/lib``.
+
+.. _FILENAME_DEF:
+.. _EXTENSION_DEF:
+.. _STEM_DEF:
+
+``filename``
+ A path has a ``filename`` if it does not end with a ``directory-separator``.
+ The ``filename`` is effectively the last ``item-name`` of the path, so it
+ can also be a hard link, symbolic link or a directory.
+
+ A ``filename`` can have an *extension*. By default, the extension is
+ defined as the sub-string beginning at the left-most period (including
+ the period) and until the end of the ``filename``. In commands that
+ accept a ``LAST_ONLY`` keyword, ``LAST_ONLY`` changes the interpretation
+ to the sub-string beginning at the right-most period.
+
+ The following exceptions apply to the above interpretation:
+
+ * If the first character in the ``filename`` is a period, that period is
+ ignored (i.e. a ``filename`` like ``".profile"`` is treated as having
+ no extension).
+
+ * If the ``filename`` is either ``.`` or ``..``, it has no extension.
+
+ The *stem* is the part of the ``filename`` before the extension.
+
+Some commands refer to a ``root-path``. This is the concatenation of
+``root-name`` and ``root-directory-separator``, either or both of which can
+be empty. A ``relative-part`` refers to the full path with any ``root-path``
+removed.
+
+
+Creating A Path Variable
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+While a path can be created with care using an ordinary :command:`set`
+command, it is recommended to use :ref:`cmake_path(SET) <cmake_path-SET>`
+instead, as it automatically converts the path to the required form where
+required. The :ref:`cmake_path(APPEND) <APPEND>` subcommand may
+be another suitable alternative where a path needs to be constructed by
+joining fragments. The following example compares the three methods for
+constructing the same path:
+
+.. code-block:: cmake
+
+ set(path1 "${CMAKE_CURRENT_SOURCE_DIR}/data")
+
+ cmake_path(SET path2 "${CMAKE_CURRENT_SOURCE_DIR}/data")
+
+ cmake_path(APPEND path3 "${CMAKE_CURRENT_SOURCE_DIR}" "data")
+
+`Modification`_ and `Generation`_ sub-commands can either store the result
+in-place, or in a separate variable named after an ``OUTPUT_VARIABLE``
+keyword. All other sub-commands store the result in a mandatory ``<out-var>``
+variable.
+
+.. _Normalization:
+
+Normalization
+^^^^^^^^^^^^^
+
+Some sub-commands support *normalizing* a path. The algorithm used to
+normalize a path is as follows:
+
+1. If the path is empty, stop (the normalized form of an empty path is
+ also an empty path).
+2. Replace each ``directory-separator``, which may consist of multiple
+ separators, with a single ``/`` (``/a///b --> /a/b``).
+3. Remove each solitary period (``.``) and any immediately following
+ ``directory-separator`` (``/a/./b/. --> /a/b``).
+4. Remove each ``item-name`` (other than ``..``) that is immediately
+ followed by a ``directory-separator`` and a ``..``, along with any
+ immediately following ``directory-separator`` (``/a/b/../c --> a/c``).
+5. If there is a ``root-directory``, remove any ``..`` and any
+ ``directory-separators`` immediately following them. The parent of the
+ root directory is treated as still the root directory (``/../a --> /a``).
+6. If the last ``item-name`` is ``..``, remove any trailing
+ ``directory-separator`` (``../ --> ..``).
+7. If the path is empty by this stage, add a ``dot`` (normal form of ``./``
+ is ``.``).
+
+
+Decomposition
+^^^^^^^^^^^^^
+
+.. _GET:
+.. _GET_ROOT_NAME:
+.. _GET_ROOT_DIRECTORY:
+.. _GET_ROOT_PATH:
+.. _GET_FILENAME:
+.. _GET_EXTENSION:
+.. _GET_STEM:
+.. _GET_RELATIVE_PART:
+.. _GET_PARENT_PATH:
+
+The following forms of the ``GET`` subcommand each retrieve a different
+component or group of components from a path. See
+`Path Structure And Terminology`_ for the meaning of each path component.
+
+::
+
+ cmake_path(GET <path-var> ROOT_NAME <out-var>)
+ cmake_path(GET <path-var> ROOT_DIRECTORY <out-var>)
+ cmake_path(GET <path-var> ROOT_PATH <out-var>)
+ cmake_path(GET <path-var> FILENAME <out-var>)
+ cmake_path(GET <path-var> EXTENSION [LAST_ONLY] <out-var>)
+ cmake_path(GET <path-var> STEM [LAST_ONLY] <out-var>)
+ cmake_path(GET <path-var> RELATIVE_PART <out-var>)
+ cmake_path(GET <path-var> PARENT_PATH <out-var>)
+
+If a requested component is not present in the path, an empty string will be
+stored in ``<out-var>``. For example, only Windows systems have the concept
+of a ``root-name``, so when the host machine is non-Windows, the ``ROOT_NAME``
+subcommand will always return an empty string.
+
+For ``PARENT_PATH``, if the `HAS_RELATIVE_PART`_ subcommand returns false,
+the result is a copy of ``<path-var>``. Note that this implies that a root
+directory is considered to have a parent, with that parent being itself.
+Where `HAS_RELATIVE_PART`_ returns true, the result will essentially be
+``<path-var>`` with one less element.
+
+Root examples
+"""""""""""""
+
+.. code-block:: cmake
+
+ set(path "c:/a")
+
+ cmake_path(GET path ROOT_NAME rootName)
+ cmake_path(GET path ROOT_DIRECTORY rootDir)
+ cmake_path(GET path ROOT_PATH rootPath)
+
+ message("Root name is \"${rootName}\"")
+ message("Root directory is \"${rootDir}\"")
+ message("Root path is \"${rootPath}\"")
+
+::
+
+ Root name is "c:"
+ Root directory is "/"
+ Root path is "c:/"
+
+Filename examples
+"""""""""""""""""
+
+.. code-block:: cmake
+
+ set(path "/a/b")
+ cmake_path(GET path FILENAME filename)
+ message("First filename is \"${filename}\"")
+
+ # Trailing slash means filename is empty
+ set(path "/a/b/")
+ cmake_path(GET path FILENAME filename)
+ message("Second filename is \"${filename}\"")
+
+::
+
+ First filename is "b"
+ Second filename is ""
+
+Extension and stem examples
+"""""""""""""""""""""""""""
+
+.. code-block:: cmake
+
+ set(path "name.ext1.ext2")
+
+ cmake_path(GET path EXTENSION fullExt)
+ cmake_path(GET path STEM fullStem)
+ message("Full extension is \"${fullExt}\"")
+ message("Full stem is \"${fullStem}\"")
+
+ # Effect of LAST_ONLY
+ cmake_path(GET path EXTENSION LAST_ONLY lastExt)
+ cmake_path(GET path STEM LAST_ONLY lastStem)
+ message("Last extension is \"${lastExt}\"")
+ message("Last stem is \"${lastStem}\"")
+
+ # Special cases
+ set(dotPath "/a/.")
+ set(dotDotPath "/a/..")
+ set(someMorePath "/a/.some.more")
+ cmake_path(GET dotPath EXTENSION dotExt)
+ cmake_path(GET dotPath STEM dotStem)
+ cmake_path(GET dotDotPath EXTENSION dotDotExt)
+ cmake_path(GET dotDotPath STEM dotDotStem)
+ cmake_path(GET dotMorePath EXTENSION someMoreExt)
+ cmake_path(GET dotMorePath STEM someMoreStem)
+ message("Dot extension is \"${dotExt}\"")
+ message("Dot stem is \"${dotStem}\"")
+ message("Dot-dot extension is \"${dotDotExt}\"")
+ message("Dot-dot stem is \"${dotDotStem}\"")
+ message(".some.more extension is \"${someMoreExt}\"")
+ message(".some.more stem is \"${someMoreStem}\"")
+
+::
+
+ Full extension is ".ext1.ext2"
+ Full stem is "name"
+ Last extension is ".ext2"
+ Last stem is "name.ext1"
+ Dot extension is ""
+ Dot stem is "."
+ Dot-dot extension is ""
+ Dot-dot stem is ".."
+ .some.more extension is ".more"
+ .some.more stem is ".some"
+
+Relative part examples
+""""""""""""""""""""""
+
+.. code-block:: cmake
+
+ set(path "c:/a/b")
+ cmake_path(GET path RELATIVE_PART result)
+ message("Relative part is \"${result}\"")
+
+ set(path "c/d")
+ cmake_path(GET path RELATIVE_PART result)
+ message("Relative part is \"${result}\"")
+
+ set(path "/")
+ cmake_path(GET path RELATIVE_PART result)
+ message("Relative part is \"${result}\"")
+
+::
+
+ Relative part is "a/b"
+ Relative part is "c/d"
+ Relative part is ""
+
+Path traversal examples
+"""""""""""""""""""""""
+
+.. code-block:: cmake
+
+ set(path "c:/a/b")
+ cmake_path(GET path PARENT_PATH result)
+ message("Parent path is \"${result}\"")
+
+ set(path "c:/")
+ cmake_path(GET path PARENT_PATH result)
+ message("Parent path is \"${result}\"")
+
+::
+
+ Parent path is "c:/a"
+ Parent path is "c:/"
+
+
+Query
+^^^^^
+
+Each of the ``GET`` subcommands has a corresponding ``HAS_...``
+subcommand which can be used to discover whether a particular path
+component is present. See `Path Structure And Terminology`_ for the
+meaning of each path component.
+
+.. _HAS_ROOT_NAME:
+.. _HAS_ROOT_DIRECTORY:
+.. _HAS_ROOT_PATH:
+.. _HAS_FILENAME:
+.. _HAS_EXTENSION:
+.. _HAS_STEM:
+.. _HAS_RELATIVE_PART:
+.. _HAS_PARENT_PATH:
+
+::
+
+ cmake_path(HAS_ROOT_NAME <path-var> <out-var>)
+ cmake_path(HAS_ROOT_DIRECTORY <path-var> <out-var>)
+ cmake_path(HAS_ROOT_PATH <path-var> <out-var>)
+ cmake_path(HAS_FILENAME <path-var> <out-var>)
+ cmake_path(HAS_EXTENSION <path-var> <out-var>)
+ cmake_path(HAS_STEM <path-var> <out-var>)
+ cmake_path(HAS_RELATIVE_PART <path-var> <out-var>)
+ cmake_path(HAS_PARENT_PATH <path-var> <out-var>)
+
+Each of the above follows the predictable pattern of setting ``<out-var>``
+to true if the path has the associated component, or false otherwise.
+Note the following special cases:
+
+* For ``HAS_ROOT_PATH``, a true result will only be returned if at least one
+ of ``root-name`` or ``root-directory`` is non-empty.
+
+* For ``HAS_PARENT_PATH``, the root directory is also considered to have a
+ parent, which will be itself. The result is true except if the path
+ consists of just a :ref:`filename <FILENAME_DEF>`.
+
+.. _IS_ABSOLUTE:
+
+::
+
+ cmake_path(IS_ABSOLUTE <path-var> <out-var>)
+
+Sets ``<out-var>`` to true if ``<path-var>`` is absolute. An absolute path
+is a path that unambiguously identifies the location of a file without
+reference to an additional starting location. On Windows, this means the
+path must have both a ``root-name`` and a ``root-directory-separator`` to be
+considered absolute. On other platforms, just a ``root-directory-separator``
+is sufficient. Note that this means on Windows, ``IS_ABSOLUTE`` can be
+false while ``HAS_ROOT_DIRECTORY`` can be true.
+
+.. _IS_RELATIVE:
+
+::
+
+ cmake_path(IS_RELATIVE <path-var> <out-var>)
+
+This will store the opposite of ``IS_ABSOLUTE`` in ``<out-var>``.
+
+.. _IS_PREFIX:
+
+::
+
+ cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)
+
+Checks if ``<path-var>`` is the prefix of ``<input>``.
+
+When the ``NORMALIZE`` option is specified, ``<path-var>`` and ``<input>``
+are :ref:`normalized <Normalization>` before the check.
+
+.. code-block:: cmake
+
+ set(path "/a/b/c/d")
+ cmake_path(IS_PREFIX path "/a/b" result) # result = true
+ cmake_path(IS_PREFIX path "/x/y/z" result) # result = false
+
+ set(path "/a/b")
+ cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE result) # result = true
+
+.. _COMPARE:
+
+::
+
+ cmake_path(COMPARE <input1> EQUAL <input2> <out-var>)
+ cmake_path(COMPARE <input1> NOT_EQUAL <input2> <out-var>)
+
+Compares the lexical representations of two paths provided as string literals.
+No normalization is performed on either path. Equality is determined
+according to the following pseudo-code logic:
+
+::
+
+ if(NOT <input1>.root_name() STREQUAL <input2>.root_name())
+ return FALSE
+
+ if(<input1>.has_root_directory() XOR <input2>.has_root_directory())
+ return FALSE
+
+ Return FALSE if a relative portion of <input1> is not lexicographically
+ equal to the relative portion of <input2>. This comparison is performed path
+ component-wise. If all of the components compare equal, then return TRUE.
+
+.. note::
+ Unlike most other ``cmake_path()`` subcommands, the ``COMPARE`` subcommand
+ takes literal strings as input, not the names of variables.
+
+
+Modification
+^^^^^^^^^^^^
+
+.. _cmake_path-SET:
+
+::
+
+ cmake_path(SET <path-var> [NORMALIZE] <input>)
+
+Assign the ``<input>`` path to ``<path-var>``. If ``<input>`` is a native
+path, it is converted into a cmake-style path with forward-slashes
+(``/``). On Windows, the long filename marker is taken into account.
+
+When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
+<Normalization>` before the conversion.
+
+For example:
+
+.. code-block:: cmake
+
+ set(native_path "c:\\a\\b/..\\c")
+ cmake_path(SET path "${native_path}")
+ message("CMake path is \"${path}\"")
+
+ cmake_path(SET path NORMALIZE "${native_path}")
+ message("Normalized CMake path is \"${path}\"")
+
+Output::
+
+ CMake path is "c:/a/b/../c"
+ Normalized CMake path is "c:/a/c"
+
+.. _APPEND:
+
+::
+
+ cmake_path(APPEND <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
+
+Append all the ``<input>`` arguments to the ``<path-var>`` using ``/`` as
+the ``directory-separator``. Depending on the ``<input>``, the previous
+contents of ``<path-var>`` may be discarded. For each ``<input>`` argument,
+the following algorithm (pseudo-code) applies:
+
+::
+
+ # <path> is the contents of <path-var>
+
+ if(<input>.is_absolute() OR
+ (<input>.has_root_name() AND
+ NOT <input>.root_name() STREQUAL <path>.root_name()))
+ replace <path> with <input>
+ return()
+ endif()
+
+ if(<input>.has_root_directory())
+ remove any root-directory and the entire relative path from <path>
+ elseif(<path>.has_filename() OR
+ (NOT <path-var>.has_root_directory() OR <path>.is_absolute()))
+ append directory-separator to <path>
+ endif()
+
+ append <input> omitting any root-name to <path>
+
+.. _APPEND_STRING:
+
+::
+
+ cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
+
+Append all the ``<input>`` arguments to the ``<path-var>`` without adding any
+``directory-separator``.
+
+.. _REMOVE_FILENAME:
+
+::
+
+ cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>])
+
+Removes the :ref:`filename <FILENAME_DEF>` component (as returned by
+:ref:`GET ... FILENAME <GET_FILENAME>`) from ``<path-var>``. After removal,
+any trailing ``directory-separator`` is left alone, if present.
+
+If ``OUTPUT_VARIABLE`` is not given, then after this function returns,
+`HAS_FILENAME`_ returns false for ``<path-var>``.
+
+For example:
+
+.. code-block:: cmake
+
+ set(path "/a/b")
+ cmake_path(REMOVE_FILENAME path)
+ message("First path is \"${path}\"")
+
+ # filename is now already empty, the following removes nothing
+ cmake_path(REMOVE_FILENAME path)
+ message("Second path is \"${result}\"")
+
+Output::
+
+ First path is "/a/"
+ Second path is "/a/"
+
+.. _REPLACE_FILENAME:
+
+::
+
+ cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>])
+
+Replaces the :ref:`filename <FILENAME_DEF>` component from ``<path-var>``
+with ``<input>``. If ``<path-var>`` has no filename component (i.e.
+`HAS_FILENAME`_ returns false), the path is unchanged. The operation is
+equivalent to the following:
+
+.. code-block:: cmake
+
+ cmake_path(HAS_FILENAME path has_filename)
+ if(has_filename)
+ cmake_path(REMOVE_FILENAME path)
+ cmake_path(APPEND path input);
+ endif()
+
+.. _REMOVE_EXTENSION:
+
+::
+
+ cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY]
+ [OUTPUT_VARIABLE <out-var>])
+
+Removes the :ref:`extension <EXTENSION_DEF>`, if any, from ``<path-var>``.
+
+.. _REPLACE_EXTENSION:
+
+::
+
+ cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input>
+ [OUTPUT_VARIABLE <out-var>])
+
+Replaces the :ref:`extension <EXTENSION_DEF>` with ``<input>``. Its effect
+is equivalent to the following:
+
+.. code-block:: cmake
+
+ cmake_path(REMOVE_EXTENSION path)
+ if(NOT "input" MATCHES "^\\.")
+ cmake_path(APPEND_STRING path ".")
+ endif()
+ cmake_path(APPEND_STRING path "input")
+
+
+Generation
+^^^^^^^^^^
+
+.. _NORMAL_PATH:
+
+::
+
+ cmake_path(NORMAL_PATH <path-var> [OUTPUT_VARIABLE <out-var>])
+
+Normalize ``<path-var>`` according the steps described in :ref:`Normalization`.
+
+.. _cmake_path-RELATIVE_PATH:
+.. _RELATIVE_PATH:
+
+::
+
+ cmake_path(RELATIVE_PATH <path-var> [BASE_DIRECTORY <input>]
+ [OUTPUT_VARIABLE <out-var>])
+
+Modifies ``<path-var>`` to make it relative to the ``BASE_DIRECTORY`` argument.
+If ``BASE_DIRECTORY`` is not specified, the default base directory will be
+:variable:`CMAKE_CURRENT_SOURCE_DIR`.
+
+For reference, the algorithm used to compute the relative path is the same
+as that used by C++
+`std::filesystem::path::lexically_relative
+<https://en.cppreference.com/w/cpp/filesystem/path/lexically_normal>`_.
+
+.. _ABSOLUTE_PATH:
+
+::
+
+ cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE]
+ [OUTPUT_VARIABLE <out-var>])
+
+If ``<path-var>`` is a relative path (`IS_RELATIVE`_ is true), it is evaluated
+relative to the given base directory specified by ``BASE_DIRECTORY`` option.
+If ``BASE_DIRECTORY`` is not specified, the default base directory will be
+:variable:`CMAKE_CURRENT_SOURCE_DIR`.
+
+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
+:command:`file(REAL_PATH)` command instead.
+
+Native Conversion
+^^^^^^^^^^^^^^^^^
+
+For commands in this section, *native* refers to the host platform, not the
+target platform when cross-compiling.
+
+.. _cmake_path-NATIVE_PATH:
+.. _NATIVE_PATH:
+
+::
+
+ cmake_path(NATIVE_PATH <path-var> [NORMALIZE] <out-var>)
+
+Converts a cmake-style ``<path-var>`` into a native path with
+platform-specific slashes (``\`` on Windows hosts and ``/`` elsewhere).
+
+When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
+<Normalization>` before the conversion.
+
+.. _CONVERT:
+.. _cmake_path-TO_CMAKE_PATH_LIST:
+.. _TO_CMAKE_PATH_LIST:
+
+::
+
+ cmake_path(CONVERT <input> TO_CMAKE_PATH_LIST <out-var> [NORMALIZE])
+
+Converts a native ``<input>`` path into a cmake-style path with forward
+slashes (``/``). On Windows hosts, the long filename marker is taken into
+account. The input can be a single path or a system search path like
+``$ENV{PATH}``. A search path will be converted to a cmake-style list
+separated by ``;`` characters (on non-Windows platforms, this essentially
+means ``:`` separators are replaced with ``;``). The result of the
+conversion is stored in the ``<out-var>`` variable.
+
+When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
+<Normalization>` before the conversion.
+
+.. note::
+ Unlike most other ``cmake_path()`` subcommands, the ``CONVERT`` subcommand
+ takes a literal string as input, not the name of a variable.
+
+.. _cmake_path-TO_NATIVE_PATH_LIST:
+.. _TO_NATIVE_PATH_LIST:
+
+::
+
+ cmake_path(CONVERT <input> TO_NATIVE_PATH_LIST <out-var> [NORMALIZE])
+
+Converts a cmake-style ``<input>`` path into a native path with
+platform-specific slashes (``\`` on Windows hosts and ``/`` elsewhere).
+The input can be a single path or a cmake-style list. A list will be
+converted into a native search path (``;``-separated on Windows,
+``:``-separated on other platforms). The result of the conversion is
+stored in the ``<out-var>`` variable.
+
+When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
+<Normalization>` before the conversion.
+
+.. note::
+ Unlike most other ``cmake_path()`` subcommands, the ``CONVERT`` subcommand
+ takes a literal string as input, not the name of a variable.
+
+For example:
+
+.. code-block:: cmake
+
+ set(paths "/a/b/c" "/x/y/z")
+ cmake_path(CONVERT "${paths}" TO_NATIVE_PATH_LIST native_paths)
+ message("Native path list is \"${native_paths}\"")
+
+Output on Windows::
+
+ Native path list is "\a\b\c;\x\y\z"
+
+Output on all other platforms::
+
+ Native path list is "/a/b/c:/x/y/z"
+
+Hashing
+^^^^^^^
+
+.. _HASH:
+
+::
+
+ cmake_path(HASH <path-var> <out-var>)
+
+Compute a hash value of ``<path-var>`` such that for two paths ``p1`` and
+``p2`` that compare equal (:ref:`COMPARE ... EQUAL <COMPARE>`), the hash
+value of ``p1`` is equal to the hash value of ``p2``. The path is always
+:ref:`normalized <Normalization>` before the hash is computed.
diff --git a/Help/command/cmake_policy.rst b/Help/command/cmake_policy.rst
index 4bc7807bb..94060d9b8 100644
--- a/Help/command/cmake_policy.rst
+++ b/Help/command/cmake_policy.rst
@@ -28,6 +28,9 @@ encourage projects to set policies based on CMake versions:
cmake_policy(VERSION <min>[...<max>])
+.. versionadded:: 3.12
+ The optional ``<max>`` version.
+
``<min>`` and the optional ``<max>`` are each CMake versions of the form
``major.minor[.patch[.tweak]]``, and the ``...`` is literal. The ``<min>``
version must be at least ``2.4`` and at most the running version of CMake.
diff --git a/Help/command/configure_file.rst b/Help/command/configure_file.rst
index c59995ae2..63ea84d1b 100644
--- a/Help/command/configure_file.rst
+++ b/Help/command/configure_file.rst
@@ -6,8 +6,9 @@ Copy a file to another location and modify its contents.
.. code-block:: cmake
configure_file(<input> <output>
+ [FILE_PERMISSIONS <permissions>...]
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
- [NO_SOURCE_PERMISSIONS]
+ [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
Copies an ``<input>`` file to an ``<output>`` file and substitutes
@@ -37,22 +38,24 @@ 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.
-The result lines (with the exception of the ``#undef`` comments) can be
-indented using spaces and/or tabs between the ``#`` character
-and the ``cmakedefine`` or ``cmakedefine01`` words. This whitespace
-indentation will be preserved in the output lines:
-.. code-block:: c
+.. versionadded:: 3.10
+ The result lines (with the exception of the ``#undef`` comments) can be
+ indented using spaces and/or tabs between the ``#`` character
+ and the ``cmakedefine`` or ``cmakedefine01`` words. This whitespace
+ indentation will be preserved in the output lines:
- # cmakedefine VAR
- # cmakedefine01 VAR
+ .. code-block:: c
-will be replaced, if ``VAR`` is defined, with
+ # cmakedefine VAR
+ # cmakedefine01 VAR
-.. code-block:: c
+ will be replaced, if ``VAR`` is defined, with
- # define VAR
- # define VAR 1
+ .. code-block:: c
+
+ # define VAR
+ # define VAR 1
If the input file is modified the build system will re-run CMake to
re-configure the file and generate the build system again.
@@ -72,6 +75,9 @@ The arguments are:
If the path names an existing directory the output file is placed
in that directory with the same file name as the input file.
+``FILE_PERMISSIONS <permissions>...``
+ Use user provided permissions for the output file.
+
``COPYONLY``
Copy the file without replacing any variable references or other
content. This option may not be used with ``NEWLINE_STYLE``.
@@ -84,10 +90,17 @@ The arguments are:
This is useful for configuring scripts that use ``${VAR}`` syntax.
``NO_SOURCE_PERMISSIONS``
+ .. versionadded:: 3.19
+
Does not transfer the file permissions of the original file to the copy.
The copied file permissions default to the standard 644 value
(-rw-r--r--).
+``USE_SOURCE_PERMISSIONS``
+ .. versionadded:: 3.20
+
+ Transfer the file permissions of the original file to the output file.
+
``NEWLINE_STYLE <style>``
Specify the newline style for the output file. Specify
``UNIX`` or ``LF`` for ``\n`` newlines, or specify
diff --git a/Help/command/ctest_build.rst b/Help/command/ctest_build.rst
index 66e1844e9..4d6dc5a43 100644
--- a/Help/command/ctest_build.rst
+++ b/Help/command/ctest_build.rst
@@ -50,7 +50,10 @@ The options are:
for an example.
``PROJECT_NAME <project-name>``
- Ignored. This was once used but is no longer needed.
+ Ignored since CMake 3.0.
+
+ .. versionchanged:: 3.14
+ This value is no longer required.
``TARGET <target-name>``
Specify the name of a target to build. If not specified the
@@ -68,10 +71,14 @@ The options are:
Store the return value of the native build tool in the given variable.
``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.7
+
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.
``QUIET``
+ .. versionadded:: 3.3
+
Suppress any CTest-specific non-error output that would have been
printed to the console otherwise. The summary of warnings / errors,
as well as the output from the native build tool is unaffected by
diff --git a/Help/command/ctest_configure.rst b/Help/command/ctest_configure.rst
index 2dea07b16..95712aac0 100644
--- a/Help/command/ctest_configure.rst
+++ b/Help/command/ctest_configure.rst
@@ -37,10 +37,14 @@ The options are:
configuration tool.
``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.7
+
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.
``QUIET``
+ .. versionadded:: 3.3
+
Suppress any CTest-specific non-error messages that would have
otherwise been printed to the console. Output from the underlying
configure command is not affected.
diff --git a/Help/command/ctest_coverage.rst b/Help/command/ctest_coverage.rst
index d50f63498..a6c643bbc 100644
--- a/Help/command/ctest_coverage.rst
+++ b/Help/command/ctest_coverage.rst
@@ -37,10 +37,14 @@ The options are:
ran without error and non-zero otherwise.
``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.7
+
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.
``QUIET``
+ .. versionadded:: 3.3
+
Suppress any CTest-specific non-error output that would have been
printed to the console otherwise. The summary indicating how many
lines of code were covered is unaffected by this option.
diff --git a/Help/command/ctest_memcheck.rst b/Help/command/ctest_memcheck.rst
index 288b65a25..f655c2eb2 100644
--- a/Help/command/ctest_memcheck.rst
+++ b/Help/command/ctest_memcheck.rst
@@ -35,4 +35,6 @@ Most options are the same as those for the :command:`ctest_test` command.
The options unique to this command are:
``DEFECT_COUNT <defect-count-var>``
+ .. versionadded:: 3.8
+
Store in the ``<defect-count-var>`` the number of defects found.
diff --git a/Help/command/ctest_start.rst b/Help/command/ctest_start.rst
index f0704aca5..c0f3c6d3c 100644
--- a/Help/command/ctest_start.rst
+++ b/Help/command/ctest_start.rst
@@ -29,8 +29,11 @@ The parameters are as follows:
``GROUP <group>``
If ``GROUP`` is used, the submissions will go to the specified group on the
CDash server. If no ``GROUP`` is specified, the name of the model is used by
- default. This replaces the deprecated option ``TRACK``. Despite the name
- change its behavior is unchanged.
+ default.
+
+ .. versionchanged:: 3.16
+ This replaces the deprecated option ``TRACK``. Despite the name
+ change its behavior is unchanged.
``APPEND``
If ``APPEND`` is used, the existing ``TAG`` is used rather than creating a new
@@ -56,6 +59,8 @@ The parameters are as follows:
new model and group will be used.
``QUIET``
+ .. versionadded:: 3.3
+
If ``QUIET`` is used, CTest will suppress any non-error messages that it
otherwise would have printed to the console.
diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst
index 983fc20ce..e6d277f59 100644
--- a/Help/command/ctest_submit.rst
+++ b/Help/command/ctest_submit.rst
@@ -42,14 +42,20 @@ The options are:
Each individual file must exist at the time of the call.
``SUBMIT_URL <url>``
+ .. versionadded:: 3.14
+
The ``http`` or ``https`` URL of the dashboard server to send the submission
to. If not given, the :variable:`CTEST_SUBMIT_URL` variable is used.
``BUILD_ID <result-var>``
+ .. versionadded:: 3.15
+
Store in the ``<result-var>`` variable the ID assigned to this build by
CDash.
``HTTPHEADER <HTTP-header>``
+ .. versionadded:: 3.9
+
Specify HTTP header to be included in the request to CDash during submission.
For example, CDash can be configured to only accept submissions from
authenticated clients. In this case, you should provide a bearer token in your
@@ -73,20 +79,27 @@ The options are:
non-zero on failure.
``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.13
+
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.
``QUIET``
+ .. versionadded:: 3.3
+
Suppress all non-error messages that would have otherwise been
printed to the console.
Submit to CDash Upload API
^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.2
+
::
ctest_submit(CDASH_UPLOAD <file> [CDASH_UPLOAD_TYPE <type>]
[SUBMIT_URL <url>]
+ [BUILD_ID <result-var>]
[HTTPHEADER <header>]
[RETRY_COUNT <count>]
[RETRY_DELAY <delay>]
@@ -99,6 +112,19 @@ with a content hash of the file. If CDash does not already have the file,
then it is uploaded. Along with the file, a CDash type string is specified
to tell CDash which handler to use to process the data.
-This signature accepts the ``SUBMIT_URL``, ``BUILD_ID``, ``HTTPHEADER``,
-``RETRY_COUNT``, ``RETRY_DELAY``, ``RETURN_VALUE`` and ``QUIET`` options
-as described above.
+This signature interprets options in the same way as the first one.
+
+.. versionadded:: 3.8
+ Added the ``RETRY_COUNT``, ``RETRY_DELAY``, ``QUIET`` options.
+
+.. versionadded:: 3.9
+ Added the ``HTTPHEADER`` option.
+
+.. versionadded:: 3.13
+ Added the ``RETURN_VALUE`` option.
+
+.. versionadded:: 3.14
+ Added the ``SUBMIT_URL`` option.
+
+.. versionadded:: 3.15
+ Added the ``BUILD_ID`` option.
diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst
index 3589296ad..b4493a03d 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -68,6 +68,8 @@ The options are:
Tests not matching this expression are excluded.
``EXCLUDE_FIXTURE <regex>``
+ .. versionadded:: 3.7
+
If a test in the set of tests to be executed requires a particular fixture,
that fixture's setup and cleanup tests would normally be added to the test
set automatically. This option prevents adding setup or cleanup tests for
@@ -76,9 +78,13 @@ The options are:
setup tests that fail.
``EXCLUDE_FIXTURE_SETUP <regex>``
+ .. versionadded:: 3.7
+
Same as ``EXCLUDE_FIXTURE`` except only matching setup tests are excluded.
``EXCLUDE_FIXTURE_CLEANUP <regex>``
+ .. versionadded:: 3.7
+
Same as ``EXCLUDE_FIXTURE`` except only matching cleanup tests are excluded.
``PARALLEL_LEVEL <level>``
@@ -86,11 +92,15 @@ The options are:
be run in parallel.
``RESOURCE_SPEC_FILE <file>``
+ .. versionadded:: 3.16
+
Specify a
:ref:`resource specification file <ctest-resource-specification-file>`. See
:ref:`ctest-resource-allocation` for more information.
``TEST_LOAD <threshold>``
+ .. versionadded:: 3.4
+
While running tests in parallel, try not to start tests when they
may cause the CPU load to pass above a given threshold. If not
specified the :variable:`CTEST_TEST_LOAD` variable will be checked,
@@ -98,6 +108,8 @@ The options are:
See also the ``TestLoad`` setting in the :ref:`CTest Test Step`.
``REPEAT <mode>:<n>``
+ .. versionadded:: 3.17
+
Run tests repeatedly based on the given ``<mode>`` up to ``<n>`` times.
The modes are:
@@ -121,6 +133,8 @@ The options are:
implicit test dependencies.
``STOP_ON_FAILURE``
+ .. versionadded:: 3.18
+
Stop the execution of the tests once one has failed.
``STOP_TIME <time-of-day>``
@@ -131,10 +145,14 @@ The options are:
Store non-zero if anything went wrong.
``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.7
+
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.
``QUIET``
+ .. versionadded:: 3.3
+
Suppress any CTest-specific non-error messages that would have otherwise
been printed to the console. Output from the underlying test command is not
affected. Summary info detailing the percentage of passing tests is also
diff --git a/Help/command/ctest_update.rst b/Help/command/ctest_update.rst
index 96a11c913..63f991b5e 100644
--- a/Help/command/ctest_update.rst
+++ b/Help/command/ctest_update.rst
@@ -24,10 +24,14 @@ The options are:
updated or ``-1`` on error.
``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.13
+
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.
``QUIET``
+ .. versionadded:: 3.3
+
Tell CTest to suppress most non-error messages that it would
have otherwise printed to the console. CTest will still report
the new revision of the repository and any conflicting files
diff --git a/Help/command/ctest_upload.rst b/Help/command/ctest_upload.rst
index 39d9de1a3..ffddd0a43 100644
--- a/Help/command/ctest_upload.rst
+++ b/Help/command/ctest_upload.rst
@@ -14,9 +14,13 @@ The options are:
dashboard server.
``QUIET``
+ .. versionadded:: 3.3
+
Suppress any CTest-specific non-error output that would have been
printed to the console otherwise.
``CAPTURE_CMAKE_ERROR <result-var>``
+ .. versionadded:: 3.7
+
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.
diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index e8640eadc..ce765de68 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -12,6 +12,15 @@ variables that are created by the project command. Example languages
are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``,
``ISPC``, and ``ASM``.
+.. versionadded:: 3.8
+ Added ``CUDA`` support.
+
+.. versionadded:: 3.16
+ Added ``OBJC`` and ``OBJCXX`` support.
+
+.. versionadded:: 3.18
+ Added ``ISPC`` 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/execute_process.rst b/Help/command/execute_process.rst
index 268c3075b..82fcd46a5 100644
--- a/Help/command/execute_process.rst
+++ b/Help/command/execute_process.rst
@@ -62,6 +62,8 @@ Options:
describing an error condition.
``RESULTS_VARIABLE <variable>``
+ .. versionadded:: 3.10
+
The variable will be set to contain the result of all processes as a
:ref:`semicolon-separated list <CMake Language Lists>`, in order of the
given ``COMMAND`` arguments. Each entry will be an integer return code
@@ -75,19 +77,26 @@ Options:
``INPUT_FILE, OUTPUT_FILE``, ``ERROR_FILE``
The file named will be attached to the standard input of the first
process, standard output of the last process, or standard error of
- all processes, respectively. If the same file is named for both
- output and error then it will be used for both.
+ all processes, respectively.
+
+ .. versionadded:: 3.3
+ If the same file is named for both output and error then it will be used
+ for both.
``OUTPUT_QUIET``, ``ERROR_QUIET``
The standard output or standard error results will be quietly ignored.
``COMMAND_ECHO <where>``
+ .. versionadded:: 3.15
+
The command being run will be echo'ed to ``<where>`` with ``<where>``
being set to one of ``STDERR``, ``STDOUT`` or ``NONE``.
See the :variable:`CMAKE_EXECUTE_PROCESS_COMMAND_ECHO` variable for a way
to control the default behavior when this option is not present.
``ENCODING <name>``
+ .. versionadded:: 3.8
+
On Windows, the encoding that is used to decode output from the process.
Ignored on other platforms.
Valid encoding names are:
@@ -104,11 +113,15 @@ Options:
``OEM``
Use the original equipment manufacturer (OEM) code page.
``UTF8`` or ``UTF-8``
- Use the UTF-8 codepage. Prior to CMake 3.11.0, only ``UTF8`` was accepted
- for this encoding. In CMake 3.11.0, ``UTF-8`` was added for consistency with
- the `UTF-8 RFC <https://www.ietf.org/rfc/rfc3629>`_ naming convention.
+ Use the UTF-8 codepage.
+
+ .. versionadded:: 3.11
+ Accept ``UTF-8`` spelling for consistency with the
+ `UTF-8 RFC <https://www.ietf.org/rfc/rfc3629>`_ naming convention.
``ECHO_OUTPUT_VARIABLE``, ``ECHO_ERROR_VARIABLE``
+ .. versionadded:: 3.18
+
The standard output or standard error will not be exclusively redirected to
the configured variables.
@@ -118,6 +131,8 @@ Options:
This is analogous to the ``tee`` Unix command.
``COMMAND_ERROR_IS_FATAL <ANY|LAST>``
+ .. versionadded:: 3.19
+
The option following ``COMMAND_ERROR_IS_FATAL`` determines the behavior when
an error is encountered:
diff --git a/Help/command/export.rst b/Help/command/export.rst
index 2ca705616..e8a1fa70e 100644
--- a/Help/command/export.rst
+++ b/Help/command/export.rst
@@ -64,16 +64,23 @@ build tree. In some cases, for example for packaging and for system
wide installations, it is not desirable to write the user package
registry.
-By default the ``export(PACKAGE)`` command does nothing (see policy
-:policy:`CMP0090`) because populating the user package registry has effects
-outside the source and build trees. Set the
-:variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable to add build directories to
-the CMake user package registry.
+.. versionchanged:: 3.1
+ If the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable
+ is enabled, the ``export(PACKAGE)`` command will do nothing.
+
+.. versionchanged:: 3.15
+ By default the ``export(PACKAGE)`` command does nothing (see policy
+ :policy:`CMP0090`) because populating the user package registry has effects
+ outside the source and build trees. Set the
+ :variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable to add build directories
+ to the CMake user package registry.
.. code-block:: cmake
export(TARGETS [target1 [target2 [...]]] [ANDROID_MK <filename>])
+.. versionadded:: 3.7
+
This signature exports cmake built targets to the android ndk build system
by creating an Android.mk file that references the prebuilt targets. The
Android NDK supports the use of prebuilt libraries, both static and shared.
diff --git a/Help/command/file.rst b/Help/command/file.rst
index e963be0fb..3db605d6a 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -3,6 +3,21 @@ file
File manipulation command.
+This command is dedicated to file and path manipulation requiring access to the
+filesystem.
+
+For other path manipulation, handling only syntactic aspects, have a look at
+:command:`cmake_path` command.
+
+.. note::
+
+ The sub-commands `RELATIVE_PATH`_, `TO_CMAKE_PATH`_ and `TO_NATIVE_PATH`_ has
+ been superseded, respectively, by sub-commands
+ :ref:`RELATIVE_PATH <cmake_path-RELATIVE_PATH>`,
+ :ref:`CONVERT ... TO_CMAKE_PATH_LIST <cmake_path-TO_CMAKE_PATH_LIST>` and
+ :ref:`CONVERT ... TO_NATIVE_PATH_LIST <cmake_path-TO_NATIVE_PATH_LIST>` of
+ :command:`cmake_path` command.
+
Synopsis
^^^^^^^^
@@ -103,10 +118,15 @@ Parse a list of ASCII strings from ``<filename>`` and store it in
Consider only strings that match the given regular expression.
``ENCODING <encoding-type>``
+ .. versionadded:: 3.1
+
Consider strings of a given encoding. Currently supported encodings are:
- UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE. If the ENCODING option
- is not provided and the file has a Byte Order Mark, the ENCODING option
- will be defaulted to respect the Byte Order Mark.
+ ``UTF-8``, ``UTF-16LE``, ``UTF-16BE``, ``UTF-32LE``, ``UTF-32BE``.
+ If the ``ENCODING`` option is not provided and the file has a Byte Order Mark,
+ the ``ENCODING`` option will be defaulted to respect the Byte Order Mark.
+
+ .. versionadded:: 3.2
+ Added the ``UTF-16LE``, ``UTF-16BE``, ``UTF-32LE``, ``UTF-32BE`` encodings.
For example, the code
@@ -160,6 +180,8 @@ the ``<format>`` and ``UTC`` options.
[POST_EXCLUDE_REGEXES [<regexes>...]]
)
+.. versionadded:: 3.16
+
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.
@@ -408,6 +430,9 @@ dependency resolution:
If this variable is not specified, it is determined by the value of
``CMAKE_OBJDUMP`` if set, else by system introspection.
+ .. versionadded:: 3.18
+ Use ``CMAKE_OBJDUMP`` if set.
+
Writing
^^^^^^^
@@ -436,6 +461,8 @@ to update the file only when its content changes.
file(TOUCH [<files>...])
file(TOUCH_NOCREATE [<files>...])
+.. versionadded:: 3.12
+
Create a file with no content if it does not yet exist. If the file already
exists, its access and/or modification will be updated to the time when the
function call is executed.
@@ -452,7 +479,10 @@ modified.
file(GENERATE OUTPUT output-file
<INPUT input-file|CONTENT content>
- [CONDITION expression] [TARGET target])
+ [CONDITION expression] [TARGET target]
+ [FILE_PERMISSIONS <permissions>...]
+ [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
+ [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
Generate an output file for each build configuration supported by the current
:manual:`CMake Generator <cmake-generators(7)>`. Evaluate
@@ -469,8 +499,10 @@ from the input content to produce the output content. The options are:
``INPUT <input-file>``
Use the content from a given file as input.
- A relative path is treated with respect to the value of
- :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
+
+ .. versionchanged:: 3.10
+ A relative path is treated with respect to the value of
+ :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
``OUTPUT <output-file>``
Specify the output file name to generate. Use generator expressions
@@ -478,15 +510,37 @@ from the input content to produce the output content. The options are:
name. Multiple configurations may generate the same output file only
if the generated content is identical. Otherwise, the ``<output-file>``
must evaluate to an unique name for each configuration.
- A relative path (after evaluating generator expressions) is treated
- with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
- See policy :policy:`CMP0070`.
+
+ .. versionchanged:: 3.10
+ A relative path (after evaluating generator expressions) is treated
+ with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ See policy :policy:`CMP0070`.
``TARGET <target>``
+ .. versionadded:: 3.19
+
Specify which target to use when evaluating generator expressions that
require a target for evaluation (e.g. ``$<COMPILE_FEATURES:...>``,
``$<TARGET_PROPERTY:prop>``).
+``FILE_PERMISSIONS <permissions>...``
+ Use user provided permissions for the generated file.
+
+``NO_SOURCE_PERMISSIONS``
+ The generated file permissions default to the standard 644 value
+ (-rw-r--r--).
+
+``USE_SOURCE_PERMISSIONS``
+ Transfer the file permissions of the original file to the generated file.
+ This option expects INPUT option.
+
+``NEWLINE_STYLE <style>``
+ .. versionadded:: 3.20
+
+ Specify the newline style for the generated file. Specify
+ ``UNIX`` or ``LF`` for ``\n`` newlines, or specify
+ ``DOS``, ``WIN32``, or ``CRLF`` for ``\r\n`` newlines.
+
Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
Generated files are modified and their timestamp updated on subsequent cmake
@@ -506,6 +560,8 @@ of a project's ``CMakeLists.txt`` files.
[ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
+.. versionadded:: 3.18
+
Generate an output file using the input given by ``CONTENT`` and substitute
variable values referenced as ``@VAR@`` or ``${VAR}`` contained therein. The
substitution rules behave the same as the :command:`configure_file` command.
@@ -554,20 +610,25 @@ Generate a list of files that match the ``<globbing-expressions>`` and
store it into the ``<variable>``. Globbing expressions are similar to
regular expressions, but much simpler. If ``RELATIVE`` flag is
specified, the results will be returned as relative paths to the given
-path. The results will be ordered lexicographically.
+path.
+
+.. versionchanged:: 3.6
+ The results will be ordered lexicographically.
On Windows and macOS, globbing is case-insensitive even if the underlying
filesystem is case-sensitive (both filenames and globbing expressions are
converted to lowercase before matching). On other platforms, globbing is
case-sensitive.
-If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic
-to the main build system check target to rerun the flagged ``GLOB`` commands
-at build time. If any of the outputs change, CMake will regenerate the build
-system.
+.. versionadded:: 3.3
+ By default ``GLOB`` lists directories - directories are omitted in result if
+ ``LIST_DIRECTORIES`` is set to false.
-By default ``GLOB`` lists directories - directories are omitted in result if
-``LIST_DIRECTORIES`` is set to false.
+.. versionadded:: 3.12
+ If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic
+ to the main build system check target to rerun the flagged ``GLOB`` commands
+ at build time. If any of the outputs change, CMake will regenerate the build
+ system.
.. note::
We do not recommend using GLOB to collect a list of source files from
@@ -590,10 +651,11 @@ matched directory and match the files. Subdirectories that are symlinks
are only traversed if ``FOLLOW_SYMLINKS`` is given or policy
:policy:`CMP0009` is not set to ``NEW``.
-By default ``GLOB_RECURSE`` omits directories from result list - setting
-``LIST_DIRECTORIES`` to true adds directories to result list.
-If ``FOLLOW_SYMLINKS`` is given or policy :policy:`CMP0009` is not set to
-``NEW`` then ``LIST_DIRECTORIES`` treats symlinks as directories.
+.. versionadded:: 3.3
+ By default ``GLOB_RECURSE`` omits directories from result list - setting
+ ``LIST_DIRECTORIES`` to true adds directories to result list.
+ If ``FOLLOW_SYMLINKS`` is given or policy :policy:`CMP0009` is not set to
+ ``NEW`` then ``LIST_DIRECTORIES`` treats symlinks as directories.
Examples of recursive globbing include::
@@ -619,7 +681,12 @@ Move a file or directory within a filesystem from ``<oldname>`` to
Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given
files and directories, also non-empty directories. No error is emitted if a
given file does not exist. Relative input paths are evaluated with respect
-to the current source directory. Empty input paths are ignored with a warning.
+to the current source directory.
+
+.. versionchanged:: 3.15
+ Empty input paths are ignored with a warning. Previous versions of CMake
+ interpreted empty string as a relative path with respect to the current
+ directory and removed its contents.
.. _MAKE_DIRECTORY:
@@ -652,17 +719,18 @@ at the destination with the same timestamp. Copying preserves input
permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
are given (default is ``USE_SOURCE_PERMISSIONS``).
-If ``FOLLOW_SYMLINK_CHAIN`` is specified, ``COPY`` will recursively resolve
-the symlinks at the paths given until a real file is found, and install
-a corresponding symlink in the destination for each symlink encountered. For
-each symlink that is installed, the resolution is stripped of the directory,
-leaving only the filename, meaning that the new symlink points to a file in
-the same directory as the symlink. This feature is useful on some Unix systems,
-where libraries are installed as a chain of symlinks with version numbers, with
-less specific versions pointing to more specific versions.
-``FOLLOW_SYMLINK_CHAIN`` will install all of these symlinks and the library
-itself into the destination directory. For example, if you have the following
-directory structure:
+.. versionadded:: 3.15
+ If ``FOLLOW_SYMLINK_CHAIN`` is specified, ``COPY`` will recursively resolve
+ the symlinks at the paths given until a real file is found, and install
+ a corresponding symlink in the destination for each symlink encountered. For
+ each symlink that is installed, the resolution is stripped of the directory,
+ leaving only the filename, meaning that the new symlink points to a file in
+ the same directory as the symlink. This feature is useful on some Unix systems,
+ where libraries are installed as a chain of symlinks with version numbers, with
+ less specific versions pointing to more specific versions.
+ ``FOLLOW_SYMLINK_CHAIN`` will install all of these symlinks and the library
+ itself into the destination directory. For example, if you have the following
+ directory structure:
* ``/opt/foo/lib/libfoo.so.1.2.3``
* ``/opt/foo/lib/libfoo.so.1.2 -> libfoo.so.1.2.3``
@@ -696,6 +764,8 @@ use this signature (with some undocumented options for internal use).
file(SIZE <filename> <variable>)
+.. versionadded:: 3.14
+
Determine the file size of the ``<filename>`` and put the result in
``<variable>`` variable. Requires that ``<filename>`` is a valid path
pointing to a file and is readable.
@@ -706,6 +776,8 @@ pointing to a file and is readable.
file(READ_SYMLINK <linkname> <variable>)
+.. versionadded:: 3.14
+
This subcommand queries the symlink ``<linkname>`` and stores the path it
points to in the result ``<variable>``. If ``<linkname>`` does not exist or
is not a symlink, CMake issues a fatal error.
@@ -730,6 +802,8 @@ absolute path is obtained:
file(CREATE_LINK <original> <linkname>
[RESULT <result>] [COPY_ON_ERROR] [SYMBOLIC])
+.. versionadded:: 3.14
+
Create a link ``<linkname>`` that points to ``<original>``.
It will be a hard link by default, but providing the ``SYMBOLIC`` option
results in a symbolic link instead. Hard links require that ``original``
@@ -754,10 +828,12 @@ which would make them unable to support a hard link.
[FILE_PERMISSIONS <permissions>...]
[DIRECTORY_PERMISSIONS <permissions>...])
+.. versionadded:: 3.19
+
Set the permissions for the ``<files>...`` and ``<directories>...`` specified.
Valid permissions are ``OWNER_READ``, ``OWNER_WRITE``, ``OWNER_EXECUTE``,
``GROUP_READ``, ``GROUP_WRITE``, ``GROUP_EXECUTE``, ``WORLD_READ``,
-``WORLD_WRITE``, ``WORLD_EXECUTE``.
+``WORLD_WRITE``, ``WORLD_EXECUTE``, ``SETUID``, ``SETGID``.
Valid combination of keywords are:
@@ -790,6 +866,8 @@ Valid combination of keywords are:
[FILE_PERMISSIONS <permissions>...]
[DIRECTORY_PERMISSIONS <permissions>...])
+.. versionadded:: 3.19
+
Same as `CHMOD`_, but change the permissions of files and directories present in
the ``<directories>...`` recursively.
@@ -802,6 +880,8 @@ Path Conversion
file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>])
+.. versionadded:: 3.19
+
Compute the absolute path to an existing file or directory with symlinks
resolved.
@@ -849,10 +929,12 @@ Transfer
file(UPLOAD <file> <url> [<options>...])
The ``DOWNLOAD`` subcommand downloads the given ``<url>`` to a local ``<file>``.
-If ``<file>`` is not specified for ``file(DOWNLOAD)``, the file is not saved.
-This can be useful if you want to know if a file can be downloaded (for example,
-to check that it exists) without actually saving it anywhere. The ``UPLOAD``
-mode uploads a local ``<file>`` to a given ``<url>``.
+The ``UPLOAD`` mode uploads a local ``<file>`` to a given ``<url>``.
+
+.. versionadded:: 3.19
+ If ``<file>`` is not specified for ``file(DOWNLOAD)``, the file is not saved.
+ This can be useful if you want to know if a file can be downloaded (for example,
+ to check that it exists) without actually saving it anywhere.
Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
@@ -877,12 +959,18 @@ Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
Terminate the operation after a given total time has elapsed.
``USERPWD <username>:<password>``
+ .. versionadded:: 3.7
+
Set username and password for operation.
``HTTPHEADER <HTTP-header>``
+ .. versionadded:: 3.7
+
HTTP header for operation. Suboption can be repeated several times.
``NETRC <level>``
+ .. versionadded:: 3.11
+
Specify whether the .netrc file is to be used for operation. If this
option is not specified, the value of the ``CMAKE_NETRC`` variable
will be used instead.
@@ -899,6 +987,8 @@ Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
The .netrc file is required, and information in the URL is ignored.
``NETRC_FILE <file>``
+ .. versionadded:: 3.11
+
Specify an alternative .netrc file to the one in your home directory,
if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will
@@ -911,9 +1001,15 @@ If neither ``NETRC`` option is given CMake will check variables
Specify whether to verify the server certificate for ``https://`` URLs.
The default is to *not* verify.
+ .. versionadded:: 3.18
+ Added support to ``file(UPLOAD)``.
+
``TLS_CAINFO <file>``
Specify a custom Certificate Authority file for ``https://`` URLs.
+ .. versionadded:: 3.18
+ Added support to ``file(UPLOAD)``.
+
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
@@ -944,6 +1040,8 @@ Locking
[RESULT_VARIABLE <variable>]
[TIMEOUT <seconds>])
+.. versionadded:: 3.2
+
Lock a file specified by ``<path>`` if no ``DIRECTORY`` option present and file
``<path>/cmake.lock`` otherwise. File will be locked for scope defined by
``GUARD`` option (default value is ``PROCESS``). ``RELEASE`` option can be used
@@ -979,6 +1077,8 @@ Archiving
[MTIME <mtime>]
[VERBOSE])
+.. versionadded:: 3.18
+
Creates the specified ``<archive>`` file with the files and directories
listed in ``<paths>``. Note that ``<paths>`` must list actual files or
directories, wildcards are not supported.
@@ -993,9 +1093,10 @@ compression. The other formats use no compression by default, but can be
directed to do so with the ``COMPRESSION`` option. Valid values for
``<compression>`` are ``None``, ``BZip2``, ``GZip``, ``XZ``, and ``Zstd``.
-The compression level can be specified with the ``COMPRESSION_LEVEL`` option.
-The ``<compression-level>`` should be between 0-9, with the default being 0.
-The ``COMPRESSION`` option must be present when ``COMPRESSION_LEVEL`` is given.
+.. versionadded:: 3.19
+ The compression level can be specified with the ``COMPRESSION_LEVEL`` option.
+ The ``<compression-level>`` should be between 0-9, with the default being 0.
+ The ``COMPRESSION`` option must be present when ``COMPRESSION_LEVEL`` is given.
.. note::
With ``FORMAT`` set to ``raw`` only one file will be compressed with the
@@ -1016,6 +1117,8 @@ the ``MTIME`` option.
[LIST_ONLY]
[VERBOSE])
+.. versionadded:: 3.18
+
Extracts or lists the content of the specified ``<archive>``.
The directory where the content of the archive will be extracted to can
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index 1be2e09ee..3dfd62fc3 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -351,15 +351,16 @@ The set of installation prefixes is constructed using the following
steps. If ``NO_DEFAULT_PATH`` is specified all ``NO_*`` options are
enabled.
-1. Search paths specified in the :variable:`<PackageName>_ROOT` CMake
- variable and the :envvar:`<PackageName>_ROOT` environment variable,
- where ``<PackageName>`` is the package to be found.
- The package root variables are maintained as a stack so if
- called from within a find module, root paths from the parent's find
- module will also be searched after paths for the current package.
- This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting
- the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``.
- See policy :policy:`CMP0074`.
+1. .. versionadded:: 3.12
+ Search paths specified in the :variable:`<PackageName>_ROOT` CMake
+ variable and the :envvar:`<PackageName>_ROOT` environment variable,
+ where ``<PackageName>`` is the package to be found.
+ The package root variables are maintained as a stack so if
+ called from within a find module, root paths from the parent's find
+ module will also be searched after paths for the current package.
+ This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting
+ the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``.
+ See policy :policy:`CMP0074`.
2. Search paths specified in cmake-specific cache variables. These
are intended to be used on the command line with a ``-DVAR=value``.
@@ -430,6 +431,10 @@ enabled.
9. Search paths specified by the ``PATHS`` option. These are typically
hard-coded guesses.
+.. versionadded:: 3.16
+ Added the ``CMAKE_FIND_USE_<CATEGORY>_PATH`` variables to globally disable
+ various search locations.
+
.. |FIND_XXX| replace:: find_package
.. |FIND_ARGS_XXX| replace:: <PackageName>
.. |CMAKE_FIND_ROOT_PATH_MODE_XXX| replace::
diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst
index a01a1042c..8de6debae 100644
--- a/Help/command/foreach.rst
+++ b/Help/command/foreach.rst
@@ -88,6 +88,8 @@ yields
foreach(<loop_var>... IN ZIP_LISTS <lists>)
+.. versionadded:: 3.17
+
In this variant, ``<lists>`` is a whitespace or semicolon
separated list of list-valued variables. The ``foreach``
command iterates over each list simultaneously setting the
diff --git a/Help/command/function.rst b/Help/command/function.rst
index 7a9b90754..3d25aa45f 100644
--- a/Help/command/function.rst
+++ b/Help/command/function.rst
@@ -50,8 +50,9 @@ and so on. However, it is strongly recommended to stay with the
case chosen in the function definition. Typically functions use
all-lowercase names.
-The :command:`cmake_language(CALL ...)` command can also be used to
-invoke the function.
+.. versionadded:: 3.18
+ The :command:`cmake_language(CALL ...)` command can also be used to
+ invoke the function.
Arguments
^^^^^^^^^
diff --git a/Help/command/get_directory_property.rst b/Help/command/get_directory_property.rst
index 39015cc24..0ccbfb027 100644
--- a/Help/command/get_directory_property.rst
+++ b/Help/command/get_directory_property.rst
@@ -11,12 +11,14 @@ Stores a property of directory scope in the named ``<variable>``.
The ``DIRECTORY`` argument specifies another directory from which
to retrieve the property value instead of the current directory.
-It may reference either a source directory, or since CMake 3.19,
-a binary directory. Relative paths are treated as relative to the
+Relative paths are treated as relative to the
current source directory. CMake must already know about the directory,
either by having added it through a call to :command:`add_subdirectory`
or being the top level directory.
+.. versionadded:: 3.19
+ ``<dir>`` may reference a binary directory.
+
If the property is not defined for the nominated directory scope,
an empty string is returned. In the case of ``INHERITED`` properties,
if the property is not found for the nominated directory scope,
diff --git a/Help/command/get_filename_component.rst b/Help/command/get_filename_component.rst
index ea2dedb64..be9d00af3 100644
--- a/Help/command/get_filename_component.rst
+++ b/Help/command/get_filename_component.rst
@@ -3,6 +3,11 @@ get_filename_component
Get a specific component of a full filename.
+.. versionchanged:: 3.19
+ This command been superseded by :command:`cmake_path` command, except
+ ``REALPATH`` now offered by :ref:`file(REAL_PATH) <REAL_PATH>` command and
+ ``PROGRAM`` now available in :command:`separate_arguments(PROGRAM)` command.
+
.. code-block:: cmake
get_filename_component(<var> <FileName> <mode> [CACHE])
@@ -19,6 +24,9 @@ Sets ``<var>`` to a component of ``<FileName>``, where ``<mode>`` is one of:
NAME_WLE = File name with neither the directory nor the last extension
PATH = Legacy alias for DIRECTORY (use for CMake <= 2.8.11)
+.. versionadded:: 3.14
+ Added the ``LAST_EXT`` and ``NAME_WLE`` modes.
+
Paths are returned with forward slashes and have no trailing slashes.
If the optional ``CACHE`` argument is specified, the result variable is
added to the cache.
@@ -27,6 +35,8 @@ added to the cache.
get_filename_component(<var> <FileName> <mode> [BASE_DIR <dir>] [CACHE])
+.. versionadded:: 3.4
+
Sets ``<var>`` to the absolute path of ``<FileName>``, where ``<mode>`` is one
of:
@@ -53,9 +63,3 @@ left as a full path. If ``PROGRAM_ARGS`` is present with ``PROGRAM``, then
any command-line arguments present in the ``<FileName>`` string are split
from the program name and stored in ``<arg_var>``. This is used to
separate a program name from its arguments in a command line string.
-
-.. note::
-
- The ``REALPATH`` and ``PROGRAM`` subcommands had been superseded,
- respectively, by :ref:`file(REAL_PATH) <REAL_PATH>` and
- :command:`separate_arguments(PROGRAM)` commands.
diff --git a/Help/command/get_property.rst b/Help/command/get_property.rst
index 870c934e3..f77d8af78 100644
--- a/Help/command/get_property.rst
+++ b/Help/command/get_property.rst
@@ -30,35 +30,43 @@ It must be one of the following:
``DIRECTORY``
Scope defaults to the current directory but another
directory (already processed by CMake) may be named by the
- full or relative path ``<dir>``. The ``<dir>`` may reference either a
- source directory, or since CMake 3.19, a binary directory.
+ full or relative path ``<dir>``.
Relative paths are treated as relative to the current source directory.
See also the :command:`get_directory_property` command.
+ .. versionadded:: 3.19
+ ``<dir>`` may reference a binary directory.
+
``TARGET``
Scope must name one existing target.
See also the :command:`get_target_property` command.
``SOURCE``
Scope must name one source file. By default, the source file's property
- will be read from the current source directory's scope, but this can be
- overridden with one of the following sub-options:
+ will be read from the current source directory's scope.
+
+ .. versionadded:: 3.18
+ Directory scope can be overridden with one of the following sub-options:
+
+ ``DIRECTORY <dir>``
+ The source file property will be read from the ``<dir>`` directory's
+ scope. CMake must already know about
+ the directory, either by having added it through a call
+ to :command:`add_subdirectory` or ``<dir>`` being the top level directory.
+ Relative paths are treated as relative to the current source directory.
- ``DIRECTORY <dir>``
- The source file property will be read from the ``<dir>`` directory's
- scope. The ``<dir>`` may reference either a source directory, or
- since CMake 3.19, a binary directory. CMake must already know about
- the directory, either by having added it through a call
- to :command:`add_subdirectory` or ``<dir>`` being the top level directory.
- Relative paths are treated as relative to the current source directory.
+ .. versionadded:: 3.19
+ ``<dir>`` may reference a binary directory.
- ``TARGET_DIRECTORY <target>``
- The source file property will be read from the directory scope in which
- ``<target>`` was created (``<target>`` must therefore already exist).
+ ``TARGET_DIRECTORY <target>``
+ The source file property will be read from the directory scope in which
+ ``<target>`` was created (``<target>`` must therefore already exist).
See also the :command:`get_source_file_property` command.
``INSTALL``
+ .. versionadded:: 3.1
+
Scope must name one installed file path.
``TEST``
@@ -86,3 +94,8 @@ If ``BRIEF_DOCS`` or ``FULL_DOCS`` is given then the variable is set to a
string containing documentation for the requested property. If
documentation is requested for a property that has not been defined
``NOTFOUND`` is returned.
+
+.. note::
+
+ The :prop_sf:`GENERATED` source file property may be globally visible.
+ See its documentation for details.
diff --git a/Help/command/get_source_file_property.rst b/Help/command/get_source_file_property.rst
index 76ed776c0..ae4156598 100644
--- a/Help/command/get_source_file_property.rst
+++ b/Help/command/get_source_file_property.rst
@@ -19,22 +19,29 @@ command and if still unable to find the property, ``variable`` will be set to
an empty string.
By default, the source file's property will be read from the current source
-directory's scope, but this can be overridden with one of the following
-sub-options:
+directory's scope.
-``DIRECTORY <dir>``
- The source file property will be read from the ``<dir>`` directory's
- scope. CMake must already know about that source directory, either by
- having added it through a call to :command:`add_subdirectory` or ``<dir>``
- being the top level source directory. Relative paths are treated as
- relative to the current source directory.
+.. versionadded:: 3.18
+ Directory scope can be overridden with one of the following sub-options:
-``TARGET_DIRECTORY <target>``
- The source file property will be read from the directory scope in which
- ``<target>`` was created (``<target>`` must therefore already exist).
+ ``DIRECTORY <dir>``
+ The source file property will be read from the ``<dir>`` directory's
+ scope. CMake must already know about that source directory, either by
+ having added it through a call to :command:`add_subdirectory` or ``<dir>``
+ being the top level source directory. Relative paths are treated as
+ relative to the current source directory.
+
+ ``TARGET_DIRECTORY <target>``
+ The source file property will be read from the directory scope in which
+ ``<target>`` was created (``<target>`` must therefore already exist).
Use :command:`set_source_files_properties` to set property values. Source
file properties usually control how the file is built. One property that is
always there is :prop_sf:`LOCATION`.
See also the more general :command:`get_property` command.
+
+.. note::
+
+ The :prop_sf:`GENERATED` source file property may be globally visible.
+ See its documentation for details.
diff --git a/Help/command/if.rst b/Help/command/if.rst
index be992df15..f327ca943 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -39,15 +39,16 @@ the ``if``, ``elseif`` and :command:`while` clauses.
Compound conditions are evaluated in the following order of precedence:
Innermost parentheses are evaluated first. Next come unary tests such
-as ``EXISTS``, ``COMMAND``, and ``DEFINED``. Then binary tests such as
-``EQUAL``, ``LESS``, ``LESS_EQUAL``, ``GREATER``, ``GREATER_EQUAL``,
-``STREQUAL``, ``STRLESS``, ``STRLESS_EQUAL``, ``STRGREATER``,
-``STRGREATER_EQUAL``, ``VERSION_EQUAL``, ``VERSION_LESS``,
-``VERSION_LESS_EQUAL``, ``VERSION_GREATER``, ``VERSION_GREATER_EQUAL``,
-and ``MATCHES``. Then the boolean operators in the order ``NOT``, ``AND``,
-and finally ``OR``.
+as `EXISTS`_, `COMMAND`_, and `DEFINED`_. Then binary tests such as
+`EQUAL`_, `LESS`_, `LESS_EQUAL`_, `GREATER`_, `GREATER_EQUAL`_,
+`STREQUAL`_, `STRLESS`_, `STRLESS_EQUAL`_, `STRGREATER`_,
+`STRGREATER_EQUAL`_, `VERSION_EQUAL`_, `VERSION_LESS`_,
+`VERSION_LESS_EQUAL`_, `VERSION_GREATER`_, `VERSION_GREATER_EQUAL`_,
+and `MATCHES`_. Then the boolean operators in the order `NOT`_, `AND`_,
+and finally `OR`_.
-Possible conditions are:
+Basic Expressions
+"""""""""""""""""
``if(<constant>)``
True if the constant is ``1``, ``ON``, ``YES``, ``TRUE``, ``Y``,
@@ -62,15 +63,35 @@ Possible conditions are:
True if given a variable that is defined to a value that is not a false
constant. False otherwise. (Note macro arguments are not variables.)
+Logic Operators
+"""""""""""""""
+
+.. _NOT:
+
``if(NOT <condition>)``
True if the condition is not true.
+.. _AND:
+
``if(<cond1> AND <cond2>)``
True if both conditions would be considered true individually.
+.. _OR:
+
``if(<cond1> OR <cond2>)``
True if either condition would be considered true individually.
+``if((condition) AND (condition OR (condition)))``
+ The conditions inside the parenthesis are evaluated first and then
+ the remaining condition is evaluated as in the other examples.
+ Where there are nested parenthesis the innermost are evaluated as part
+ of evaluating the condition that contains them.
+
+Existence Checks
+""""""""""""""""
+
+.. _COMMAND:
+
``if(COMMAND command-name)``
True if the given name is a command, macro or function that can be
invoked.
@@ -85,14 +106,35 @@ Possible conditions are:
(in any directory).
``if(TEST test-name)``
- True if the given name is an existing test name created by the
- :command:`add_test` command.
+ .. versionadded:: 3.3
+ True if the given name is an existing test name created by the
+ :command:`add_test` command.
+
+.. _DEFINED:
+
+``if(DEFINED <name>|CACHE{<name>}|ENV{<name>})``
+ True if a variable, cache variable or environment variable
+ with given ``<name>`` is defined. The value of the variable
+ does not matter. Note that macro arguments are not variables.
+
+ .. versionadded:: 3.14
+ Added support for ``CACHE{<name>}`` variables.
+
+``if(<variable|string> IN_LIST <variable>)``
+ .. versionadded:: 3.3
+ True if the given element is contained in the named list variable.
+
+File Operations
+"""""""""""""""
+
+.. _EXISTS:
``if(EXISTS path-to-file-or-directory)``
True if the named file or directory exists. Behavior is well-defined
- only for full paths. Resolves symbolic links, i.e. if the named file or
- directory is a symbolic link, returns true if the target of the
- symbolic link exists.
+ only for explicit full paths (a leading ``~/`` is not expanded as
+ a home directory and is considered a relative path).
+ Resolves symbolic links, i.e. if the named file or directory is a
+ symbolic link, returns true if the target of the symbolic link exists.
``if(file1 IS_NEWER_THAN file2)``
True if ``file1`` is newer than ``file2`` or if one of the two files doesn't
@@ -113,50 +155,86 @@ Possible conditions are:
``if(IS_ABSOLUTE path)``
True if the given path is an absolute path.
+Comparisons
+"""""""""""
+
+.. _MATCHES:
+
``if(<variable|string> MATCHES regex)``
True if the given string or variable's value matches the given regular
condition. See :ref:`Regex Specification` for regex format.
- ``()`` groups are captured in :variable:`CMAKE_MATCH_<n>` variables.
+
+ .. versionadded:: 3.9
+ ``()`` groups are captured in :variable:`CMAKE_MATCH_<n>` variables.
+
+.. _LESS:
``if(<variable|string> LESS <variable|string>)``
True if the given string or variable's value is a valid number and less
than that on the right.
+.. _GREATER:
+
``if(<variable|string> GREATER <variable|string>)``
True if the given string or variable's value is a valid number and greater
than that on the right.
+.. _EQUAL:
+
``if(<variable|string> EQUAL <variable|string>)``
True if the given string or variable's value is a valid number and equal
to that on the right.
+.. _LESS_EQUAL:
+
``if(<variable|string> LESS_EQUAL <variable|string>)``
- True if the given string or variable's value is a valid number and less
- than or equal to that on the right.
+ .. versionadded:: 3.7
+ True if the given string or variable's value is a valid number and less
+ than or equal to that on the right.
+
+.. _GREATER_EQUAL:
``if(<variable|string> GREATER_EQUAL <variable|string>)``
- True if the given string or variable's value is a valid number and greater
- than or equal to that on the right.
+ .. versionadded:: 3.7
+ True if the given string or variable's value is a valid number and greater
+ than or equal to that on the right.
+
+.. _STRLESS:
``if(<variable|string> STRLESS <variable|string>)``
True if the given string or variable's value is lexicographically less
than the string or variable on the right.
+.. _STRGREATER:
+
``if(<variable|string> STRGREATER <variable|string>)``
True if the given string or variable's value is lexicographically greater
than the string or variable on the right.
+.. _STREQUAL:
+
``if(<variable|string> STREQUAL <variable|string>)``
True if the given string or variable's value is lexicographically equal
to the string or variable on the right.
+.. _STRLESS_EQUAL:
+
``if(<variable|string> STRLESS_EQUAL <variable|string>)``
- True if the given string or variable's value is lexicographically less
- than or equal to the string or variable on the right.
+ .. versionadded:: 3.7
+ True if the given string or variable's value is lexicographically less
+ than or equal to the string or variable on the right.
+
+.. _STRGREATER_EQUAL:
``if(<variable|string> STRGREATER_EQUAL <variable|string>)``
- True if the given string or variable's value is lexicographically greater
- than or equal to the string or variable on the right.
+ .. versionadded:: 3.7
+ True if the given string or variable's value is lexicographically greater
+ than or equal to the string or variable on the right.
+
+Version Comparisons
+"""""""""""""""""""
+
+.. _VERSION_LESS:
``if(<variable|string> VERSION_LESS <variable|string>)``
Component-wise integer version number comparison (version format is
@@ -164,43 +242,39 @@ Possible conditions are:
Any non-integer version component or non-integer trailing part of a version
component effectively truncates the string at that point.
+.. _VERSION_GREATER:
+
``if(<variable|string> VERSION_GREATER <variable|string>)``
Component-wise integer version number comparison (version format is
``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
Any non-integer version component or non-integer trailing part of a version
component effectively truncates the string at that point.
-``if(<variable|string> VERSION_EQUAL <variable|string>)``
- Component-wise integer version number comparison (version format is
- ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
- Any non-integer version component or non-integer trailing part of a version
- component effectively truncates the string at that point.
+.. _VERSION_EQUAL:
-``if(<variable|string> VERSION_LESS_EQUAL <variable|string>)``
+``if(<variable|string> VERSION_EQUAL <variable|string>)``
Component-wise integer version number comparison (version format is
``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
Any non-integer version component or non-integer trailing part of a version
component effectively truncates the string at that point.
-``if(<variable|string> VERSION_GREATER_EQUAL <variable|string>)``
- Component-wise integer version number comparison (version format is
- ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
- Any non-integer version component or non-integer trailing part of a version
- component effectively truncates the string at that point.
+.. _VERSION_LESS_EQUAL:
-``if(<variable|string> IN_LIST <variable>)``
- True if the given element is contained in the named list variable.
+``if(<variable|string> VERSION_LESS_EQUAL <variable|string>)``
+ .. versionadded:: 3.7
+ Component-wise integer version number comparison (version format is
+ ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
+ Any non-integer version component or non-integer trailing part of a version
+ component effectively truncates the string at that point.
-``if(DEFINED <name>|CACHE{<name>}|ENV{<name>})``
- True if a variable, cache variable or environment variable
- with given ``<name>`` is defined. The value of the variable
- does not matter. Note that macro arguments are not variables.
+.. _VERSION_GREATER_EQUAL:
-``if((condition) AND (condition OR (condition)))``
- The conditions inside the parenthesis are evaluated first and then
- the remaining condition is evaluated as in the previous examples.
- Where there are nested parenthesis the innermost are evaluated as part
- of evaluating the condition that contains them.
+``if(<variable|string> VERSION_GREATER_EQUAL <variable|string>)``
+ .. versionadded:: 3.7
+ Component-wise integer version number comparison (version format is
+ ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
+ Any non-integer version component or non-integer trailing part of a version
+ component effectively truncates the string at that point.
Variable Expansion
^^^^^^^^^^^^^^^^^^
@@ -268,11 +342,12 @@ above-documented condition syntax accepts ``<variable|string>``:
tested to see if they are boolean constants, if so they are used as
such, otherwise they are assumed to be variables and are dereferenced.
-To prevent ambiguity, potential variable or keyword names can be
-specified in a :ref:`Quoted Argument` or a :ref:`Bracket Argument`.
-A quoted or bracketed variable or keyword will be interpreted as a
-string and not dereferenced or interpreted.
-See policy :policy:`CMP0054`.
+.. versionchanged:: 3.1
+ To prevent ambiguity, potential variable or keyword names can be
+ specified in a :ref:`Quoted Argument` or a :ref:`Bracket Argument`.
+ A quoted or bracketed variable or keyword will be interpreted as a
+ string and not dereferenced or interpreted.
+ See policy :policy:`CMP0054`.
There is no automatic evaluation for environment or cache
:ref:`Variable References`. Their values must be referenced as
diff --git a/Help/command/include_external_msproject.rst b/Help/command/include_external_msproject.rst
index 540a13af8..435465462 100644
--- a/Help/command/include_external_msproject.rst
+++ b/Help/command/include_external_msproject.rst
@@ -21,6 +21,7 @@ specify the type of project, id (``GUID``) of the project and the name of
the target platform. This is useful for projects requiring values
other than the default (e.g. WIX projects).
-If the imported project has different configuration names than the
-current project, set the :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>`
-target property to specify the mapping.
+.. versionadded:: 3.9
+ If the imported project has different configuration names than the
+ current project, set the :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>`
+ target property to specify the mapping.
diff --git a/Help/command/install.rst b/Help/command/install.rst
index c11eaf429..35207f4c4 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -20,10 +20,13 @@ Introduction
This command generates installation rules for a project. Install rules
specified by calls to the ``install()`` command within a source directory
-are executed in order during installation. Install rules in subdirectories
-added by calls to the :command:`add_subdirectory` command are interleaved
-with those in the parent directory to run in the order declared (see
-policy :policy:`CMP0082`).
+are executed in order during installation.
+
+.. versionchanged:: 3.14
+ Install rules in subdirectories
+ added by calls to the :command:`add_subdirectory` command are interleaved
+ with those in the parent directory to run in the order declared (see
+ policy :policy:`CMP0082`).
There are multiple signatures for this command. Some of them define
installation options for files and targets. Options common to
@@ -85,6 +88,8 @@ signatures that specify them. The common options are:
:variable:`CMAKE_INSTALL_DEFAULT_COMPONENT_NAME` variable.
``EXCLUDE_FROM_ALL``
+ .. versionadded:: 3.6
+
Specify that the file is excluded from a full installation and only
installed as part of a component-specific installation
@@ -97,16 +102,18 @@ signatures that specify them. The common options are:
Specify that it is not an error if the file to be installed does
not exist.
-Command signatures that install files may print messages during
-installation. Use the :variable:`CMAKE_INSTALL_MESSAGE` variable
-to control which messages are printed.
+.. versionadded:: 3.1
+ Command signatures that install files may print messages during
+ installation. Use the :variable:`CMAKE_INSTALL_MESSAGE` variable
+ to control which messages are printed.
-Many of the ``install()`` variants implicitly create the directories
-containing the installed files. If
-:variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` is set, these
-directories will be created with the permissions specified. Otherwise,
-they will be created according to the uname rules on Unix-like platforms.
-Windows platforms are unaffected.
+.. versionadded:: 3.11
+ Many of the ``install()`` variants implicitly create the directories
+ containing the installed files. If
+ :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` is set, these
+ directories will be created with the permissions specified. Otherwise,
+ they will be created according to the uname rules on Unix-like platforms.
+ Windows platforms are unaffected.
Installing Targets
^^^^^^^^^^^^^^^^^^
@@ -162,6 +169,8 @@ that may be installed:
accompanying import libraries are of kind ``ARCHIVE``).
``OBJECTS``
+ .. versionadded:: 3.9
+
Object files associated with *object libraries*.
``FRAMEWORK``
@@ -246,6 +255,8 @@ In addition to the common options listed above, each target can accept
the following additional arguments:
``NAMELINK_COMPONENT``
+ .. versionadded:: 3.12
+
On some platforms a versioned shared library has a symbolic link such
as::
@@ -357,17 +368,19 @@ targets that link to the object libraries in their implementation.
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
set to ``TRUE`` has undefined behavior.
-`install(TARGETS)`_ can install targets that were created in
-other directories. When using such cross-directory install rules, running
-``make install`` (or similar) from a subdirectory will not guarantee that
-targets from other directories are up-to-date. You can use
-:command:`target_link_libraries` or :command:`add_dependencies`
-to ensure that such out-of-directory targets are built before the
-subdirectory-specific install rules are run.
+.. versionadded:: 3.3
+ An install destination given as a ``DESTINATION`` argument may
+ use "generator expressions" with the syntax ``$<...>``. See the
+ :manual:`cmake-generator-expressions(7)` manual for available expressions.
-An install destination given as a ``DESTINATION`` argument may
-use "generator expressions" with the syntax ``$<...>``. See the
-:manual:`cmake-generator-expressions(7)` manual for available expressions.
+.. versionadded:: 3.13
+ `install(TARGETS)`_ can install targets that were created in
+ other directories. When using such cross-directory install rules, running
+ ``make install`` (or similar) from a subdirectory will not guarantee that
+ targets from other directories are up-to-date. You can use
+ :command:`target_link_libraries` or :command:`add_dependencies`
+ to ensure that such out-of-directory targets are built before the
+ subdirectory-specific install rules are run.
Installing Files
^^^^^^^^^^^^^^^^
@@ -455,9 +468,15 @@ this advice while installing headers to a project-specific subdirectory:
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/myproj
)
-An install destination given as a ``DESTINATION`` argument may
-use "generator expressions" with the syntax ``$<...>``. See the
-:manual:`cmake-generator-expressions(7)` manual for available expressions.
+.. versionadded:: 3.4
+ An install destination given as a ``DESTINATION`` argument may
+ use "generator expressions" with the syntax ``$<...>``. See the
+ :manual:`cmake-generator-expressions(7)` manual for available expressions.
+
+.. versionadded:: 3.20
+ An install rename given as a ``RENAME`` argument may
+ use "generator expressions" with the syntax ``$<...>``. See the
+ :manual:`cmake-generator-expressions(7)` manual for available expressions.
Installing Directories
^^^^^^^^^^^^^^^^^^^^^^
@@ -495,7 +514,8 @@ permissions specified in the ``FILES`` form of the command, and the
directories will be given the default permissions specified in the
``PROGRAMS`` form of the command.
-The ``MESSAGE_NEVER`` option disables file installation status output.
+.. versionadded:: 3.1
+ The ``MESSAGE_NEVER`` option disables file installation status output.
Installation of directories may be controlled with fine granularity
using the ``PATTERN`` or ``REGEX`` options. These "match" options specify a
@@ -579,10 +599,14 @@ path that begins with the appropriate :module:`GNUInstallDirs` variable.
This allows package maintainers to control the install destination by setting
the appropriate cache variables.
-The list of ``dirs...`` given to ``DIRECTORY`` and an install destination
-given as a ``DESTINATION`` argument may use "generator expressions"
-with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
-manual for available expressions.
+.. versionadded:: 3.4
+ An install destination given as a ``DESTINATION`` argument may
+ use "generator expressions" with the syntax ``$<...>``. See the
+ :manual:`cmake-generator-expressions(7)` manual for available expressions.
+
+.. versionadded:: 3.5
+ The list of ``dirs...`` given to ``DIRECTORY`` may use
+ "generator expressions" too.
Custom Installation Logic
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -610,10 +634,11 @@ example, the code
will print a message during installation.
-``<file>`` or ``<code>`` may use "generator expressions" with the syntax
-``$<...>`` (in the case of ``<file>``, this refers to their use in the file
-name, not the file's contents). See the
-:manual:`cmake-generator-expressions(7)` manual for available expressions.
+.. 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
+ name, not the file's contents). See the
+ :manual:`cmake-generator-expressions(7)` manual for available expressions.
Installing Exports
^^^^^^^^^^^^^^^^^^
@@ -673,13 +698,14 @@ RPM, typically handle this by listing the ``Runtime`` component as a dependency
of the ``Development`` component in the package metadata, ensuring that the
library is always installed if the headers and CMake export file are present.
-In addition to cmake language files, the ``EXPORT_ANDROID_MK`` mode maybe
-used to specify an export to the android ndk build system. This mode
-accepts the same options as the normal export mode. The Android
-NDK supports the use of prebuilt libraries, both static and shared. This
-allows cmake to build the libraries of a project and make them available
-to an ndk build system complete with transitive dependencies, include flags
-and defines required to use the libraries.
+.. versionadded:: 3.7
+ In addition to cmake language files, the ``EXPORT_ANDROID_MK`` mode maybe
+ used to specify an export to the android ndk build system. This mode
+ accepts the same options as the normal export mode. The Android
+ NDK supports the use of prebuilt libraries, both static and shared. This
+ allows cmake to build the libraries of a project and make them available
+ to an ndk build system complete with transitive dependencies, include flags
+ and defines required to use the libraries.
The ``EXPORT`` form is useful to help outside projects use targets built
and installed by the current project. For example, the code
diff --git a/Help/command/link_directories.rst b/Help/command/link_directories.rst
index 9cb8faa74..673240234 100644
--- a/Help/command/link_directories.rst
+++ b/Help/command/link_directories.rst
@@ -11,21 +11,25 @@ Adds the paths in which the linker should search for libraries.
Relative paths given to this command are interpreted as relative to
the current source directory, see :policy:`CMP0015`.
-The directories are added to the :prop_dir:`LINK_DIRECTORIES` directory
-property for the current ``CMakeLists.txt`` file, converting relative
-paths to absolute as needed.
The command will apply only to targets created after it is called.
-By default the directories specified are appended onto the current list of
-directories. This default behavior can be changed by setting
-:variable:`CMAKE_LINK_DIRECTORIES_BEFORE` to ``ON``. By using
-``AFTER`` or ``BEFORE`` explicitly, you can select between appending and
-prepending, independent of the default.
-
-Arguments to ``link_directories`` 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.
+.. versionadded:: 3.13
+ The directories are added to the :prop_dir:`LINK_DIRECTORIES` directory
+ property for the current ``CMakeLists.txt`` file, converting relative
+ paths to absolute as needed. See the :manual:`cmake-buildsystem(7)`
+ manual for more on defining buildsystem properties.
+
+.. versionadded:: 3.13
+ By default the directories specified are appended onto the current list of
+ directories. This default behavior can be changed by setting
+ :variable:`CMAKE_LINK_DIRECTORIES_BEFORE` to ``ON``. By using
+ ``AFTER`` or ``BEFORE`` explicitly, you can select between appending and
+ prepending, independent of the default.
+
+.. versionadded:: 3.13
+ Arguments to ``link_directories`` may use "generator expressions" with
+ the syntax "$<...>". See the :manual:`cmake-generator-expressions(7)`
+ manual for available expressions.
.. note::
diff --git a/Help/command/list.rst b/Help/command/list.rst
index 4d339a03c..7accc5a39 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -88,6 +88,8 @@ Returns the list of elements specified by indices from the list.
list(JOIN <list> <glue> <output variable>)
+.. versionadded:: 3.12
+
Returns a string joining all list's elements using the glue string.
To join multiple strings, which are not part of a list, use ``JOIN`` operator
from :command:`string` command.
@@ -98,6 +100,8 @@ from :command:`string` command.
list(SUBLIST <list> <begin> <length> <output variable>)
+.. versionadded:: 3.12
+
Returns a sublist of the given list.
If ``<length>`` is 0, an empty list will be returned.
If ``<length>`` is -1 or the list is smaller than ``<begin>+<length>`` then
@@ -132,6 +136,8 @@ Appends elements to the list.
list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
+.. versionadded:: 3.6
+
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.
@@ -152,6 +158,8 @@ Inserts elements to the list to the specified location.
list(POP_BACK <list> [<out-var>...])
+.. versionadded:: 3.15
+
If no variable name is given, removes exactly one element. Otherwise,
assign the last element's value to the given variable and removes it,
up to the last variable name given.
@@ -162,6 +170,8 @@ up to the last variable name given.
list(POP_FRONT <list> [<out-var>...])
+.. versionadded:: 3.15
+
If no variable name is given, removes exactly one element. Otherwise,
assign the first element's value to the given variable and removes it,
up to the last variable name given.
@@ -172,6 +182,8 @@ up to the last variable name given.
list(PREPEND <list> [<element> ...])
+.. versionadded:: 3.15
+
Insert elements to the 0th position in the list.
.. _REMOVE_ITEM:
@@ -206,6 +218,8 @@ but if duplicates are encountered, only the first instance is preserved.
list(TRANSFORM <list> <ACTION> [<SELECTOR>]
[OUTPUT_VARIABLE <output variable>])
+.. versionadded:: 3.12
+
Transforms the list by applying an action to all or, by specifying a
``<SELECTOR>``, to the selected elements of the list, storing the result
in-place or in the specified output variable.
@@ -302,6 +316,13 @@ Reverses the contents of the list in-place.
list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
Sorts the list in-place alphabetically.
+
+.. versionadded:: 3.13
+ Added the ``COMPARE``, ``CASE``, and ``ORDER`` options.
+
+.. versionadded:: 3.18
+ Added the ``COMPARE NATURAL`` option.
+
Use the ``COMPARE`` keyword to select the comparison method for sorting.
The ``<compare>`` option should be one of:
diff --git a/Help/command/macro.rst b/Help/command/macro.rst
index 797a90d8f..5fe4c00ef 100644
--- a/Help/command/macro.rst
+++ b/Help/command/macro.rst
@@ -48,8 +48,9 @@ and so on. However, it is strongly recommended to stay with the
case chosen in the macro definition. Typically macros use
all-lowercase names.
-The :command:`cmake_language(CALL ...)` command can also be used to
-invoke the macro.
+.. versionadded:: 3.18
+ The :command:`cmake_language(CALL ...)` command can also be used to
+ invoke the macro.
Arguments
^^^^^^^^^
diff --git a/Help/command/mark_as_advanced.rst b/Help/command/mark_as_advanced.rst
index e52e623a7..201363fad 100644
--- a/Help/command/mark_as_advanced.rst
+++ b/Help/command/mark_as_advanced.rst
@@ -23,8 +23,6 @@ new values will be marked as advanced, but if a
variable already has an advanced/non-advanced state,
it will not be changed.
-.. note::
-
- Policy :policy:`CMP0102` affects the behavior of the ``mark_as_advanced``
- call. When set to ``NEW``, variables passed to this command which are not
- already in the cache are ignored. See policy :policy:`CMP0102`.
+.. versionchanged:: 3.17
+ Variables passed to this command which are not already in the cache
+ are ignored. See policy :policy:`CMP0102`.
diff --git a/Help/command/math.rst b/Help/command/math.rst
index ddb1ec63c..8386aabc6 100644
--- a/Help/command/math.rst
+++ b/Help/command/math.rst
@@ -17,17 +17,18 @@ Supported operators are ``+``, ``-``, ``*``, ``/``, ``%``, ``|``, ``&``,
``^``, ``~``, ``<<``, ``>>``, and ``(...)``; they have the same meaning
as in C code.
-Hexadecimal numbers are recognized when prefixed with ``0x``, as in C code.
-
-The result is formatted according to the option ``OUTPUT_FORMAT``,
-where ``<format>`` is one of
-
-``HEXADECIMAL``
- Hexadecimal notation as in C code, i. e. starting with "0x".
-``DECIMAL``
- Decimal notation. Which is also used if no ``OUTPUT_FORMAT`` option
- is specified.
-
+.. versionadded:: 3.13
+ Hexadecimal numbers are recognized when prefixed with ``0x``, as in C code.
+
+.. versionadded:: 3.13
+ The result is formatted according to the option ``OUTPUT_FORMAT``,
+ where ``<format>`` is one of
+
+ ``HEXADECIMAL``
+ Hexadecimal notation as in C code, i. e. starting with "0x".
+ ``DECIMAL``
+ Decimal notation. Which is also used if no ``OUTPUT_FORMAT`` option
+ is specified.
For example
diff --git a/Help/command/message.rst b/Help/command/message.rst
index 6bc0e4cfc..e44803e85 100644
--- a/Help/command/message.rst
+++ b/Help/command/message.rst
@@ -71,6 +71,9 @@ influences the way the message is handled:
using this log level would normally only be temporary and would expect to be
removed before releasing the project, packaging up the files, etc.
+.. versionadded:: 3.15
+ Added the ``NOTICE``, ``VERBOSE``, ``DEBUG``, and ``TRACE`` levels.
+
The CMake command-line tool displays ``STATUS`` to ``TRACE`` messages on stdout
with the message preceded by two hyphens and a space. All other message types
are sent to stderr and are not prefixed with hyphens. The
@@ -79,25 +82,29 @@ The :manual:`curses interface <ccmake(1)>` shows ``STATUS`` to ``TRACE``
messages one at a time on a status line and other messages in an
interactive pop-up box. The ``--log-level`` command-line option to each of
these tools can be used to control which messages will be shown.
-To make a log level persist between CMake runs, the
-:variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can be set instead.
-Note that the command line option takes precedence over the cache variable.
-
-Messages of log levels ``NOTICE`` and below will have each line preceded
-by the content of the :variable:`CMAKE_MESSAGE_INDENT` variable (converted to
-a single string by concatenating its list items). For ``STATUS`` to ``TRACE``
-messages, this indenting content will be inserted after the hyphens.
-
-Messages of log levels ``NOTICE`` and below can also have each line preceded
-with context of the form ``[some.context.example]``. The content between the
-square brackets is obtained by converting the :variable:`CMAKE_MESSAGE_CONTEXT`
-list variable to a dot-separated string. The message context will always
-appear before any indenting content but after any automatically added leading
-hyphens. By default, message context is not shown, it has to be explicitly
-enabled by giving the :manual:`cmake <cmake(1)>` ``--log-context``
-command-line option or by setting the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW`
-variable to true. See the :variable:`CMAKE_MESSAGE_CONTEXT` documentation for
-usage examples.
+
+.. versionadded:: 3.17
+ To make a log level persist between CMake runs, the
+ :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can be set instead.
+ Note that the command line option takes precedence over the cache variable.
+
+.. versionadded:: 3.16
+ Messages of log levels ``NOTICE`` and below will have each line preceded
+ by the content of the :variable:`CMAKE_MESSAGE_INDENT` variable (converted to
+ a single string by concatenating its list items). For ``STATUS`` to ``TRACE``
+ messages, this indenting content will be inserted after the hyphens.
+
+.. versionadded:: 3.17
+ Messages of log levels ``NOTICE`` and below can also have each line preceded
+ with context of the form ``[some.context.example]``. The content between the
+ square brackets is obtained by converting the :variable:`CMAKE_MESSAGE_CONTEXT`
+ list variable to a dot-separated string. The message context will always
+ appear before any indenting content but after any automatically added leading
+ hyphens. By default, message context is not shown, it has to be explicitly
+ enabled by giving the :manual:`cmake <cmake(1)>` ``--log-context``
+ command-line option or by setting the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW`
+ variable to true. See the :variable:`CMAKE_MESSAGE_CONTEXT` documentation for
+ usage examples.
CMake Warning and Error message text displays using a simple markup
language. Non-indented text is formatted in line-wrapped paragraphs
@@ -107,6 +114,8 @@ delimited by newlines. Indented text is considered pre-formatted.
Reporting checks
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.17
+
A common pattern in CMake output is a message indicating the start of some
sort of check, followed by another message reporting the result of that check.
For example:
diff --git a/Help/command/project.rst b/Help/command/project.rst
index c325050f9..6c931b692 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -55,10 +55,14 @@ The options are:
* :variable:`PROJECT_VERSION_TWEAK`,
:variable:`<PROJECT-NAME>_VERSION_TWEAK`.
- When the ``project()`` command is called from the top-level ``CMakeLists.txt``,
- then the version is also stored in the variable :variable:`CMAKE_PROJECT_VERSION`.
+ .. versionadded:: 3.12
+ When the ``project()`` command is called from the top-level
+ ``CMakeLists.txt``, then the version is also stored in the variable
+ :variable:`CMAKE_PROJECT_VERSION`.
``DESCRIPTION <project-description-string>``
+ .. versionadded:: 3.9
+
Optional.
Sets the variables
@@ -71,7 +75,12 @@ The options are:
When the ``project()`` command is called from the top-level ``CMakeLists.txt``,
then the description is also stored in the variable :variable:`CMAKE_PROJECT_DESCRIPTION`.
+ .. versionadded:: 3.12
+ Added the ``<PROJECT-NAME>_DESCRIPTION`` variable.
+
``HOMEPAGE_URL <url-string>``
+ .. versionadded:: 3.12
+
Optional.
Sets the variables
@@ -93,6 +102,15 @@ The options are:
Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
to skip enabling any languages.
+ .. versionadded:: 3.8
+ Added ``CUDA`` support.
+
+ .. versionadded:: 3.16
+ Added ``OBJC`` and ``OBJCXX`` support.
+
+ .. versionadded:: 3.18
+ Added ``ISPC`` support.
+
If enabling ``ASM``, list it last so that CMake can check whether
compilers for other languages like ``C`` work for assembly too.
@@ -115,6 +133,13 @@ they point to will be included as the last step of the ``project()`` command.
If both are set, then :variable:`CMAKE_PROJECT_INCLUDE` will be included before
:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`.
+.. versionadded:: 3.15
+ Added the ``CMAKE_PROJECT_INCLUDE`` and ``CMAKE_PROJECT_INCLUDE_BEFORE``
+ variables.
+
+.. versionadded:: 3.17
+ Added the ``CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`` variable.
+
Usage
^^^^^
diff --git a/Help/command/separate_arguments.rst b/Help/command/separate_arguments.rst
index 69fb72672..f66af35a5 100644
--- a/Help/command/separate_arguments.rst
+++ b/Help/command/separate_arguments.rst
@@ -32,10 +32,14 @@ be one of the following keywords:
MSDN article `Parsing C Command-Line Arguments`_ for details.
``NATIVE_COMMAND``
+ .. versionadded:: 3.9
+
Proceeds as in ``WINDOWS_COMMAND`` mode if the host system is Windows.
Otherwise proceeds as in ``UNIX_COMMAND`` mode.
``PROGRAM``
+ .. versionadded:: 3.19
+
The first item in ``<args>`` is assumed to be an executable and will be
searched in the system search path or left as a full path. If not found,
``<variable>`` will be empty. Otherwise, ``<variable>`` is a list of 2
diff --git a/Help/command/set_property.rst b/Help/command/set_property.rst
index b5c1613e3..bf437b434 100644
--- a/Help/command/set_property.rst
+++ b/Help/command/set_property.rst
@@ -28,11 +28,12 @@ It must be one of the following:
``DIRECTORY``
Scope defaults to the current directory but other directories
(already processed by CMake) may be named by full or relative path.
- Each path may reference either a source directory, or since CMake 3.19,
- a binary directory.
Relative paths are treated as relative to the current source directory.
See also the :command:`set_directory_properties` command.
+ .. versionadded:: 3.19
+ ``<dir>`` may reference a binary directory.
+
``TARGET``
Scope may name zero or more existing targets.
See also the :command:`set_target_properties` command.
@@ -40,25 +41,31 @@ It must be one of the following:
``SOURCE``
Scope may name zero or more source files. By default, source file properties
are only visible to targets added in the same directory (``CMakeLists.txt``).
- Visibility can be set in other directory scopes using one or both of the
- following sub-options:
-
- ``DIRECTORY <dirs>...``
- The source file property will be set in each of the ``<dirs>``
- directories' scopes. Each path may reference either a source directory,
- or since CMake 3.19, a binary directory. CMake must already know about
- each of these directories, either by having added them through a call to
- :command:`add_subdirectory` or it being the top level source directory.
- Relative paths are treated as relative to the current source directory.
-
- ``TARGET_DIRECTORY <targets>...``
- The source file property will be set in each of the directory scopes
- where any of the specified ``<targets>`` were created (the ``<targets>``
- must therefore already exist).
+
+ .. versionadded:: 3.18
+ Visibility can be set in other directory scopes using one or both of the
+ following sub-options:
+
+ ``DIRECTORY <dirs>...``
+ The source file property will be set in each of the ``<dirs>``
+ directories' scopes. CMake must already know about
+ each of these directories, either by having added them through a call to
+ :command:`add_subdirectory` or it being the top level source directory.
+ Relative paths are treated as relative to the current source directory.
+
+ .. versionadded:: 3.19
+ ``<dirs>`` may reference a binary directory.
+
+ ``TARGET_DIRECTORY <targets>...``
+ The source file property will be set in each of the directory scopes
+ where any of the specified ``<targets>`` were created (the ``<targets>``
+ must therefore already exist).
See also the :command:`set_source_files_properties` command.
``INSTALL``
+ .. versionadded:: 3.1
+
Scope may name zero or more installed file paths.
These are made available to CPack to influence deployment.
@@ -98,3 +105,8 @@ directly set in the nominated scope, the command will behave as though
See the :manual:`cmake-properties(7)` manual for a list of properties
in each scope.
+
+.. note::
+
+ The :prop_sf:`GENERATED` source file property may be globally visible.
+ See its documentation for details.
diff --git a/Help/command/set_source_files_properties.rst b/Help/command/set_source_files_properties.rst
index 9558b4036..61c69a2e9 100644
--- a/Help/command/set_source_files_properties.rst
+++ b/Help/command/set_source_files_properties.rst
@@ -14,9 +14,10 @@ Source files can have properties that affect how they are built.
Sets properties associated with source files using a key/value paired
list.
-By default, source file properties are only visible to targets added in the
-same directory (``CMakeLists.txt``). Visibility can be set in other directory
-scopes using one or both of the following options:
+.. versionadded:: 3.18
+ By default, source file properties are only visible to targets added in the
+ same directory (``CMakeLists.txt``). Visibility can be set in other directory
+ scopes using one or both of the following options:
``DIRECTORY <dirs>...``
The source file properties will be set in each of the ``<dirs>``
@@ -35,3 +36,8 @@ See also the :command:`set_property(SOURCE)` command.
See :ref:`Source File Properties` for the list of properties known
to CMake.
+
+.. note::
+
+ The :prop_sf:`GENERATED` source file property may be globally visible.
+ See its documentation for details.
diff --git a/Help/command/site_name.rst b/Help/command/site_name.rst
index 1bcaeada0..09b5a9fbd 100644
--- a/Help/command/site_name.rst
+++ b/Help/command/site_name.rst
@@ -6,3 +6,7 @@ Set the given variable to the name of the computer.
.. code-block:: cmake
site_name(variable)
+
+On UNIX-like platforms, if the variable ``HOSTNAME`` is set, its value
+will be executed as a command expected to print out the host name,
+much like the ``hostname`` command-line tool.
diff --git a/Help/command/source_group.rst b/Help/command/source_group.rst
index 5ae9e5144..5db1ec8c5 100644
--- a/Help/command/source_group.rst
+++ b/Help/command/source_group.rst
@@ -14,12 +14,16 @@ This is intended to set up file tabs in Visual Studio.
The options are:
``TREE``
+ .. versionadded:: 3.8
+
CMake will automatically detect, from ``<src>`` files paths, source groups
it needs to create, to keep structure of source groups analogically to the
actual files and directories structure in the project. Paths of ``<src>``
files will be cut to be relative to ``<root>``.
``PREFIX``
+ .. versionadded:: 3.8
+
Source group and files located directly in ``<root>`` path, will be placed
in ``<prefix>`` source groups.
@@ -47,6 +51,9 @@ appropriately:
source_group(outer\\inner ...)
source_group(TREE <root> PREFIX sources\\inc ...)
+.. versionadded:: 3.18
+ Allow using forward slashes (``/``) to specify subgroups.
+
For backwards compatibility, the short-hand signature
.. code-block:: cmake
diff --git a/Help/command/string.rst b/Help/command/string.rst
index 51f8d821a..8ad0089af 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -170,10 +170,12 @@ The following characters have special meaning in regular expressions:
Matches a pattern on either side of the ``|``
``()``
Saves a matched subexpression, which can be referenced
- in the ``REGEX REPLACE`` operation. Additionally it is saved
- by all regular expression-related commands, including
- e.g. :command:`if(MATCHES)`, in the variables
- :variable:`CMAKE_MATCH_<n>` for ``<n>`` 0..9.
+ in the ``REGEX REPLACE`` operation.
+
+ .. versionadded:: 3.9
+ All regular expression-related commands, including e.g.
+ :command:`if(MATCHES)`, save subgroup matches in the variables
+ :variable:`CMAKE_MATCH_<n>` for ``<n>`` 0..9.
``*``, ``+`` and ``?`` have higher precedence than concatenation. ``|``
has lower precedence than concatenation. This means that the regular
@@ -205,6 +207,8 @@ Manipulation
string(APPEND <string_variable> [<input>...])
+.. versionadded:: 3.4
+
Append all the ``<input>`` arguments to the string.
.. _PREPEND:
@@ -213,6 +217,8 @@ Append all the ``<input>`` arguments to the string.
string(PREPEND <string_variable> [<input>...])
+.. versionadded:: 3.10
+
Prepend all the ``<input>`` arguments to the string.
.. _CONCAT:
@@ -230,6 +236,8 @@ the result in the named ``<output_variable>``.
string(JOIN <glue> <output_variable> [<input>...])
+.. versionadded:: 3.12
+
Join all the ``<input>`` arguments together using the ``<glue>``
string and store the result in the named ``<output_variable>``.
@@ -271,16 +279,15 @@ result stored in ``<output_variable>`` will *not* be the number of characters.
Store in an ``<output_variable>`` a substring of a given ``<string>``. If
``<length>`` is ``-1`` the remainder of the string starting at ``<begin>``
-will be returned. If ``<string>`` is shorter than ``<length>`` then the
-end of the string is used instead.
+will be returned.
+
+.. versionchanged:: 3.2
+ If ``<string>`` is shorter than ``<length>`` then the end of the string
+ is used instead. Previous versions of CMake reported an error in this case.
Both ``<begin>`` and ``<length>`` are counted in bytes, so care must
be exercised if ``<string>`` could contain multi-byte characters.
-.. note::
- CMake 3.1 and below reported an error if ``<length>`` pointed past
- the end of ``<string>``.
-
.. _STRIP:
.. code-block:: cmake
@@ -296,6 +303,8 @@ leading and trailing spaces removed.
string(GENEX_STRIP <string> <output_variable>)
+.. versionadded:: 3.1
+
Strip any :manual:`generator expressions <cmake-generator-expressions(7)>`
from the input ``<string>`` and store the result in the ``<output_variable>``.
@@ -305,6 +314,8 @@ from the input ``<string>`` and store the result in the ``<output_variable>``.
string(REPEAT <string> <count> <output_variable>)
+.. versionadded:: 3.15
+
Produce the output string as the input ``<string>`` repeated ``<count>`` times.
Comparison
@@ -323,6 +334,9 @@ Comparison
Compare the strings and store true or false in the ``<output_variable>``.
+.. versionadded:: 3.7
+ Added the ``LESS_EQUAL`` and ``GREATER_EQUAL`` options.
+
.. _`Supported Hash Algorithms`:
Hashing
@@ -358,6 +372,9 @@ The supported ``<HASH>`` algorithm names are:
``SHA3_512``
Keccak SHA-3.
+.. versionadded:: 3.8
+ Added the ``SHA3_*`` hash algorithms.
+
Generation
^^^^^^^^^^
@@ -375,6 +392,8 @@ Convert all numbers into corresponding ASCII characters.
string(HEX <string> <output_variable>)
+.. versionadded:: 3.18
+
Convert each byte in the input ``<string>`` to its hexadecimal representation
and store the concatenated hex digits in the ``<output_variable>``. Letters in
the output (``a`` through ``f``) are in lowercase.
@@ -451,6 +470,18 @@ specifiers:
%y The last two digits of the current year (00-99)
%Y The current year.
+.. versionadded:: 3.6
+ ``%s`` format specifier (UNIX time).
+
+.. versionadded:: 3.7
+ ``%a`` and ``%b`` format specifiers (abbreviated month and weekday names).
+
+.. versionadded:: 3.8
+ ``%%`` specifier (literal ``%``).
+
+.. versionadded:: 3.7
+ ``%A`` and ``%B`` format specifiers (full month and weekday names).
+
Unknown format specifiers will be ignored and copied to the output
as-is.
@@ -461,8 +492,7 @@ If no explicit ``<format_string>`` is given, it will default to:
%Y-%m-%dT%H:%M:%S for local time.
%Y-%m-%dT%H:%M:%SZ for UTC.
-.. note::
-
+.. versionadded:: 3.8
If the ``SOURCE_DATE_EPOCH`` environment variable is set,
its value will be used instead of the current time.
See https://reproducible-builds.org/specs/source-date-epoch/ for details.
@@ -474,6 +504,8 @@ If no explicit ``<format_string>`` is given, it will default to:
string(UUID <output_variable> NAMESPACE <namespace> NAME <name>
TYPE <MD5|SHA1> [UPPER])
+.. versionadded:: 3.1
+
Create a universally unique identifier (aka GUID) as per RFC4122
based on the hash of the combined values of ``<namespace>``
(which itself has to be a valid UUID) and ``<name>``.
@@ -489,6 +521,8 @@ with the optional ``UPPER`` flag.
JSON
^^^^
+.. versionadded:: 3.19
+
Functionality for querying a JSON string.
.. note::
diff --git a/Help/command/target_compile_definitions.rst b/Help/command/target_compile_definitions.rst
index 9e9c69093..3fb113a92 100644
--- a/Help/command/target_compile_definitions.rst
+++ b/Help/command/target_compile_definitions.rst
@@ -19,10 +19,12 @@ specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
items will populate the :prop_tgt:`COMPILE_DEFINITIONS` property of
``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property of ``<target>``.
-(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
The following arguments specify compile definitions. Repeated calls for the
same ``<target>`` append items in the order called.
+.. versionadded:: 3.11
+ Allow setting ``INTERFACE`` items on :ref:`IMPORTED targets <Imported Targets>`.
+
Arguments to ``target_compile_definitions`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
@@ -37,3 +39,12 @@ For example, the following are all equivalent:
target_compile_definitions(foo PUBLIC -DFOO) # -D removed
target_compile_definitions(foo PUBLIC "" FOO) # "" ignored
target_compile_definitions(foo PUBLIC -D FOO) # -D becomes "", then ignored
+
+Definitions may optionally have values:
+
+.. code-block:: cmake
+
+ target_compile_definitions(foo PUBLIC FOO=1)
+
+Note that many compilers treat ``-DFOO`` as equivalent to ``-DFOO=1``, but
+other tools may not recognize this in all circumstances (e.g. IntelliSense).
diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst
index b50be34a6..58502bfc2 100644
--- a/Help/command/target_compile_features.rst
+++ b/Help/command/target_compile_features.rst
@@ -21,9 +21,11 @@ specify the scope of the features. ``PRIVATE`` and ``PUBLIC`` items will
populate the :prop_tgt:`COMPILE_FEATURES` property of ``<target>``.
``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ``<target>``.
-(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
Repeated calls for the same ``<target>`` append items.
+.. versionadded:: 3.11
+ Allow setting ``INTERFACE`` items on :ref:`IMPORTED targets <Imported Targets>`.
+
The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an
:ref:`ALIAS target <Alias Targets>`.
diff --git a/Help/command/target_compile_options.rst b/Help/command/target_compile_options.rst
index 3c733c5d7..e45b209ad 100644
--- a/Help/command/target_compile_options.rst
+++ b/Help/command/target_compile_options.rst
@@ -26,10 +26,12 @@ specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
items will populate the :prop_tgt:`COMPILE_OPTIONS` property of
``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property of ``<target>``.
-(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
The following arguments specify compile options. Repeated calls for the same
``<target>`` append items in the order called.
+.. versionadded:: 3.11
+ Allow setting ``INTERFACE`` items on :ref:`IMPORTED targets <Imported Targets>`.
+
Arguments to ``target_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)`
diff --git a/Help/command/target_include_directories.rst b/Help/command/target_include_directories.rst
index 660e15c9b..3e53b2e4a 100644
--- a/Help/command/target_include_directories.rst
+++ b/Help/command/target_include_directories.rst
@@ -5,7 +5,7 @@ Add include directories to a target.
.. code-block:: cmake
- target_include_directories(<target> [SYSTEM] [BEFORE]
+ target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
@@ -14,17 +14,19 @@ The named ``<target>`` must have been created by a command such
as :command:`add_executable` or :command:`add_library` and must not be an
:ref:`ALIAS target <Alias Targets>`.
-If ``BEFORE`` is specified, the content will be prepended to the property
-instead of being appended.
+By using ``AFTER`` or ``BEFORE`` explicitly, you can select between appending
+and prepending, independent of the default.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to specify
the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` items will
populate the :prop_tgt:`INCLUDE_DIRECTORIES` property of ``<target>``.
``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property of ``<target>``.
-(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
The following arguments specify include directories.
+.. versionadded:: 3.11
+ Allow setting ``INTERFACE`` items on :ref:`IMPORTED targets <Imported Targets>`.
+
Specified include directories may be absolute paths or relative paths.
Repeated calls for the same <target> append items in the order called. If
``SYSTEM`` is specified, the compiler will be told the
diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst
index c2e7e8ac9..872e264e9 100644
--- a/Help/command/target_link_libraries.rst
+++ b/Help/command/target_link_libraries.rst
@@ -27,6 +27,10 @@ set to ``NEW`` then the target must have been created in the current
directory. Repeated calls for the same ``<target>`` append items in
the order called.
+.. versionadded:: 3.13
+ The ``<target>`` doesn't have to be defined in the same directory as the
+ ``target_link_libraries`` call.
+
Each ``<item>`` may be:
* **A library target name**: The generated link line will have the
@@ -62,10 +66,11 @@ Each ``<item>`` may be:
:ref:`usage requirement <Target Usage Requirements>`. This has the same
effect as passing the framework directory as an include directory.
- On :ref:`Visual Studio Generators` for VS 2010 and above, library files
- ending in ``.targets`` will be treated as MSBuild targets files and
- imported into generated project files. This is not supported by other
- generators.
+ .. versionadded:: 3.8
+ On :ref:`Visual Studio Generators` for VS 2010 and above, library files
+ ending in ``.targets`` will be treated as MSBuild targets files and
+ imported into generated project files. This is not supported by other
+ generators.
The full path to the library file will be quoted/escaped for
the shell automatically.
@@ -89,6 +94,11 @@ Each ``<item>`` may be:
flags explicitly. The flags will then be placed at the toolchain-defined
flag position in the link command.
+ .. versionadded:: 3.13
+ :prop_tgt:`LINK_OPTIONS` target property and :command:`target_link_options`
+ command. For earlier versions of CMake, use :prop_tgt:`LINK_FLAGS`
+ property instead.
+
The link flag is treated as a command-line string fragment and
will be used with no extra quoting or escaping.
@@ -216,6 +226,8 @@ is not ``NEW``, they are also appended to the
Linking Object Libraries
^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.12
+
:ref:`Object Libraries` may be used as the ``<target>`` (first) argument
of ``target_link_libraries`` to specify dependencies of their sources
on other libraries. For example, the code
diff --git a/Help/command/target_link_options.rst b/Help/command/target_link_options.rst
index e59e0e1c6..87dff39ae 100644
--- a/Help/command/target_link_options.rst
+++ b/Help/command/target_link_options.rst
@@ -36,10 +36,12 @@ specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
items will populate the :prop_tgt:`LINK_OPTIONS` property of
``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_LINK_OPTIONS` property of ``<target>``.
-(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
The following arguments specify link options. Repeated calls for the same
``<target>`` append items in the order called.
+.. note::
+ :ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.
+
Arguments to ``target_link_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)`
diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst
index 700518063..9f7dabbd4 100644
--- a/Help/command/target_precompile_headers.rst
+++ b/Help/command/target_precompile_headers.rst
@@ -34,7 +34,7 @@ Repeated calls for the same ``<target>`` will append items in the order called.
Projects should generally avoid using ``PUBLIC`` or ``INTERFACE`` for targets
that will be :ref:`exported <install(EXPORT)>`, or they should at least use
-the ``$<BUILD_INTERFACE:...>`` generator expression to prevent precompile
+the :genex:`$<BUILD_INTERFACE:...>` generator expression to prevent precompile
headers from appearing in an installed exported target. Consumers of a target
should typically be in control of what precompile headers they use, not have
precompile headers forced on them by the targets being consumed (since
@@ -74,7 +74,7 @@ Arguments to ``target_precompile_headers()`` may use "generator expressions"
with the syntax ``$<...>``.
See the :manual:`cmake-generator-expressions(7)` manual for available
expressions.
-The ``$<COMPILE_LANGUAGE:...>`` generator expression is particularly
+The :genex:`$<COMPILE_LANGUAGE:...>` generator expression is particularly
useful for specifying a language-specific header to precompile for
only one language (e.g. ``CXX`` and not ``C``). In this case, header
file names that are not explicitly in double quotes or angle brackets
diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst
index 653b8d7c5..520614a17 100644
--- a/Help/command/target_sources.rst
+++ b/Help/command/target_sources.rst
@@ -12,27 +12,37 @@ Add sources to a target.
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
Specifies sources to use when building a target and/or its dependents.
-Relative source file paths are interpreted as being relative to the current
-source directory (i.e. :variable:`CMAKE_CURRENT_SOURCE_DIR`). The
-named ``<target>`` must have been created by a command such as
-:command:`add_executable` or :command:`add_library` and must not be an
+The named ``<target>`` must have been created by a command such as
+:command:`add_executable` or :command:`add_library` or
+:command:`add_custom_target` and must not be an
:ref:`ALIAS target <Alias Targets>`.
+.. versionchanged:: 3.13
+ Relative source file paths are interpreted as being relative to the current
+ source directory (i.e. :variable:`CMAKE_CURRENT_SOURCE_DIR`).
+ See policy :policy:`CMP0076`.
+
+.. versionadded:: 3.20
+ ``<target>`` can be a custom target.
+
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
specify the scope of the items following them. ``PRIVATE`` and ``PUBLIC``
items will populate the :prop_tgt:`SOURCES` property of
``<target>``, which are used when building the target itself.
``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_SOURCES` property of ``<target>``, which are used
-when building dependents. (:ref:`IMPORTED targets <Imported Targets>`
-only support ``INTERFACE`` items because they are not build targets.)
+when building dependents.
The following arguments specify sources. Repeated calls for the same
-``<target>`` append items in the order called.
+``<target>`` append items in the order called. The targets created by
+:command:`add_custom_target` can only have ``PRIVATE`` scope.
+
+.. versionadded:: 3.3
+ Allow exporting targets with :prop_tgt:`INTERFACE_SOURCES`.
+
+.. versionadded:: 3.11
+ Allow setting ``INTERFACE`` items on :ref:`IMPORTED targets <Imported Targets>`.
Arguments to ``target_sources`` 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.
-
-See also the :policy:`CMP0076` policy for older behavior related to the
-handling of relative source file paths.
diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst
index 323077af1..06da910dd 100644
--- a/Help/command/try_compile.rst
+++ b/Help/command/try_compile.rst
@@ -19,6 +19,10 @@ Try Compiling Whole Projects
Try building a project. The success or failure of the ``try_compile``,
i.e. ``TRUE`` or ``FALSE`` respectively, is returned in ``<resultVar>``.
+.. versionadded:: 3.14
+ The name of the ``<resultVar>`` is defined by the user. Previously, it had
+ a fixed name ``RESULT_VAR``.
+
In this form, ``<srcdir>`` should contain a complete CMake project with a
``CMakeLists.txt`` file and all sources. The ``<bindir>`` and ``<srcdir>``
will not be deleted after this command is run. Specify ``<targetName>`` to
@@ -47,6 +51,10 @@ Try building an executable or static library from one or more source files
variable). The success or failure of the ``try_compile``, i.e. ``TRUE`` or
``FALSE`` respectively, is returned in ``<resultVar>``.
+.. versionadded:: 3.14
+ The name of the ``<resultVar>`` is defined by the user. Previously, it had
+ a fixed name ``RESULT_VAR``.
+
In this form, one or more source files must be provided. If
:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is unset or is set to ``EXECUTABLE``,
the sources must include a definition for ``main`` and CMake will create a
@@ -94,6 +102,8 @@ The options are:
given to the ``CMAKE_FLAGS`` option will be ignored.
``LINK_OPTIONS <options>...``
+ .. versionadded:: 3.14
+
Specify link step options to pass to :command:`target_link_options` or to
set the :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property in the generated
project, depending on the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable.
@@ -102,17 +112,23 @@ The options are:
Store the output from the build process in the given variable.
``<LANG>_STANDARD <std>``
+ .. versionadded:: 3.8
+
Specify the :prop_tgt:`C_STANDARD`, :prop_tgt:`CXX_STANDARD`,
:prop_tgt:`OBJC_STANDARD`, :prop_tgt:`OBJCXX_STANDARD`,
or :prop_tgt:`CUDA_STANDARD` target property of the generated project.
``<LANG>_STANDARD_REQUIRED <bool>``
+ .. versionadded:: 3.8
+
Specify the :prop_tgt:`C_STANDARD_REQUIRED`,
:prop_tgt:`CXX_STANDARD_REQUIRED`, :prop_tgt:`OBJC_STANDARD_REQUIRED`,
:prop_tgt:`OBJCXX_STANDARD_REQUIRED`,or :prop_tgt:`CUDA_STANDARD_REQUIRED`
target property of the generated project.
``<LANG>_EXTENSIONS <bool>``
+ .. versionadded:: 3.8
+
Specify the :prop_tgt:`C_EXTENSIONS`, :prop_tgt:`CXX_EXTENSIONS`,
:prop_tgt:`OBJC_EXTENSIONS`, :prop_tgt:`OBJCXX_EXTENSIONS`,
or :prop_tgt:`CUDA_EXTENSIONS` target property of the generated project.
@@ -131,24 +147,26 @@ the try_compile call of interest, and then re-run cmake again with
Other Behavior Settings
^^^^^^^^^^^^^^^^^^^^^^^
-If set, the following variables are passed in to the generated
-try_compile CMakeLists.txt to initialize compile target properties with
-default values:
+.. versionadded:: 3.4
+ If set, the following variables are passed in to the generated
+ try_compile CMakeLists.txt to initialize compile target properties with
+ default values:
-* :variable:`CMAKE_CUDA_RUNTIME_LIBRARY`
-* :variable:`CMAKE_ENABLE_EXPORTS`
-* :variable:`CMAKE_LINK_SEARCH_START_STATIC`
-* :variable:`CMAKE_LINK_SEARCH_END_STATIC`
-* :variable:`CMAKE_MSVC_RUNTIME_LIBRARY`
-* :variable:`CMAKE_POSITION_INDEPENDENT_CODE`
+ * :variable:`CMAKE_CUDA_RUNTIME_LIBRARY`
+ * :variable:`CMAKE_ENABLE_EXPORTS`
+ * :variable:`CMAKE_LINK_SEARCH_START_STATIC`
+ * :variable:`CMAKE_LINK_SEARCH_END_STATIC`
+ * :variable:`CMAKE_MSVC_RUNTIME_LIBRARY`
+ * :variable:`CMAKE_POSITION_INDEPENDENT_CODE`
-If :policy:`CMP0056` is set to ``NEW``, then
-:variable:`CMAKE_EXE_LINKER_FLAGS` is passed in as well.
+ If :policy:`CMP0056` is set to ``NEW``, then
+ :variable:`CMAKE_EXE_LINKER_FLAGS` is passed in as well.
-If :policy:`CMP0083` is set to ``NEW``, then in order to obtain correct
-behavior at link time, the ``check_pie_supported()`` command from the
-:module:`CheckPIESupported` module must be called before using the
-:command:`try_compile` command.
+.. versionchanged:: 3.14
+ If :policy:`CMP0083` is set to ``NEW``, then in order to obtain correct
+ behavior at link time, the ``check_pie_supported()`` command from the
+ :module:`CheckPIESupported` module must be called before using the
+ :command:`try_compile` command.
The current settings of :policy:`CMP0065` and :policy:`CMP0083` are propagated
through to the generated test project.
@@ -156,37 +174,41 @@ through to the generated test project.
Set the :variable:`CMAKE_TRY_COMPILE_CONFIGURATION` variable to choose
a build configuration.
-Set the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to specify
-the type of target used for the source file signature.
-
-Set the :variable:`CMAKE_TRY_COMPILE_PLATFORM_VARIABLES` variable to specify
-variables that must be propagated into the test project. This variable is
-meant for use only in toolchain files and is only honored by the
-``try_compile()`` command for the source files form, not when given a whole
-project.
-
-If :policy:`CMP0067` is set to ``NEW``, or any of the ``<LANG>_STANDARD``,
-``<LANG>_STANDARD_REQUIRED``, or ``<LANG>_EXTENSIONS`` options are used,
-then the language standard variables are honored:
-
-* :variable:`CMAKE_C_STANDARD`
-* :variable:`CMAKE_C_STANDARD_REQUIRED`
-* :variable:`CMAKE_C_EXTENSIONS`
-* :variable:`CMAKE_CXX_STANDARD`
-* :variable:`CMAKE_CXX_STANDARD_REQUIRED`
-* :variable:`CMAKE_CXX_EXTENSIONS`
-* :variable:`CMAKE_OBJC_STANDARD`
-* :variable:`CMAKE_OBJC_STANDARD_REQUIRED`
-* :variable:`CMAKE_OBJC_EXTENSIONS`
-* :variable:`CMAKE_OBJCXX_STANDARD`
-* :variable:`CMAKE_OBJCXX_STANDARD_REQUIRED`
-* :variable:`CMAKE_OBJCXX_EXTENSIONS`
-* :variable:`CMAKE_CUDA_STANDARD`
-* :variable:`CMAKE_CUDA_STANDARD_REQUIRED`
-* :variable:`CMAKE_CUDA_EXTENSIONS`
-
-Their values are used to set the corresponding target properties in
-the generated project (unless overridden by an explicit option).
-
-For the :generator:`Green Hills MULTI` generator the GHS toolset and target
-system customization cache variables are also propagated into the test project.
+.. versionadded:: 3.6
+ Set the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to specify
+ the type of target used for the source file signature.
+
+.. versionadded:: 3.6
+ Set the :variable:`CMAKE_TRY_COMPILE_PLATFORM_VARIABLES` variable to specify
+ variables that must be propagated into the test project. This variable is
+ meant for use only in toolchain files and is only honored by the
+ ``try_compile()`` command for the source files form, not when given a whole
+ project.
+
+.. versionchanged:: 3.8
+ If :policy:`CMP0067` is set to ``NEW``, or any of the ``<LANG>_STANDARD``,
+ ``<LANG>_STANDARD_REQUIRED``, or ``<LANG>_EXTENSIONS`` options are used,
+ then the language standard variables are honored:
+
+ * :variable:`CMAKE_C_STANDARD`
+ * :variable:`CMAKE_C_STANDARD_REQUIRED`
+ * :variable:`CMAKE_C_EXTENSIONS`
+ * :variable:`CMAKE_CXX_STANDARD`
+ * :variable:`CMAKE_CXX_STANDARD_REQUIRED`
+ * :variable:`CMAKE_CXX_EXTENSIONS`
+ * :variable:`CMAKE_OBJC_STANDARD`
+ * :variable:`CMAKE_OBJC_STANDARD_REQUIRED`
+ * :variable:`CMAKE_OBJC_EXTENSIONS`
+ * :variable:`CMAKE_OBJCXX_STANDARD`
+ * :variable:`CMAKE_OBJCXX_STANDARD_REQUIRED`
+ * :variable:`CMAKE_OBJCXX_EXTENSIONS`
+ * :variable:`CMAKE_CUDA_STANDARD`
+ * :variable:`CMAKE_CUDA_STANDARD_REQUIRED`
+ * :variable:`CMAKE_CUDA_EXTENSIONS`
+
+ Their values are used to set the corresponding target properties in
+ the generated project (unless overridden by an explicit option).
+
+.. versionchanged:: 3.14
+ For the :generator:`Green Hills MULTI` generator the GHS toolset and target
+ system customization cache variables are also propagated into the test project.
diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst
index d401ebe92..404de985d 100644
--- a/Help/command/try_run.rst
+++ b/Help/command/try_run.rst
@@ -20,6 +20,7 @@ Try Compiling and Running Source Files
[COMPILE_OUTPUT_VARIABLE <var>]
[RUN_OUTPUT_VARIABLE <var>]
[OUTPUT_VARIABLE <var>]
+ [WORKING_DIRECTORY <var>]
[ARGS <args>...])
Try compiling a ``<srcfile>``. Returns ``TRUE`` or ``FALSE`` for success
@@ -29,6 +30,11 @@ executable was built, but failed to run, then ``<runResultVar>`` will be
set to ``FAILED_TO_RUN``. See the :command:`try_compile` command for
information on how the test project is constructed to build the source file.
+.. versionadded:: 3.14
+ The names of the result variables ``<runResultVar>`` and
+ ``<compileResultVar>`` are defined by the user. Previously, they had
+ fixed names ``RUN_RESULT_VAR`` and ``COMPILE_RESULT_VAR``.
+
The options are:
``CMAKE_FLAGS <flags>...``
@@ -46,6 +52,8 @@ The options are:
Report the compile step build output in a given variable.
``LINK_LIBRARIES <libs>...``
+ .. versionadded:: 3.2
+
Specify libraries to be linked in the generated project.
The list of libraries may refer to system libraries and to
:ref:`Imported Targets <Imported Targets>` from the calling project.
@@ -54,6 +62,8 @@ The options are:
given to the ``CMAKE_FLAGS`` option will be ignored.
``LINK_OPTIONS <options>...``
+ .. versionadded:: 3.14
+
Specify link step options to pass to :command:`target_link_options` in the
generated project.
@@ -65,6 +75,12 @@ The options are:
``RUN_OUTPUT_VARIABLE <var>``
Report the output from running the executable in a given variable.
+``WORKING_DIRECTORY <var>``
+ .. versionadded:: 3.20
+
+ Run the executable in the given directory. If no ``WORKING_DIRECTORY`` is
+ specified, the executable will run in ``<bindir>``.
+
Other Behavior Settings
^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,6 +90,10 @@ a build configuration.
Behavior when Cross Compiling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.3
+ Use ``CMAKE_CROSSCOMPILING_EMULATOR`` when running cross-compiled
+ binaries.
+
When cross compiling, the executable compiled in the first step
usually cannot be run on the build host. The ``try_run`` command checks
the :variable:`CMAKE_CROSSCOMPILING` variable to detect whether CMake is in
diff --git a/Help/cpack_gen/archive.rst b/Help/cpack_gen/archive.rst
index 3656aa2d5..b9418126f 100644
--- a/Help/cpack_gen/archive.rst
+++ b/Help/cpack_gen/archive.rst
@@ -12,6 +12,12 @@ any of the following formats:
- TZST (.tar.zst)
- ZIP (.zip)
+.. versionadded:: 3.1
+ ``7Z`` and ``TXZ`` formats support.
+
+.. versionadded:: 3.16
+ ``TZST`` format support.
+
When this generator is called from ``CPackSourceConfig.cmake`` (or through
the ``package_source`` target), then the generated archive will contain all
files in the project directory, except those specified in
@@ -46,6 +52,9 @@ Variables specific to CPack Archive generator
The default is ``<CPACK_PACKAGE_FILE_NAME>[-<component>]``, with spaces
replaced by '-'.
+ .. versionadded:: 3.9
+ Per-component ``CPACK_ARCHIVE_<component>_FILE_NAME`` variables.
+
.. variable:: CPACK_ARCHIVE_COMPONENT_INSTALL
Enable component packaging. If enabled (ON), then the archive generator
@@ -63,12 +72,16 @@ CPack generators which are essentially archives at their core. These include:
.. variable:: CPACK_ARCHIVE_THREADS
+ .. versionadded:: 3.18
+
The number of threads to use when performing the compression. If set to
``0``, the number of available cores on the machine will be used instead.
The default is ``1`` which limits compression to a single thread. Note that
not all compression modes support threading in all environments. Currently,
only the XZ compression may support it.
+ See also the :variable:`CPACK_THREADS` variable.
+
.. note::
Official CMake binaries available on ``cmake.org`` ship with a ``liblzma``
diff --git a/Help/cpack_gen/bundle.rst b/Help/cpack_gen/bundle.rst
index b16dbda03..5e335c07b 100644
--- a/Help/cpack_gen/bundle.rst
+++ b/Help/cpack_gen/bundle.rst
@@ -36,6 +36,8 @@ Bundle-specific parameters (``CPACK_BUNDLE_xxx``).
.. variable:: CPACK_BUNDLE_APPLE_CERT_APP
+ .. versionadded:: 3.2
+
The name of your Apple supplied code signing certificate for the application.
The name usually takes the form ``Developer ID Application: [Name]`` or
``3rd Party Mac Developer Application: [Name]``. If this variable is not set
@@ -43,23 +45,31 @@ Bundle-specific parameters (``CPACK_BUNDLE_xxx``).
.. variable:: CPACK_BUNDLE_APPLE_ENTITLEMENTS
+ .. versionadded:: 3.2
+
The name of the Property List (``.plist``) file that contains your Apple
entitlements for sandboxing your application. This file is required
for submission to the macOS App Store.
.. variable:: CPACK_BUNDLE_APPLE_CODESIGN_FILES
+ .. versionadded:: 3.2
+
A list of additional files that you wish to be signed. You do not need to
list the main application folder, or the main executable. You should
list any frameworks and plugins that are included in your app bundle.
.. variable:: CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER
+ .. versionadded:: 3.3
+
Additional parameter that will passed to ``codesign``.
Default value: ``--deep -f``
.. variable:: CPACK_COMMAND_CODESIGN
+ .. versionadded:: 3.2
+
Path to the ``codesign(1)`` command used to sign applications with an
Apple cert. This variable can be used to override the automatically
detected command (or specify its location if the auto-detection fails
diff --git a/Help/cpack_gen/cygwin.rst b/Help/cpack_gen/cygwin.rst
index c65653efb..c537a796a 100644
--- a/Help/cpack_gen/cygwin.rst
+++ b/Help/cpack_gen/cygwin.rst
@@ -6,7 +6,9 @@ Cygwin CPack generator (Cygwin).
Variables affecting the CPack Cygwin generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- - :variable:`CPACK_ARCHIVE_THREADS`
+- .. versionadded:: 3.18
+ :variable:`CPACK_ARCHIVE_THREADS`
+
Variables specific to CPack Cygwin generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst
index bf50c555d..03c4ea8db 100644
--- a/Help/cpack_gen/deb.rst
+++ b/Help/cpack_gen/deb.rst
@@ -54,11 +54,16 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_NAME` suffixed with -<COMPONENT>
for component-based installations.
+ .. versionadded:: 3.5
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_NAME`` variables.
+
See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
.. variable:: CPACK_DEBIAN_FILE_NAME
CPACK_DEBIAN_<COMPONENT>_FILE_NAME
+ .. versionadded:: 3.6
+
Package file name.
* Mandatory : YES
@@ -72,6 +77,9 @@ List of CPack DEB generator specific variables:
Alternatively provided package file name must end
with either ``.deb`` or ``.ipk`` suffix.
+ .. versionadded:: 3.10
+ ``.ipk`` suffix used by OPKG packaging system.
+
.. note::
Preferred setting of this variable is ``DEB-DEFAULT`` but for backward
@@ -86,6 +94,8 @@ List of CPack DEB generator specific variables:
.. variable:: CPACK_DEBIAN_PACKAGE_EPOCH
+ .. versionadded:: 3.10
+
The Debian package epoch
* Mandatory : No
@@ -116,6 +126,8 @@ List of CPack DEB generator specific variables:
.. variable:: CPACK_DEBIAN_PACKAGE_RELEASE
+ .. versionadded:: 3.6
+
The Debian package release - Debian revision number.
* Mandatory : No
@@ -136,6 +148,9 @@ List of CPack DEB generator specific variables:
* Default : Output of ``dpkg --print-architecture`` (or ``i386``
if ``dpkg`` is not found)
+ .. versionadded:: 3.6
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_ARCHITECTURE`` variables.
+
.. variable:: CPACK_DEBIAN_PACKAGE_DEPENDS
CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS
@@ -148,6 +163,10 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_DEPENDS` for component-based
installations.
+
+ .. versionadded:: 3.3
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS`` variables.
+
.. note::
If :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS` or
@@ -165,7 +184,9 @@ List of CPack DEB generator specific variables:
.. variable:: CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS
- Sets inter component dependencies if listed with
+ .. versionadded:: 3.6
+
+ Sets inter-component dependencies if listed with
:variable:`CPACK_COMPONENT_<compName>_DEPENDS` variables.
* Mandatory : NO
@@ -196,6 +217,15 @@ List of CPack DEB generator specific variables:
used if set. Otherwise, :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` will be added as the first
line of description as defined in `Debian Policy Manual`_.
+ .. versionadded:: 3.3
+ Per-component ``CPACK_COMPONENT_<compName>_DESCRIPTION`` variables.
+
+ .. versionadded:: 3.16
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_DESCRIPTION`` variables.
+
+ .. versionadded:: 3.16
+ The ``CPACK_PACKAGE_DESCRIPTION_FILE`` variable.
+
.. _Debian Policy Manual: https://www.debian.org/doc/debian-policy/ch-controlfields.html#description
.. variable:: CPACK_DEBIAN_PACKAGE_SECTION
@@ -206,10 +236,17 @@ List of CPack DEB generator specific variables:
* Mandatory : YES
* Default : "devel"
+ .. versionadded:: 3.5
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_SECTION`` variables.
+
See https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
.. variable:: CPACK_DEBIAN_ARCHIVE_TYPE
+ .. versionadded:: 3.7
+
+ .. deprecated:: 3.14
+
The archive format used for creating the Debian package.
* Mandatory : YES
@@ -228,6 +265,8 @@ List of CPack DEB generator specific variables:
.. variable:: CPACK_DEBIAN_COMPRESSION_TYPE
+ .. versionadded:: 3.1
+
The compression used for creating the Debian package.
* Mandatory : YES
@@ -249,6 +288,9 @@ List of CPack DEB generator specific variables:
* Mandatory : YES
* Default : "optional"
+ .. versionadded:: 3.5
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY`` varables.
+
See https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities
.. variable:: CPACK_DEBIAN_PACKAGE_HOMEPAGE
@@ -260,6 +302,9 @@ List of CPack DEB generator specific variables:
* Mandatory : NO
* Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
+ .. versionadded:: 3.12
+ The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable.
+
.. note::
The content of this field is a simple URL without any surrounding
@@ -284,6 +329,36 @@ List of CPack DEB generator specific variables:
may fail to find your own shared libs.
See https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
+ .. note::
+
+ You can also set :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS`
+ to an appropriate value if you use this feature, in order to please
+ ``dpkg-shlibdeps``. However, you should only do this for private
+ shared libraries that could not get resolved otherwise.
+
+ .. versionadded:: 3.3
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS`` variables.
+
+ .. versionadded:: 3.6
+ Correct handling of ``$ORIGIN`` in :variable:`CMAKE_INSTALL_RPATH`.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS
+
+ .. versionadded:: 3.20
+
+ May be set to a list of directories that will be given to ``dpkg-shlibdeps``
+ via its ``-l`` option. These will be searched by ``dpkg-shlibdeps`` in order
+ to find private shared library dependencies.
+
+ * Mandatory : NO
+ * Default :
+
+ .. note::
+
+ You should prefer to set :variable:`CMAKE_INSTALL_RPATH` to an appropriate
+ value if you use ``dpkg-shlibdeps``. The current option is really only
+ needed for private shared library dependencies.
+
.. variable:: CPACK_DEBIAN_PACKAGE_DEBUG
May be set when invoking cpack in order to trace debug information
@@ -308,6 +383,9 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_PREDEPENDS` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_PREDEPENDS`` variables.
+
See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_ENHANCES
@@ -325,6 +403,9 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_ENHANCES` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_ENHANCES`` variables.
+
See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_BREAKS
@@ -345,6 +426,9 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_BREAKS` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_BREAKS`` variables.
+
See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-breaks
.. variable:: CPACK_DEBIAN_PACKAGE_CONFLICTS
@@ -362,6 +446,9 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_CONFLICTS` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONFLICTS`` variables.
+
See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-conflicts
.. note::
@@ -386,6 +473,9 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_PROVIDES` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_PROVIDES`` variables.
+
See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-virtual
.. variable:: CPACK_DEBIAN_PACKAGE_REPLACES
@@ -402,6 +492,9 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_REPLACES` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_REPLACES`` variables.
+
See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_RECOMMENDS
@@ -418,6 +511,9 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_RECOMMENDS` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_RECOMMENDS`` variables.
+
See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_SUGGESTS
@@ -433,10 +529,15 @@ List of CPack DEB generator specific variables:
- :variable:`CPACK_DEBIAN_PACKAGE_SUGGESTS` for component-based
installations.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_SUGGESTS`` variables.
+
See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
.. variable:: CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS
+ .. versionadded:: 3.6
+
* Mandatory : NO
* Default : OFF
@@ -451,6 +552,8 @@ List of CPack DEB generator specific variables:
.. variable:: CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY
+ .. versionadded:: 3.6
+
Compatibility policy for auto-generated shlibs control file.
* Mandatory : NO
@@ -476,17 +579,14 @@ List of CPack DEB generator specific variables:
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
"${CMAKE_CURRENT_SOURCE_DIR}/prerm;${CMAKE_CURRENT_SOURCE_DIR}/postrm")
- .. note::
-
- The original permissions of the files will be used in the final
- package unless the variable
- :variable:`CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION` is set.
- In particular, the scripts should have the proper executable
- flag prior to the generation of the package.
+ .. versionadded:: 3.4
+ Per-component ``CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONTROL_EXTRA`` variables.
.. variable:: CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION
CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONTROL_STRICT_PERMISSION
+ .. versionadded:: 3.4
+
This variable indicates if the Debian policy on control files should be
strictly followed.
@@ -497,15 +597,22 @@ List of CPack DEB generator specific variables:
set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
+ This overrides the permissions on the original files, following the rules
+ set by Debian policy
+ https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
+
.. note::
- This overrides the permissions on the original files, following the rules
- set by Debian policy
- https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
+ The original permissions of the files will be used in the final
+ package unless this variable is set to ``TRUE``.
+ In particular, the scripts should have the proper executable
+ flag prior to the generation of the package.
.. variable:: CPACK_DEBIAN_PACKAGE_SOURCE
CPACK_DEBIAN_<COMPONENT>_PACKAGE_SOURCE
+ .. versionadded:: 3.5
+
Sets the ``Source`` field of the binary Debian package.
When the binary package name is not the same as the source package name
(in particular when several components/binaries are generated from one
@@ -529,6 +636,8 @@ List of CPack DEB generator specific variables:
Packaging of debug information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.13
+
Dbgsym packages contain debug symbols for debugging packaged binaries.
Dbgsym packaging has its own set of variables:
@@ -549,6 +658,8 @@ Dbgsym packaging has its own set of variables:
Building Debian packages on Windows
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.10
+
To communicate UNIX file permissions from the install stage
to the CPack DEB generator the "cmake_mode_t" NTFS
alternate data stream (ADT) is used.
@@ -559,6 +670,8 @@ permissions can be preserved.
Reproducible packages
^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.13
+
The environment variable ``SOURCE_DATE_EPOCH`` may be set to a UNIX
timestamp, defined as the number of seconds, excluding leap seconds,
since 01 Jan 1970 00:00:00 UTC. If set, the CPack DEB generator will
diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst
index cede0f255..4c662a6f8 100644
--- a/Help/cpack_gen/dmg.rst
+++ b/Help/cpack_gen/dmg.rst
@@ -30,6 +30,8 @@ on macOS:
.. variable:: CPACK_DMG_DS_STORE_SETUP_SCRIPT
+ .. versionadded:: 3.5
+
Path to a custom AppleScript file. This AppleScript is used to generate
a ``.DS_Store`` file which specifies the Finder window position/geometry and
layout (such as hidden toolbars, placement of the icons etc.).
@@ -47,11 +49,15 @@ on macOS:
.. variable:: CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK
+ .. versionadded:: 3.6
+
Default behaviour 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
+ .. versionadded:: 3.5
+
Directory where license and menu files for different languages are stored.
Setting this causes CPack to look for a ``<language>.menu.txt`` and
``<language>.license.txt`` or ``<language>.license.rtf`` file for every
@@ -61,8 +67,13 @@ on macOS:
``<language>.license.txt`` and ``<language>.license.rtf`` exist, the ``.txt``
file will be used.
+ .. versionadded:: 3.17
+ RTF support.
+
.. variable:: CPACK_DMG_SLA_LANGUAGES
+ .. versionadded:: 3.5
+
Languages for which a license agreement is provided when mounting the
generated DMG. A menu file consists of 9 lines of text. The first line is
is the name of the language itself, uppercase, in English (e.g. German).
@@ -85,6 +96,8 @@ on macOS:
.. variable:: CPACK_DMG_<component>_FILE_NAME
+ .. versionadded:: 3.17
+
File name when packaging ``<component>`` as its own DMG
(``CPACK_COMPONENTS_GROUPING`` set to IGNORE).
diff --git a/Help/cpack_gen/external.rst b/Help/cpack_gen/external.rst
index e54b356ac..4c083f085 100644
--- a/Help/cpack_gen/external.rst
+++ b/Help/cpack_gen/external.rst
@@ -1,6 +1,8 @@
CPack External Generator
------------------------
+.. versionadded:: 3.13
+
CPack provides many generators to create packages for a variety of platforms
and packaging systems. The intention is for CMake/CPack to be a complete
end-to-end solution for building and packaging a software project. However, it
@@ -284,6 +286,8 @@ Variables specific to CPack External generator
.. variable:: CPACK_EXTERNAL_BUILT_PACKAGES
+ .. versionadded:: 3.19
+
The ``CPACK_EXTERNAL_PACKAGE_SCRIPT`` script may set this list variable to the
full paths of generated package files. CPack will copy these files from the
staging directory back to the top build directory and possibly produce
diff --git a/Help/cpack_gen/freebsd.rst b/Help/cpack_gen/freebsd.rst
index 47a77847a..2c9356956 100644
--- a/Help/cpack_gen/freebsd.rst
+++ b/Help/cpack_gen/freebsd.rst
@@ -1,12 +1,15 @@
CPack FreeBSD Generator
-----------------------
+.. versionadded:: 3.10
+
The built in (binary) CPack FreeBSD (pkg) generator (Unix only)
Variables affecting the CPack FreeBSD (pkg) generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- - :variable:`CPACK_ARCHIVE_THREADS`
+- .. versionadded:: 3.18
+ :variable:`CPACK_ARCHIVE_THREADS`
Variables specific to CPack FreeBSD (pkg) generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,6 +89,9 @@ the RPM information (e.g. package license).
:variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
for Debian packaging, so we may as well re-use it).
+ .. versionadded:: 3.12
+ The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable.
+
.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE
The license, or licenses, which apply to this software package. This must
diff --git a/Help/cpack_gen/ifw.rst b/Help/cpack_gen/ifw.rst
index 5fbbfa27b..6817eac99 100644
--- a/Help/cpack_gen/ifw.rst
+++ b/Help/cpack_gen/ifw.rst
@@ -1,6 +1,8 @@
CPack IFW Generator
-------------------
+.. versionadded:: 3.1
+
Configure and run the Qt Installer Framework to generate a Qt installer.
.. only:: html
@@ -35,6 +37,8 @@ Debug
.. variable:: CPACK_IFW_VERBOSE
+ .. versionadded:: 3.3
+
Set to ``ON`` to enable addition debug output.
By default is ``OFF``.
@@ -71,41 +75,59 @@ Package
.. variable:: CPACK_IFW_PACKAGE_WATERMARK
+ .. versionadded:: 3.8
+
Filename for a watermark is used as QWizard::WatermarkPixmap.
.. variable:: CPACK_IFW_PACKAGE_BANNER
+ .. versionadded:: 3.8
+
Filename for a banner is used as QWizard::BannerPixmap.
.. variable:: CPACK_IFW_PACKAGE_BACKGROUND
+ .. versionadded:: 3.8
+
Filename for an image used as QWizard::BackgroundPixmap (only used by MacStyle).
.. variable:: CPACK_IFW_PACKAGE_WIZARD_STYLE
- Wizard style to be used ("Modern", "Mac", "Aero" or "Classic").
-
-.. variable:: CPACK_IFW_PACKAGE_STYLE_SHEET
+ .. versionadded:: 3.8
- Filename for a stylesheet.
+ Wizard style to be used ("Modern", "Mac", "Aero" or "Classic").
.. variable:: CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH
+ .. versionadded:: 3.8
+
Default width of the wizard in pixels. Setting a banner image will override this.
.. variable:: CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT
+ .. versionadded:: 3.8
+
Default height of the wizard in pixels. Setting a watermark image will override this.
+.. variable:: CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST
+
+ .. versionadded:: 3.20
+
+ Set to ``OFF`` if the widget listing installer pages on the left side of the wizard should not be shown.
+
+ It is ``ON`` by default, but will only have an effect if using QtIFW 4.0 or later.
+
.. variable:: CPACK_IFW_PACKAGE_TITLE_COLOR
+ .. versionadded:: 3.8
+
Color of the titles and subtitles (takes an HTML color code, such as "#88FF33").
-.. variable:: CPACK_IFW_PACKAGE_START_MENU_DIRECTORY
+.. variable:: CPACK_IFW_PACKAGE_STYLE_SHEET
- Name of the default program group for the product in the Windows Start menu.
+ .. versionadded:: 3.15
- By default used :variable:`CPACK_IFW_PACKAGE_NAME`.
+ Filename for a stylesheet.
.. variable:: CPACK_IFW_TARGET_DIRECTORY
@@ -123,6 +145,14 @@ Package
You can use predefined variables.
+.. variable:: CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR
+
+ .. versionadded:: 3.11
+
+ Set to ``OFF`` if the target directory should not be deleted when uninstalling.
+
+ Is ``ON`` by default
+
.. variable:: CPACK_IFW_PACKAGE_GROUP
The group, which will be used to configure the root package
@@ -132,43 +162,57 @@ Package
The root package name, which will be used if configuration group is not
specified
+.. variable:: CPACK_IFW_PACKAGE_START_MENU_DIRECTORY
+
+ .. versionadded:: 3.3
+
+ Name of the default program group for the product in the Windows Start menu.
+
+ By default used :variable:`CPACK_IFW_PACKAGE_NAME`.
+
.. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME
+ .. versionadded:: 3.3
+
Filename of the generated maintenance tool.
The platform-specific executable file extension is appended.
By default used QtIFW defaults (``maintenancetool``).
-.. variable:: CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR
-
- Set to ``OFF`` if the target directory should not be deleted when uninstalling.
-
- Is ``ON`` by default
-
.. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE
+ .. versionadded:: 3.3
+
Filename for the configuration of the generated maintenance tool.
By default used QtIFW defaults (``maintenancetool.ini``).
.. variable:: CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS
+ .. versionadded:: 3.3
+
Set to ``ON`` if the installation path can contain non-ASCII characters.
Is ``ON`` for QtIFW less 2.0 tools.
.. variable:: CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH
+ .. versionadded:: 3.3
+
Set to ``OFF`` if the installation path cannot contain space characters.
Is ``ON`` for QtIFW less 2.0 tools.
.. variable:: CPACK_IFW_PACKAGE_CONTROL_SCRIPT
+ .. versionadded:: 3.3
+
Filename for a custom installer control script.
.. variable:: CPACK_IFW_PACKAGE_RESOURCES
+ .. versionadded:: 3.7
+
List of additional resources ('.qrc' files) to include in the installer
binary.
@@ -177,6 +221,8 @@ Package
.. variable:: CPACK_IFW_PACKAGE_FILE_EXTENSION
+ .. versionadded:: 3.10
+
The target binary extension.
On Linux, the name of the target binary is automatically extended with
@@ -216,6 +262,8 @@ Components
.. variable:: CPACK_IFW_REPOSITORIES_DIRECTORIES
+ .. versionadded:: 3.10
+
Additional prepared repository dirs that will be used to resolve and
repack dependent components. This feature available only
since QtIFW 3.1.
@@ -225,6 +273,8 @@ QtIFW Tools
.. variable:: CPACK_IFW_FRAMEWORK_VERSION
+ .. versionadded:: 3.3
+
The version of used QtIFW tools.
The following variables provide the locations of the QtIFW
@@ -233,6 +283,8 @@ These variables are cached, and may be configured if needed.
.. variable:: CPACK_IFW_ARCHIVEGEN_EXECUTABLE
+ .. versionadded:: 3.19
+
The path to ``archivegen``.
.. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE
@@ -260,6 +312,8 @@ the path may be specified in either a CMake or an environment variable:
.. variable:: CPACK_IFW_ROOT
+ .. versionadded:: 3.9
+
An CMake variable which specifies the location of the QtIFW tool suite.
The variable will be cached in the ``CPackConfig.cmake`` file and used at
@@ -306,6 +360,8 @@ these files accessible from a download URL.
Internationalization
""""""""""""""""""""
+.. versionadded:: 3.9
+
Some variables and command arguments support internationalization via
CMake script. This is an optional feature.
diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst
index 0dd876eec..eaef8ae73 100644
--- a/Help/cpack_gen/nsis.rst
+++ b/Help/cpack_gen/nsis.rst
@@ -3,7 +3,8 @@ CPack NSIS Generator
CPack Nullsoft Scriptable Install System (NSIS) generator specific options.
-The NSIS generator requires NSIS 3.0 or newer.
+.. versionchanged:: 3.17
+ The NSIS generator requires NSIS 3.0 or newer.
Variables specific to CPack NSIS generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,10 +34,14 @@ on Windows Nullsoft Scriptable Install System.
.. variable:: CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP
+ .. versionadded:: 3.5
+
The filename of a bitmap to use as the NSIS ``MUI_WELCOMEFINISHPAGE_BITMAP``.
.. variable:: CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP
+ .. versionadded:: 3.5
+
The filename of a bitmap to use as the NSIS ``MUI_UNWELCOMEFINISHPAGE_BITMAP``.
.. variable:: CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS
@@ -99,6 +104,8 @@ on Windows Nullsoft Scriptable Install System.
.. variable:: CPACK_NSIS_<compName>_INSTALL_DIRECTORY
+ .. versionadded:: 3.7
+
Custom install directory for the specified component ``<compName>`` instead
of ``$INSTDIR``.
@@ -133,29 +140,56 @@ on Windows Nullsoft Scriptable Install System.
.. variable:: CPACK_NSIS_UNINSTALL_NAME
+ .. versionadded:: 3.17
+
Specify the name of the program to uninstall the version.
Default is ``Uninstall``.
.. variable:: CPACK_NSIS_WELCOME_TITLE
+ .. versionadded:: 3.17
+
The title to display on the top of the page for the welcome page.
.. variable:: CPACK_NSIS_WELCOME_TITLE_3LINES
+ .. versionadded:: 3.17
+
Display the title in the welcome page on 3 lines instead of 2.
.. variable:: CPACK_NSIS_FINISH_TITLE
+ .. versionadded:: 3.17
+
The title to display on the top of the page for the finish page.
.. variable:: CPACK_NSIS_FINISH_TITLE_3LINES
+ .. versionadded:: 3.17
+
Display the title in the finish page on 3 lines instead of 2.
.. variable:: CPACK_NSIS_MUI_HEADERIMAGE
+ .. versionadded:: 3.17
+
The image to display on the header of installers pages.
.. variable:: CPACK_NSIS_MANIFEST_DPI_AWARE
+ .. versionadded:: 3.18
+
If set, declares that the installer is DPI-aware.
+
+.. variable:: CPACK_NSIS_BRANDING_TEXT
+
+ .. versionadded:: 3.20
+
+ If set, updates the text at the bottom of the install window.
+ To set the string to blank, use a space (" ").
+
+.. variable:: CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION
+
+ .. versionadded:: 3.20
+
+ If set, trim down the size of the control to the size of the branding text string.
diff --git a/Help/cpack_gen/nuget.rst b/Help/cpack_gen/nuget.rst
index f8aa6266b..c980dd64c 100644
--- a/Help/cpack_gen/nuget.rst
+++ b/Help/cpack_gen/nuget.rst
@@ -1,9 +1,11 @@
CPack NuGet Generator
---------------------
+.. versionadded:: 3.12
+
When build a NuGet package there is no direct way to control an output
filename due a lack of the corresponding CLI option of NuGet, so there
-is no ``CPACK_NUGET_PACKAGE_FILENAME`` variable. To form the output filename
+is no ``CPACK_NUGET_PACKAGE_FILE_NAME`` variable. To form the output filename
NuGet uses the package name and the version according to its built-in rules.
Also, be aware that including a top level directory
@@ -35,7 +37,8 @@ List of CPack NuGet generator specific variables:
.. variable:: CPACK_NUGET_PACKAGE_NAME
CPACK_NUGET_<compName>_PACKAGE_NAME
- The NUGET package name.
+ The NUGET package name. ``CPACK_NUGET_PACKAGE_NAME`` is used as the
+ package ``id`` on nuget.org_
* Mandatory : YES
* Default : :variable:`CPACK_PACKAGE_NAME`
@@ -95,7 +98,7 @@ List of CPack NuGet generator specific variables:
.. variable:: CPACK_NUGET_PACKAGE_HOMEPAGE_URL
CPACK_NUGET_<compName>_PACKAGE_HOMEPAGE_URL
- A URL for the package's home page, often shown in UI displays as well
+ An URL for the package's home page, often shown in UI displays as well
as nuget.org_.
* Mandatory : NO
@@ -104,8 +107,45 @@ List of CPack NuGet generator specific variables:
.. variable:: CPACK_NUGET_PACKAGE_LICENSEURL
CPACK_NUGET_<compName>_PACKAGE_LICENSEURL
- A URL for the package's license, often shown in UI displays as well
- as nuget.org_.
+ .. deprecated:: 3.20
+ Use a local license file
+ (:variable:`CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME`)
+ or a `(SPDX) license identifier`_
+ (:variable:`CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION`) instead.
+
+ An URL for the package's license, often shown in UI displays as well
+ as on nuget.org_.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION
+ CPACK_NUGET_<compName>_PACKAGE_LICENSE_EXPRESSION
+
+ .. versionadded:: 3.20
+
+ A Software Package Data Exchange `(SPDX) license identifier`_ such as
+ ``MIT``, ``BSD-3-Clause``, or ``LGPL-3.0-or-later``. In the case of a
+ choice of licenses or more complex restrictions, compound license
+ expressions may be formed using boolean operators, for example
+ ``MIT OR BSD-3-Clause``. See the `SPDX specification`_ for guidance
+ on forming complex license expressions.
+
+ If ``CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME`` is specified,
+ ``CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION`` is ignored.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME
+ CPACK_NUGET_<compName>_PACKAGE_LICENSE_FILE_NAME
+
+ The package's license file in :file:`.txt` or :file:`.md` format.
+
+ If ``CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME`` is specified,
+ ``CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION`` is ignored.
+
+ .. versionadded:: 3.20
* Mandatory : NO
* Default : -
@@ -113,7 +153,21 @@ List of CPack NuGet generator specific variables:
.. variable:: CPACK_NUGET_PACKAGE_ICONURL
CPACK_NUGET_<compName>_PACKAGE_ICONURL
- A URL for a 64x64 image with transparency background to use as the
+ .. deprecated:: 3.20
+ Use a local icon file (:variable:`CPACK_NUGET_PACKAGE_ICON`) instead.
+
+ An URL for a 64x64 image with transparency background to use as the
+ icon for the package in UI display.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_ICON
+ CPACK_NUGET_<compName>_PACKAGE_ICON
+
+ .. versionadded:: 3.20
+
+ The filename of a 64x64 image with transparency background to use as the
icon for the package in UI display.
* Mandatory : NO
@@ -146,6 +200,16 @@ List of CPack NuGet generator specific variables:
* Mandatory : NO
* Default : -
+.. variable:: CPACK_NUGET_PACKAGE_LANGUAGE
+ CPACK_NUGET_<compName>_PACKAGE_LANGUAGE
+
+ .. versionadded:: 3.20
+
+ Locale specifier for the package, for example ``en_CA``.
+
+ * Mandatory : NO
+ * Default : -
+
.. variable:: CPACK_NUGET_PACKAGE_TAGS
CPACK_NUGET_<compName>_PACKAGE_TAGS
@@ -185,5 +249,7 @@ List of CPack NuGet generator specific variables:
.. _nuget.org: http://nuget.org
.. _version specification: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
+.. _(SPDX) license identifier: https://spdx.org/licenses/
+.. _SPDX specification: https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/
.. NuGet spec docs https://docs.microsoft.com/en-us/nuget/reference/nuspec
diff --git a/Help/cpack_gen/packagemaker.rst b/Help/cpack_gen/packagemaker.rst
index 357eb7316..256446dd4 100644
--- a/Help/cpack_gen/packagemaker.rst
+++ b/Help/cpack_gen/packagemaker.rst
@@ -27,6 +27,14 @@ macOS using PackageMaker:
don't mind missing extra features available in the installer shipping with
later versions of macOS.
+Background Image
+""""""""""""""""
+
+.. versionadded:: 3.17
+
+This group of variables controls the background image of the generated
+installer.
+
.. variable:: CPACK_PACKAGEMAKER_BACKGROUND
Adds a background to Distribution XML if specified. The value contains the
diff --git a/Help/cpack_gen/productbuild.rst b/Help/cpack_gen/productbuild.rst
index fd99e5a27..cf3041f30 100644
--- a/Help/cpack_gen/productbuild.rst
+++ b/Help/cpack_gen/productbuild.rst
@@ -1,6 +1,8 @@
CPack productbuild Generator
----------------------------
+.. versionadded:: 3.7
+
productbuild CPack generator (macOS).
Variables specific to CPack productbuild generator
@@ -18,11 +20,15 @@ macOS using ProductBuild:
.. variable:: CPACK_PRODUCTBUILD_IDENTITY_NAME
+ .. versionadded:: 3.8
+
Adds a digital signature to the resulting package.
.. variable:: CPACK_PRODUCTBUILD_KEYCHAIN_PATH
+ .. versionadded:: 3.8
+
Specify a specific keychain to search for the signing identity.
@@ -35,11 +41,15 @@ macOS using ProductBuild:
.. variable:: CPACK_PKGBUILD_IDENTITY_NAME
+ .. versionadded:: 3.8
+
Adds a digital signature to the resulting package.
.. variable:: CPACK_PKGBUILD_KEYCHAIN_PATH
+ .. versionadded:: 3.8
+
Specify a specific keychain to search for the signing identity.
@@ -60,12 +70,22 @@ macOS using ProductBuild:
.. variable:: CPACK_PRODUCTBUILD_RESOURCES_DIR
+ .. versionadded:: 3.9
+
If specified the productbuild generator copies files from this directory
(including subdirectories) to the ``Resources`` directory. This is done
before the :variable:`CPACK_RESOURCE_FILE_WELCOME`,
:variable:`CPACK_RESOURCE_FILE_README`, and
:variable:`CPACK_RESOURCE_FILE_LICENSE` files are copied.
+Background Image
+""""""""""""""""
+
+.. versionadded:: 3.17
+
+This group of variables controls the background image of the generated
+installer.
+
.. variable:: CPACK_PRODUCTBUILD_BACKGROUND
Adds a background to Distribution XML if specified. The value contains the
diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst
index ccb7ebd7b..5260a1d7c 100644
--- a/Help/cpack_gen/rpm.rst
+++ b/Help/cpack_gen/rpm.rst
@@ -20,7 +20,7 @@ a component GROUP name. Usually those variables correspond to RPM spec file
entities. One may find information about spec files here
http://www.rpm.org/wiki/Docs
-.. note::
+.. versionchanged:: 3.6
`<COMPONENT>` part of variables is preferred to be in upper case (e.g. if
component is named ``foo`` then use ``CPACK_RPM_FOO_XXXX`` variable name format)
@@ -59,6 +59,9 @@ List of CPack RPM generator specific variables:
* Mandatory : YES
* Default : :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+ .. versionadded:: 3.2
+ Per-component ``CPACK_RPM_<component>_PACKAGE_SUMMARY`` variables.
+
.. variable:: CPACK_RPM_PACKAGE_NAME
CPACK_RPM_<component>_PACKAGE_NAME
@@ -67,9 +70,14 @@ List of CPack RPM generator specific variables:
* Mandatory : YES
* Default : :variable:`CPACK_PACKAGE_NAME`
+ .. versionadded:: 3.5
+ Per-component ``CPACK_RPM_<component>_PACKAGE_NAME`` variables.
+
.. variable:: CPACK_RPM_FILE_NAME
CPACK_RPM_<component>_FILE_NAME
+ .. versionadded:: 3.6
+
Package file name.
* Mandatory : YES
@@ -93,6 +101,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_MAIN_COMPONENT
+ .. versionadded:: 3.8
+
Main component that is packaged without component suffix.
* Mandatory : NO
@@ -104,6 +114,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_PACKAGE_EPOCH
+ .. versionadded:: 3.10
+
The RPM package epoch
* Mandatory : No
@@ -129,6 +141,9 @@ List of CPack RPM generator specific variables:
This may be set to ``noarch`` if you know you are building a ``noarch`` package.
+ .. versionadded:: 3.3
+ Per-component ``CPACK_RPM_<component>_PACKAGE_ARCHITECTURE`` variables.
+
.. variable:: CPACK_RPM_PACKAGE_RELEASE
The RPM package release.
@@ -150,6 +165,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_PACKAGE_RELEASE_DIST
+ .. versionadded:: 3.6
+
The dist tag that is added RPM ``Release:`` field.
* Mandatory : NO
@@ -174,6 +191,9 @@ List of CPack RPM generator specific variables:
* Mandatory : YES
* Default : "unknown"
+ .. versionadded:: 3.5
+ Per-component ``CPACK_RPM_<component>_PACKAGE_GROUP`` variables.
+
.. variable:: CPACK_RPM_PACKAGE_VENDOR
The RPM package vendor.
@@ -189,6 +209,9 @@ List of CPack RPM generator specific variables:
* Mandatory : NO
* Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
+ .. versionadded:: 3.12
+ The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable.
+
.. variable:: CPACK_RPM_PACKAGE_DESCRIPTION
CPACK_RPM_<component>_PACKAGE_DESCRIPTION
@@ -199,6 +222,9 @@ List of CPack RPM generator specific variables:
based installers only) if set, :variable:`CPACK_PACKAGE_DESCRIPTION_FILE`
if set or "no package description available"
+ .. versionadded:: 3.2
+ Per-component ``CPACK_RPM_<component>_PACKAGE_DESCRIPTION`` variables.
+
.. variable:: CPACK_RPM_COMPRESSION_TYPE
RPM compression type.
@@ -302,6 +328,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_PACKAGE_REQUIRES_PRE
CPACK_RPM_<component>_PACKAGE_REQUIRES_PRE
+ .. versionadded:: 3.2
+
RPM spec requires(pre) field.
* Mandatory : NO
@@ -315,6 +343,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_PACKAGE_REQUIRES_POST
CPACK_RPM_<component>_PACKAGE_REQUIRES_POST
+ .. versionadded:: 3.2
+
RPM spec requires(post) field.
* Mandatory : NO
@@ -328,6 +358,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_PACKAGE_REQUIRES_POSTUN
CPACK_RPM_<component>_PACKAGE_REQUIRES_POSTUN
+ .. versionadded:: 3.2
+
RPM spec requires(postun) field.
* Mandatory : NO
@@ -342,6 +374,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_PACKAGE_REQUIRES_PREUN
CPACK_RPM_<component>_PACKAGE_REQUIRES_PREUN
+ .. versionadded:: 3.2
+
RPM spec requires(preun) field.
* Mandatory : NO
@@ -492,6 +526,9 @@ List of CPack RPM generator specific variables:
rpm -qp --scripts package.rpm
+ .. versionadded:: 3.18
+ The ``CPACK_RPM_PRE_TRANS_SCRIPT_FILE`` variable.
+
.. variable:: CPACK_RPM_POST_INSTALL_SCRIPT_FILE
CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE
CPACK_RPM_POST_TRANS_SCRIPT_FILE
@@ -513,6 +550,9 @@ List of CPack RPM generator specific variables:
rpm -qp --scripts package.rpm
+ .. versionadded:: 3.18
+ The ``CPACK_RPM_POST_TRANS_SCRIPT_FILE`` variable.
+
.. variable:: CPACK_RPM_USER_FILELIST
CPACK_RPM_<COMPONENT>_USER_FILELIST
@@ -521,13 +561,16 @@ List of CPack RPM generator specific variables:
May be used to explicitly specify ``%(<directive>)`` file line
in the spec file. Like ``%config(noreplace)`` or any other directive
- that be found in the ``%files`` section. You can have multiple directives
- per line, as in ``%attr(600,root,root) %config(noreplace)``. Since
+ that be found in the ``%files`` section. Since
the CPack RPM generator is generating the list of files (and directories) the
user specified files of the ``CPACK_RPM_<COMPONENT>_USER_FILELIST`` list will
be removed from the generated list. If referring to directories do
not add a trailing slash.
+ .. versionadded:: 3.8
+ You can have multiple directives per line, as in
+ ``%attr(600,root,root) %config(noreplace)``.
+
.. variable:: CPACK_RPM_CHANGELOG_FILE
RPM changelog file.
@@ -555,6 +598,9 @@ List of CPack RPM generator specific variables:
the default path. If you want to add some path to the default list then you
can use :variable:`CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION` variable.
+ .. versionadded:: 3.10
+ Added ``/usr/share/aclocal`` to the default list of excludes.
+
.. variable:: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
additional list of path to be excluded.
@@ -568,6 +614,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_RELOCATION_PATHS
+ .. versionadded:: 3.2
+
Packages relocation paths list.
* Mandatory : NO
@@ -591,6 +639,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
+ .. versionadded:: 3.2
+
Per component relocation path install prefix.
* Mandatory : NO
@@ -602,6 +652,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_NO_INSTALL_PREFIX_RELOCATION
CPACK_RPM_NO_<COMPONENT>_INSTALL_PREFIX_RELOCATION
+ .. versionadded:: 3.3
+
Removal of default install prefix from relocation paths list.
* Mandatory : NO
@@ -613,6 +665,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_ADDITIONAL_MAN_DIRS
+ .. versionadded:: 3.3
+
* Mandatory : NO
* Default : -
@@ -641,6 +695,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_DEFAULT_USER
CPACK_RPM_<compName>_DEFAULT_USER
+ .. versionadded:: 3.6
+
default user ownership of RPM content
* Mandatory : NO
@@ -652,6 +708,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_DEFAULT_GROUP
CPACK_RPM_<compName>_DEFAULT_GROUP
+ .. versionadded:: 3.6
+
default group ownership of RPM content
* Mandatory : NO
@@ -663,6 +721,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_DEFAULT_FILE_PERMISSIONS
CPACK_RPM_<compName>_DEFAULT_FILE_PERMISSIONS
+ .. versionadded:: 3.6
+
default permissions used for packaged files
* Mandatory : NO
@@ -686,6 +746,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_DEFAULT_DIR_PERMISSIONS
CPACK_RPM_<compName>_DEFAULT_DIR_PERMISSIONS
+ .. versionadded:: 3.6
+
default permissions used for packaged directories
* Mandatory : NO
@@ -697,6 +759,8 @@ List of CPack RPM generator specific variables:
.. variable:: CPACK_RPM_INSTALL_WITH_EXEC
+ .. versionadded:: 3.11
+
force execute permissions on programs and shared libraries
* Mandatory : NO
@@ -714,6 +778,8 @@ List of CPack RPM generator specific variables:
Packaging of Symbolic Links
^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.3
+
The CPack RPM generator supports packaging of symbolic links::
execute_process(COMMAND ${CMAKE_COMMAND}
@@ -731,8 +797,10 @@ those locations will be treated as if they were a part of the package
while determining if symlink should be either created or present in a
post install script - depending on relocation paths.
-Symbolic links that point to locations outside packaging path produce a
-warning and are treated as non relocatable permanent symbolic links.
+.. versionchanged:: 3.6
+ Symbolic links that point to locations outside packaging path produce a
+ warning and are treated as non relocatable permanent symbolic links.
+ Previous versions of CMake produced an error in this case.
Currently there are a few limitations though:
@@ -750,6 +818,8 @@ Currently there are a few limitations though:
Packaging of debug information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.7
+
Debuginfo packages contain debug symbols and sources for debugging packaged
binaries.
@@ -832,6 +902,8 @@ Debuginfo RPM packaging has its own set of variables:
.. variable:: CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE
+ .. versionadded:: 3.8
+
Create a single debuginfo package even if components packaging is set.
* Mandatory : NO
@@ -853,6 +925,8 @@ Debuginfo RPM packaging has its own set of variables:
.. variable:: CPACK_RPM_DEBUGINFO_FILE_NAME
CPACK_RPM_<component>_DEBUGINFO_FILE_NAME
+ .. versionadded:: 3.9
+
Debuginfo package file name.
* Mandatory : NO
@@ -877,6 +951,8 @@ Debuginfo RPM packaging has its own set of variables:
Packaging of sources (SRPM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.7
+
SRPM packaging is enabled by setting :variable:`CPACK_RPM_PACKAGE_SOURCES`
variable while usually using :variable:`CPACK_INSTALLED_DIRECTORIES` variable
to provide directory containing CMakeLists.txt and source files.
diff --git a/Help/cpack_gen/wix.rst b/Help/cpack_gen/wix.rst
index 5b880bac5..79f835e71 100644
--- a/Help/cpack_gen/wix.rst
+++ b/Help/cpack_gen/wix.rst
@@ -3,6 +3,9 @@ CPack WIX Generator
CPack WIX generator specific options
+.. versionadded:: 3.7
+ Support :variable:`CPACK_COMPONENT_<compName>_DISABLED` variable.
+
Variables specific to CPack WIX generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,9 +98,10 @@ Windows using WiX.
If this variable is not set, it will be initialized with CPACK_PACKAGE_NAME
- If this variable is set to ``.``, then application shortcuts will be
- created directly in the start menu and the uninstaller shortcut will be
- omitted.
+ .. versionadded:: 3.16
+ If this variable is set to ``.``, then application shortcuts will be
+ created directly in the start menu and the uninstaller shortcut will be
+ omitted.
.. variable:: CPACK_WIX_CULTURES
@@ -123,7 +127,10 @@ Windows using WiX.
.. variable:: CPACK_WIX_PATCH_FILE
Optional list of XML files with fragments to be inserted into
- generated WiX sources
+ generated WiX sources.
+
+ .. versionadded:: 3.5
+ Support listing multiple patch files.
This optional variable can be used to specify an XML file that the
WIX generator will use to inject fragments into its generated
@@ -152,10 +159,17 @@ Windows using WiX.
Currently fragments can be injected into most
Component, File, Directory and Feature elements.
- The following additional special Ids can be used:
+ .. versionadded:: 3.3
+ The following additional special Ids can be used:
+
+ * ``#PRODUCT`` for the ``<Product>`` element.
+ * ``#PRODUCTFEATURE`` for the root ``<Feature>`` element.
- * ``#PRODUCT`` for the ``<Product>`` element.
- * ``#PRODUCTFEATURE`` for the root ``<Feature>`` element.
+ .. versionadded:: 3.7
+ Support patching arbitrary ``<Feature>`` elements.
+
+ .. versionadded:: 3.9
+ Allow setting additional attributes.
The following example illustrates how this works.
@@ -227,6 +241,8 @@ Windows using WiX.
.. variable:: CPACK_WIX_PROPERTY_<PROPERTY>
+ .. versionadded:: 3.1
+
This variable can be used to provide a value for
the Windows Installer property ``<PROPERTY>``
@@ -243,16 +259,22 @@ Windows using WiX.
.. variable:: CPACK_WIX_ROOT_FEATURE_TITLE
+ .. versionadded:: 3.7
+
Sets the name of the root install feature in the WIX installer. Same as
CPACK_COMPONENT_<compName>_DISPLAY_NAME for components.
.. variable:: CPACK_WIX_ROOT_FEATURE_DESCRIPTION
+ .. versionadded:: 3.7
+
Sets the description of the root install feature in the WIX installer. Same as
CPACK_COMPONENT_<compName>_DESCRIPTION for components.
.. variable:: CPACK_WIX_SKIP_PROGRAM_FOLDER
+ .. versionadded:: 3.7
+
If this variable is set to true, the default install location
of the generated package will be CPACK_PACKAGE_INSTALL_DIRECTORY directly.
The install location will not be located relatively below
@@ -270,6 +292,8 @@ Windows using WiX.
.. variable:: CPACK_WIX_ROOT_FOLDER_ID
+ .. versionadded:: 3.9
+
This variable allows specification of a custom root folder ID.
The generator specific ``<64>`` token can be used for
folder IDs that come in 32-bit and 64-bit variants.
@@ -289,6 +313,8 @@ Windows using WiX.
.. variable:: CPACK_WIX_CUSTOM_XMLNS
+ .. versionadded:: 3.19
+
This variable provides a list of custom namespace declarations that are necessary
for using WiX extensions. Each declaration should be in the form name=url, where
name is the plain namespace without the usual xmlns: prefix and url is an unquoted
diff --git a/Help/dev/README.rst b/Help/dev/README.rst
index 84da4f1d3..9c3878b0c 100644
--- a/Help/dev/README.rst
+++ b/Help/dev/README.rst
@@ -37,9 +37,11 @@ CMake developer documentation is provided by the following documents:
* The `CMake Source Code Guide`_.
* The `CMake Documentation Guide`_.
+* The `CMake Experimental Features Guide`_.
.. _`CMake Source Code Guide`: source.rst
.. _`CMake Documentation Guide`: documentation.rst
+.. _`CMake Experimental Features Guide`: experimental.rst
Maintainer Documentation
========================
diff --git a/Help/dev/documentation.rst b/Help/dev/documentation.rst
index c302790aa..29fc88033 100644
--- a/Help/dev/documentation.rst
+++ b/Help/dev/documentation.rst
@@ -123,10 +123,23 @@ documentation:
``command``
A CMake language command.
+``cpack_gen``
+ A CPack package generator.
+ See the `cpack(1)`_ command-line tool's ``-G`` option.
+
+``envvar``
+ An environment variable.
+ See the `cmake-env-variables(7)`_ manual
+ and the `set()`_ command.
+
``generator``
A CMake native build system generator.
See the `cmake(1)`_ command-line tool's ``-G`` option.
+``genex``
+ A CMake generator expression.
+ See the `cmake-generator-expressions(7)`_ manual.
+
``manual``
A CMake manual page, like the `cmake(1)`_ manual.
@@ -160,10 +173,12 @@ which is expected to be of the form::
-------------
and to appear at or near the top of the ``.rst`` file before any other
-lines starting in a letter, digit, or ``<``. If no such title appears
+lines starting in a letter, digit, ``<``, or ``$``. If no such title appears
literally in the ``.rst`` file, the object name is the ``<file-name>``.
If a title does appear, it is expected that ``<file-name>`` is equal
-to ``<object-name>`` with any ``<`` and ``>`` characters removed.
+to ``<object-name>`` with any ``<`` and ``>`` characters removed,
+or in the case of a ``$<genex-name>`` or ``$<genex-name:...>``, the
+``genex-name``.
Second, the CMake Domain provides directives to define objects inside
other documents:
@@ -174,6 +189,14 @@ other documents:
This indented block documents <command-name>.
+ .. envvar:: <envvar-name>
+
+ This indented block documents <envvar-name>.
+
+ .. genex:: <genex-name>
+
+ This indented block documents <genex-name>.
+
.. variable:: <variable-name>
This indented block documents <variable-name>.
@@ -183,11 +206,14 @@ the first approach above.
.. _`Sphinx Domain`: http://sphinx-doc.org/domains.html
.. _`cmake(1)`: https://cmake.org/cmake/help/latest/manual/cmake.1.html
+.. _`cmake-env-variables(7)`: https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html
+.. _`cmake-generator-expressions(7)`: https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html
.. _`cmake-modules(7)`: https://cmake.org/cmake/help/latest/manual/cmake-modules.7.html
.. _`cmake-policies(7)`: https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html
.. _`cmake-properties(7)`: https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html
.. _`cmake-variables(7)`: https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html
.. _`cmake_policy()`: https://cmake.org/cmake/help/latest/command/cmake_policy.html
+.. _`cpack(1)`: https://cmake.org/cmake/help/latest/manual/cpack.1.html
.. _`include()`: https://cmake.org/cmake/help/latest/command/include.html
.. _`set()`: https://cmake.org/cmake/help/latest/command/set.html
.. _`set_property()`: https://cmake.org/cmake/help/latest/command/set_property.html
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst
new file mode 100644
index 000000000..d0191615a
--- /dev/null
+++ b/Help/dev/experimental.rst
@@ -0,0 +1,70 @@
+CMake Experimental Features Guide
+*********************************
+
+The following is a guide to CMake experimental features that are
+under development and not yet included in official documentation.
+See documentation on `CMake Development`_ for more information.
+
+.. _`CMake Development`: README.rst
+
+C++20 Module Dependencies
+=========================
+
+The Ninja generator has experimental infrastructure supporting C++20 module
+dependency scanning. This is similar to the Fortran modules support, but
+relies on external tools to scan C++20 translation units for module
+dependencies. The approach is described by Kitware's `D1483r1`_ paper.
+
+The ``CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP`` variable can be set to ``1``
+in order to activate this undocumented experimental infrastructure. This
+is **intended to make the functionality available to compiler writers** so
+they can use it to develop and test their dependency scanning tool.
+The ``CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE`` variable must also be set
+to tell CMake how to invoke the C++20 module dependency scanning tool.
+
+For example, add code like the following to a test project:
+
+.. code-block:: cmake
+
+ set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+ string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
+ "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> <SOURCE>"
+ " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
+ " ${flags_to_scan_deps} -fdep-file=<DYNDEP_FILE> -fdep-output=<OBJECT>"
+ )
+
+The tool specified by ``CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE`` is
+expected to process the translation unit, write preprocessor dependencies
+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.
+
+Compiler writers may try out their scanning functionality using
+the `cxx-modules-sandbox`_ test project, modified to set variables
+as above for their compiler.
+
+For compilers that generate module maps, tell CMake as follows:
+
+.. code-block:: cmake
+
+ set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc")
+ set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG
+ "${compiler_flags_for_module_map} -fmodule-mapper=<MODULE_MAP_FILE>")
+
+Currently, the only supported format is ``gcc``. The format is described in
+the GCC documentation, but the relevant section for the purposes of CMake is:
+
+ A mapping file consisting of space-separated module-name, filename
+ pairs, one per line. Only the mappings for the direct imports and any
+ module export name need be provided. If other mappings are provided,
+ they override those stored in any imported CMI files. A repository
+ root may be specified in the mapping file by using ``$root`` as the
+ module name in the first active line.
+
+ -- 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
+.. _`cxx-modules-sandbox`: https://github.com/mathstuf/cxx-modules-sandbox
diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst
index 75d685c61..664b7a409 100644
--- a/Help/dev/maint.rst
+++ b/Help/dev/maint.rst
@@ -357,3 +357,13 @@ policies added for that version. Commit with a message such as::
The files generatd by `install(EXPORT)` and `export()` commands
are known to work with policies as of CMake $prev, so enable them
in sufficiently new CMake versions.
+
+Update the ``cmake_minimum_required`` version range in CMake itself:
+
+* ``CMakeLists.txt``
+* ``Utilities/Doxygen/CMakeLists.txt``
+* ``Utilities/Sphinx/CMakeLists.txt``
+
+to end in the previous release. Commit with a message such as::
+
+ Configure CMake itself with policies through CMake $prev
diff --git a/Help/envvar/CUDAARCHS.rst b/Help/envvar/CUDAARCHS.rst
new file mode 100644
index 000000000..82369cd3b
--- /dev/null
+++ b/Help/envvar/CUDAARCHS.rst
@@ -0,0 +1,13 @@
+CUDAARCHS
+---------
+
+.. versionadded:: 3.20
+
+.. include:: ENV_VAR.txt
+
+Value used to initialize :variable:`CMAKE_CUDA_ARCHITECTURES` on the first
+configuration if it's not already defined. Subsequent runs will use the value
+stored in the cache.
+
+This is a semicolon-separated list of architectures as described in
+:prop_tgt:`CUDA_ARCHITECTURES`.
diff --git a/Help/envvar/CUDAHOSTCXX.rst b/Help/envvar/CUDAHOSTCXX.rst
index 19b15e9fc..963f9d113 100644
--- a/Help/envvar/CUDAHOSTCXX.rst
+++ b/Help/envvar/CUDAHOSTCXX.rst
@@ -13,5 +13,8 @@ configuration run (including the first), the environment variable will be
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. The :module:`FindCUDA`
-module will also use it to initialize its ``CUDA_HOST_COMPILER`` setting.
+enable ``CUDA`` as a first-class language.
+
+.. versionadded:: 3.13
+ The :module:`FindCUDA`
+ module will use this variable to initialize its ``CUDA_HOST_COMPILER`` setting.
diff --git a/Help/generator/CodeBlocks.rst b/Help/generator/CodeBlocks.rst
index d830542eb..85da71543 100644
--- a/Help/generator/CodeBlocks.rst
+++ b/Help/generator/CodeBlocks.rst
@@ -7,13 +7,15 @@ Project files for CodeBlocks will be created in the top directory and
in every subdirectory which features a ``CMakeLists.txt`` file containing
a :command:`project` call. Additionally a hierarchy of makefiles is generated
into the build tree.
-The :variable:`CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES` variable may
-be set to ``ON`` to exclude any files which are located outside of
-the project root directory.
The appropriate make program can build the
project through the default ``all`` target. An ``install`` target is
also provided.
+.. versionadded:: 3.10
+ The :variable:`CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES` variable may
+ be set to ``ON`` to exclude any files which are located outside of
+ the project root directory.
+
This "extra" generator may be specified as:
``CodeBlocks - MinGW Makefiles``
@@ -23,7 +25,8 @@ This "extra" generator may be specified as:
Generate with :generator:`NMake Makefiles`.
``CodeBlocks - NMake Makefiles JOM``
- Generate with :generator:`NMake Makefiles JOM`.
+ .. versionadded:: 3.8
+ Generate with :generator:`NMake Makefiles JOM`.
``CodeBlocks - Ninja``
Generate with :generator:`Ninja`.
diff --git a/Help/generator/CodeLite.rst b/Help/generator/CodeLite.rst
index 46fa5bef7..4f276df71 100644
--- a/Help/generator/CodeLite.rst
+++ b/Help/generator/CodeLite.rst
@@ -6,13 +6,15 @@ Generates CodeLite project files.
Project files for CodeLite will be created in the top directory and
in every subdirectory which features a CMakeLists.txt file containing
a :command:`project` call.
-The :variable:`CMAKE_CODELITE_USE_TARGETS` variable may be set to ``ON``
-to change the default behavior from projects to targets as the basis
-for project files.
The appropriate make program can build the
project through the default ``all`` target. An ``install`` target
is also provided.
+.. versionadded:: 3.7
+ The :variable:`CMAKE_CODELITE_USE_TARGETS` variable may be set to ``ON``
+ to change the default behavior from projects to targets as the basis
+ for project files.
+
This "extra" generator may be specified as:
``CodeLite - MinGW Makefiles``
diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst
index 2246699d9..5d2b1cd4d 100644
--- a/Help/generator/Green Hills MULTI.rst
+++ b/Help/generator/Green Hills MULTI.rst
@@ -3,22 +3,36 @@ Green Hills MULTI
.. versionadded:: 3.3
+.. versionadded:: 3.15
+ Linux support.
+
Generates Green Hills MULTI project files (experimental, work-in-progress).
-The buildsystem has predetermined build-configuration settings that can be controlled
-via the :variable:`CMAKE_BUILD_TYPE` variable.
+Customizations are available through the following cache variables:
+
+* ``GHS_CUSTOMIZATION``
+* ``GHS_GPJ_MACROS``
+
+.. versionadded:: 3.14
+ The buildsystem has predetermined build-configuration settings that can be controlled
+ via the :variable:`CMAKE_BUILD_TYPE` variable.
+
+Toolset and Platform Selection
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.13
Customizations that are used to pick toolset and target system:
-The ``-A <arch>`` can be supplied for setting the target architecture.
-``<arch>`` usually is one of ``arm``, ``ppc``, ``86``, etcetera.
-If the target architecture is not specified then
-the default architecture of ``arm`` will be used.
+* The ``-A <arch>`` can be supplied for setting the target architecture.
+ ``<arch>`` usually is one of ``arm``, ``ppc``, ``86``, etcetera.
+ If the target architecture is not specified then
+ the default architecture of ``arm`` will be used.
-The ``-T <toolset>`` option can be used to set the directory location of the toolset.
-Both absolute and relative paths are valid. Relative paths use ``GHS_TOOLSET_ROOT``
-as the root. If the toolset is not specified then the latest toolset found in
-``GHS_TOOLSET_ROOT`` will be used.
+* The ``-T <toolset>`` option can be used to set the directory location of the toolset.
+ Both absolute and relative paths are valid. Relative paths use ``GHS_TOOLSET_ROOT``
+ as the root. If the toolset is not specified then the latest toolset found in
+ ``GHS_TOOLSET_ROOT`` will be used.
Cache variables that are used for toolset and target system customization:
@@ -50,15 +64,18 @@ Cache variables that are used for toolset and target system customization:
a specific RTOS is to be used.
| ``GHS_OS_DIR_OPTION`` default value is ``-os_dir``.
+ .. versionadded:: 3.15
+ The ``GHS_OS_DIR_OPTION`` variable.
+
* ``GHS_BSP_NAME``
| Sets ``-bsp`` entry in project file.
| Defaults to ``sim<arch>`` for ``integrity`` platforms.
-Customizations are available through the following cache variables:
+Target Properties
+^^^^^^^^^^^^^^^^^
-* ``GHS_CUSTOMIZATION``
-* ``GHS_GPJ_MACROS``
+.. versionadded:: 3.14
The following properties are available:
diff --git a/Help/generator/NMake Makefiles JOM.rst b/Help/generator/NMake Makefiles JOM.rst
index 3a8744c1e..e0f4c90b3 100644
--- a/Help/generator/NMake Makefiles JOM.rst
+++ b/Help/generator/NMake Makefiles JOM.rst
@@ -2,3 +2,6 @@ NMake Makefiles JOM
-------------------
Generates JOM makefiles.
+
+.. versionadded:: 3.8
+ :generator:`CodeBlocks` generator can be used as an extra generator.
diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst
index 112db74f7..89011925f 100644
--- a/Help/generator/Ninja Multi-Config.rst
+++ b/Help/generator/Ninja Multi-Config.rst
@@ -86,3 +86,78 @@ used to generate ``generated.c``, which would be used to build the ``Debug``
configuration of ``generated``. This is useful for running a release-optimized
version of a generator utility while still building the debug version of the
targets built with the generated code.
+
+Custom Commands
+^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.20
+
+The ``Ninja Multi-Config`` generator adds extra capabilities to
+:command:`add_custom_command` and :command:`add_custom_target` through its
+cross-config mode. The ``COMMAND``, ``DEPENDS``, and ``WORKING_DIRECTORY``
+arguments can be evaluated in the context of either the "command config" (the
+"native" configuration of the ``build-<Config>.ninja`` file in use) or the
+"output config" (the configuration used to evaluate the ``OUTPUT`` and
+``BYPRODUCTS``).
+
+If either ``OUTPUT`` or ``BYPRODUCTS`` names a path that is common to
+more than one configuration (e.g. it does not use any generator expressions),
+all arguments are evaluated in the command config by default.
+If all ``OUTPUT`` and ``BYPRODUCTS`` paths are unique to each configuration
+(e.g. by using the ``$<CONFIG>`` generator expression), the first argument of
+``COMMAND`` is still evaluated in the command config by default, while all
+subsequent arguments, as well as the arguments to ``DEPENDS`` and
+``WORKING_DIRECTORY``, are evaluated in the output config. These defaults can
+be overridden with the ``$<OUTPUT_CONFIG:...>`` and ``$<COMMAND_CONFIG:...>``
+generator-expressions. Note that if a target is specified by its name in
+``DEPENDS``, or as the first argument of ``COMMAND``, it is always evaluated
+in the command config, even if it is wrapped in ``$<OUTPUT_CONFIG:...>``
+(because its plain name is not a generator expression).
+
+As an example, consider the following:
+
+.. code-block:: cmake
+
+ add_custom_command(
+ OUTPUT "$<CONFIG>.txt"
+ COMMAND generator "$<CONFIG>.txt" "$<OUTPUT_CONFIG:$<CONFIG>>" "$<COMMAND_CONFIG:$<CONFIG>>"
+ DEPENDS tgt1 "$<TARGET_FILE:tgt2>" "$<OUTPUT_CONFIG:$<TARGET_FILE:tgt3>>" "$<COMMAND_CONFIG:$<TARGET_FILE:tgt4>>"
+ )
+
+Assume that ``generator``, ``tgt1``, ``tgt2``, ``tgt3``, and ``tgt4`` are all
+executable targets, and assume that ``$<CONFIG>.txt`` is built in the ``Debug``
+output config using the ``Release`` command config. The ``Release`` build of
+the ``generator`` target is called with ``Debug.txt Debug Release`` as
+arguments. The command depends on the ``Release`` builds of ``tgt1`` and
+``tgt4``, and the ``Debug`` builds of ``tgt2`` and ``tgt3``.
+
+``PRE_BUILD``, ``PRE_LINK``, and ``POST_BUILD`` custom commands for targets
+only get run in their "native" configuration (the ``Release`` configuration in
+the ``build-Release.ninja`` file) unless they have no ``BYPRODUCTS`` or their
+``BYPRODUCTS`` are unique per config. Consider the following example:
+
+.. code-block:: cmake
+
+ add_executable(exe main.c)
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running no-byproduct command"
+ )
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running separate-byproduct command for $<CONFIG>"
+ BYPRODUCTS $<CONFIG>.txt
+ )
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running common-byproduct command for $<CONFIG>"
+ BYPRODUCTS exe.txt
+ )
+
+In this example, if you build ``exe:Debug`` in ``build-Release.ninja``, the
+first and second custom commands get run, since their byproducts are unique
+per-config, but the last custom command does not. However, if you build
+``exe:Release`` in ``build-Release.ninja``, all three custom commands get run.
diff --git a/Help/generator/Ninja.rst b/Help/generator/Ninja.rst
index 08ee81b52..f3ba2224b 100644
--- a/Help/generator/Ninja.rst
+++ b/Help/generator/Ninja.rst
@@ -11,32 +11,57 @@ For each subdirectory ``sub/dir`` of the project, additional targets
are generated:
``sub/dir/all``
- Depends on all targets required by the subdirectory.
+
+ .. versionadded:: 3.6
+
+ Depends on all targets required by the subdirectory.
``sub/dir/install``
- Runs the install step in the subdirectory, if any.
+
+ .. versionadded:: 3.7
+
+ Runs the install step in the subdirectory, if any.
``sub/dir/install/strip``
- Runs the install step in the subdirectory followed by a ``CMAKE_STRIP`` command,
- if any.
- The ``CMAKE_STRIP`` variable will contain the platform's ``strip`` utility, which
- removes symbols information from generated binaries.
+ .. versionadded:: 3.7
+ Runs the install step in the subdirectory followed by a ``CMAKE_STRIP`` command,
+ if any.
+
+ The ``CMAKE_STRIP`` variable will contain the platform's ``strip`` utility, which
+ removes symbols information from generated binaries.
``sub/dir/test``
- Runs the test step in the subdirectory, if any.
+
+ .. versionadded:: 3.7
+
+ Runs the test step in the subdirectory, if any.
``sub/dir/package``
- Runs the package step in the subdirectory, if any.
+
+ .. versionadded:: 3.7
+
+ Runs the package step in the subdirectory, if any.
Fortran Support
^^^^^^^^^^^^^^^
+.. versionadded:: 3.7
+
The ``Ninja`` generator conditionally supports Fortran when the ``ninja``
tool is at least version 1.10 (which has the required features).
+Swift Support
+^^^^^^^^^^^^^
+
+.. versionadded:: 3.15
+
+The Swift support is experimental, not considered stable, and may change
+in future releases of CMake.
+
See Also
^^^^^^^^
-The :generator:`Ninja Multi-Config` generator is similar to the ``Ninja``
-generator, but generates multiple configurations at once.
+.. versionadded:: 3.17
+ The :generator:`Ninja Multi-Config` generator is similar to the ``Ninja``
+ generator, but generates multiple configurations at once.
diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH.txt b/Help/generator/VS_TOOLSET_HOST_ARCH.txt
index 029363115..e36171999 100644
--- a/Help/generator/VS_TOOLSET_HOST_ARCH.txt
+++ b/Help/generator/VS_TOOLSET_HOST_ARCH.txt
@@ -1,7 +1,11 @@
-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.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.
diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst
index 4bf9a8f15..b4376d88b 100644
--- a/Help/generator/Visual Studio 10 2010.rst
+++ b/Help/generator/Visual Studio 10 2010.rst
@@ -17,13 +17,14 @@ Platform Selection
The default target platform name (architecture) is ``Win32``.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
-name (architecture). For example:
-
-* ``cmake -G "Visual Studio 10 2010" -A Win32``
-* ``cmake -G "Visual Studio 10 2010" -A x64``
-* ``cmake -G "Visual Studio 10 2010" -A Itanium``
+.. versionadded:: 3.1
+ The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+ via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+ name (architecture). For example:
+
+ * ``cmake -G "Visual Studio 10 2010" -A Win32``
+ * ``cmake -G "Visual Studio 10 2010" -A x64``
+ * ``cmake -G "Visual Studio 10 2010" -A Itanium``
For compatibility with CMake versions prior to 3.1, one may specify
a target platform name optionally at the end of the generator name.
diff --git a/Help/generator/Visual Studio 11 2012.rst b/Help/generator/Visual Studio 11 2012.rst
index 5d89a6e7c..932548bd2 100644
--- a/Help/generator/Visual Studio 11 2012.rst
+++ b/Help/generator/Visual Studio 11 2012.rst
@@ -17,15 +17,16 @@ Platform Selection
The default target platform name (architecture) is ``Win32``.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
-name (architecture). For example:
-
-* ``cmake -G "Visual Studio 11 2012" -A Win32``
-* ``cmake -G "Visual Studio 11 2012" -A x64``
-* ``cmake -G "Visual Studio 11 2012" -A ARM``
-* ``cmake -G "Visual Studio 11 2012" -A <WinCE-SDK>``
- (Specify a target platform matching a Windows CE SDK name.)
+.. versionadded:: 3.1
+ The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+ via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+ name (architecture). For example:
+
+ * ``cmake -G "Visual Studio 11 2012" -A Win32``
+ * ``cmake -G "Visual Studio 11 2012" -A x64``
+ * ``cmake -G "Visual Studio 11 2012" -A ARM``
+ * ``cmake -G "Visual Studio 11 2012" -A <WinCE-SDK>``
+ (Specify a target platform matching a Windows CE SDK name.)
For compatibility with CMake versions prior to 3.1, one may specify
a target platform name optionally at the end of the generator name.
diff --git a/Help/generator/Visual Studio 12 2013.rst b/Help/generator/Visual Studio 12 2013.rst
index fb8e021bc..b5fa1bf49 100644
--- a/Help/generator/Visual Studio 12 2013.rst
+++ b/Help/generator/Visual Studio 12 2013.rst
@@ -17,13 +17,14 @@ Platform Selection
The default target platform name (architecture) is ``Win32``.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
-name (architecture). For example:
-
-* ``cmake -G "Visual Studio 12 2013" -A Win32``
-* ``cmake -G "Visual Studio 12 2013" -A x64``
-* ``cmake -G "Visual Studio 12 2013" -A ARM``
+.. versionadded:: 3.1
+ The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+ via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+ name (architecture). For example:
+
+ * ``cmake -G "Visual Studio 12 2013" -A Win32``
+ * ``cmake -G "Visual Studio 12 2013" -A x64``
+ * ``cmake -G "Visual Studio 12 2013" -A ARM``
For compatibility with CMake versions prior to 3.1, one may specify
a target platform name optionally at the end of the generator name.
diff --git a/Help/generator/Visual Studio 14 2015.rst b/Help/generator/Visual Studio 14 2015.rst
index 5b319bbff..9c616414f 100644
--- a/Help/generator/Visual Studio 14 2015.rst
+++ b/Help/generator/Visual Studio 14 2015.rst
@@ -51,6 +51,8 @@ via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
Windows 10 SDK Maximum Version for VS 2015
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.19
+
Microsoft stated in a "Windows 10 October 2018 Update" blog post that Windows
10 SDK versions (15063, 16299, 17134, 17763) are not supported by VS 2015 and
are only supported by VS 2017 and later. Therefore by default CMake
diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst
index e7baaadb6..a002f2ff6 100644
--- a/Help/generator/Visual Studio 15 2017.rst
+++ b/Help/generator/Visual Studio 15 2017.rst
@@ -14,18 +14,20 @@ projects (JavaScript, Powershell, Python, etc.) are not supported.
Instance Selection
^^^^^^^^^^^^^^^^^^
-VS 2017 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 ``VS150COMNTOOLS`` 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.
+.. versionadded:: 3.9
+ VS 2017 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.
+
+.. versionadded:: 3.11
+ When CMake first chooses an instance, if the ``VS150COMNTOOLS`` 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
^^^^^^^^^^^^^^^^^^
diff --git a/Help/generator/Visual Studio 9 2008.rst b/Help/generator/Visual Studio 9 2008.rst
index a09d047ae..644f9363a 100644
--- a/Help/generator/Visual Studio 9 2008.rst
+++ b/Help/generator/Visual Studio 9 2008.rst
@@ -8,15 +8,16 @@ Platform Selection
The default target platform name (architecture) is ``Win32``.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
-via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
-name (architecture). For example:
-
-* ``cmake -G "Visual Studio 9 2008" -A Win32``
-* ``cmake -G "Visual Studio 9 2008" -A x64``
-* ``cmake -G "Visual Studio 9 2008" -A Itanium``
-* ``cmake -G "Visual Studio 9 2008" -A <WinCE-SDK>``
- (Specify a target platform matching a Windows CE SDK name.)
+.. versionadded:: 3.1
+ The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+ via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+ name (architecture). For example:
+
+ * ``cmake -G "Visual Studio 9 2008" -A Win32``
+ * ``cmake -G "Visual Studio 9 2008" -A x64``
+ * ``cmake -G "Visual Studio 9 2008" -A Itanium``
+ * ``cmake -G "Visual Studio 9 2008" -A <WinCE-SDK>``
+ (Specify a target platform matching a Windows CE SDK name.)
For compatibility with CMake versions prior to 3.1, one may specify
a target platform name optionally at the end of the generator name.
diff --git a/Help/generator/Xcode.rst b/Help/generator/Xcode.rst
index be03a2219..e4900a1e0 100644
--- a/Help/generator/Xcode.rst
+++ b/Help/generator/Xcode.rst
@@ -3,7 +3,8 @@ Xcode
Generate Xcode project files.
-This supports Xcode 5.0 and above.
+.. versionchanged:: 3.15
+ This generator supports Xcode 5.0 and above.
.. _`Xcode Build System Selection`:
@@ -14,7 +15,8 @@ By default Xcode is allowed to select its own default toolchain.
The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
-This generator supports toolset specification using one of these forms:
+.. versionadded:: 3.19
+ This generator supports toolset specification using one of these forms:
* ``toolset``
* ``toolset[,key=value]*``
@@ -33,3 +35,12 @@ Supported pairs are:
For example, to select the original build system under Xcode 12,
run :manual:`cmake(1)` with the option ``-T buildsystem=1``.
+
+Swift Support
+^^^^^^^^^^^^^
+
+.. versionadded:: 3.4
+
+When using the :generator:`Xcode` generator with Xcode 6.1 or higher,
+one may enable the ``Swift`` language with the :command:`enable_language`
+command or the :command:`project`.
diff --git a/Help/guide/ide-integration/index.rst b/Help/guide/ide-integration/index.rst
index 8ea31a003..addf93215 100644
--- a/Help/guide/ide-integration/index.rst
+++ b/Help/guide/ide-integration/index.rst
@@ -82,8 +82,8 @@ as the include directories, compile definitions, etc. used to build the
artifacts. Such information can be obtained by using the
:manual:`File API <cmake-file-api(7)>`. The manual page for the File API
contains more information about the API and how to invoke it.
-:manual:`Server mode <cmake-server(7)>` is deprecated and should not be
-used on CMake 3.14 or later.
+:manual:`Server mode <cmake-server(7)>` was removed as of CMake 3.20 and
+should not be used on CMake 3.14 or later.
IDEs should avoid creating more build trees than necessary, and only create
multiple build trees if the user wishes to switch to a different compiler,
diff --git a/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt
index 13c82dd10..9a9e40ee2 100644
--- a/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt
@@ -31,7 +31,7 @@ install(FILES MathFunctions.h DESTINATION include)
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
NAMESPACE MathFunctions::
- DESTINATION lib/cmake
+ DESTINATION lib/cmake/MathFunctions
)
# include CMakePackageConfigHelpers macro
@@ -58,14 +58,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
+ INSTALL_DESTINATION lib/cmake/MathFunctions
)
# install config files
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
- DESTINATION lib/cmake
+ DESTINATION lib/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 e3cf711f7..17ad95210 100644
--- a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt
@@ -26,5 +26,5 @@ install(FILES Addition.h DESTINATION include)
install(EXPORT AdditionTargets
FILE MathFunctionsAdditionTargets.cmake
NAMESPACE MathFunctions::
- DESTINATION lib/cmake
+ DESTINATION lib/cmake/MathFunctions
)
diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt
index 4e3496dcc..fd95e28df 100644
--- a/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt
@@ -24,7 +24,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
+ INSTALL_DESTINATION lib/cmake/MathFunctions
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
@@ -32,5 +32,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
+ DESTINATION lib/cmake/MathFunctions
)
diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt
index ffa1e3def..be5ae65d1 100644
--- a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt
+++ b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt
@@ -26,5 +26,5 @@ install(FILES SquareRoot.h DESTINATION include)
install(EXPORT SquareRootTargets
FILE MathFunctionsSquareRootTargets.cmake
NAMESPACE MathFunctions::
- DESTINATION lib/cmake
+ DESTINATION lib/cmake/MathFunctions
)
diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst
index 4b09e53a9..94753d5dc 100644
--- a/Help/guide/tutorial/index.rst
+++ b/Help/guide/tutorial/index.rst
@@ -176,7 +176,7 @@ directory:
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 ``mqsqrt.h`` header file can be found. The
+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
@@ -414,27 +414,23 @@ 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 the top-level
-``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.
-
-We're going to use the new defines in ``TutorialConfig.h.in``, so be sure to
-set them before that file is configured.
+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
-Now let's add these defines to ``TutorialConfig.h.in`` so that we can use them
-from ``mysqrt.cxx``:
-
-.. code-block:: console
+If available, use :command:`target_compile_definitions` to specify
+``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
- // does the platform provide exp and log functions?
- #cmakedefine HAVE_LOG
- #cmakedefine HAVE_EXP
+.. 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
@@ -456,51 +452,8 @@ 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.
-You will notice that we're not using ``log`` and ``exp``, even if we think they
-should be available. We should realize quickly that we have forgotten to
-include ``TutorialConfig.h`` in ``mysqrt.cxx``.
-
-We will also need to update ``MathFunctions/CMakeLists.txt`` so ``mysqrt.cxx``
-knows where this file is located:
-
-.. code-block:: cmake
-
- target_include_directories(MathFunctions
- INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
- PRIVATE ${CMAKE_BINARY_DIR}
- )
-
-After making this update, go ahead and build the project again and run the
-built Tutorial executable. If ``log`` and ``exp`` are still not being used,
-open the generated ``TutorialConfig.h`` file from the build directory. Maybe
-they aren't available on the current system?
-
Which function gives better results now, sqrt or mysqrt?
-Specify Compile Definition
---------------------------
-
-Is there a better place for us to save the ``HAVE_LOG`` and ``HAVE_EXP`` values
-other than in ``TutorialConfig.h``? Let's try to use
-:command:`target_compile_definitions`.
-
-First, remove the defines from ``TutorialConfig.h.in``. We no longer need to
-include ``TutorialConfig.h`` from ``mysqrt.cxx`` or the extra include in
-``MathFunctions/CMakeLists.txt``.
-
-Next, we can move the check for ``HAVE_LOG`` and ``HAVE_EXP`` to
-``MathFunctions/CMakeLists.txt`` and then specify those values as ``PRIVATE``
-compile definitions.
-
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
- :language: cmake
- :start-after: # does this system provide the log and exp functions?
- :end-before: # install rules
-
-After making these updates, go ahead and build the project again. Run the
-built Tutorial executable and verify that the results are same as earlier in
-this step.
-
Adding a Custom Command and Generated File (Step 6)
===================================================
diff --git a/Help/guide/user-interaction/index.rst b/Help/guide/user-interaction/index.rst
index 9e9f2a51f..ba8196bda 100644
--- a/Help/guide/user-interaction/index.rst
+++ b/Help/guide/user-interaction/index.rst
@@ -228,7 +228,7 @@ The Visual Studio toolset can be specified with the
.. code-block:: console
$ # Build with the clang-cl toolset
- $ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T LLVM
+ $ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T ClangCL
$ # Build targeting Windows XP
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp
diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst
index 0aa4f7517..036fa8fe5 100644
--- a/Help/manual/cmake-commands.7.rst
+++ b/Help/manual/cmake-commands.7.rst
@@ -20,6 +20,7 @@ These commands are always available.
/command/cmake_language
/command/cmake_minimum_required
/command/cmake_parse_arguments
+ /command/cmake_path
/command/cmake_policy
/command/configure_file
/command/continue
diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst
index 690d293ac..0d15ddfc3 100644
--- a/Help/manual/cmake-compile-features.7.rst
+++ b/Help/manual/cmake-compile-features.7.rst
@@ -89,6 +89,8 @@ Feature requirements are evaluated transitively by consuming the link
implementation. See :manual:`cmake-buildsystem(7)` for more on
transitive behavior of build properties and usage requirements.
+.. _`Requiring Language Standards`:
+
Requiring Language Standards
----------------------------
@@ -358,6 +360,7 @@ versions specified for each:
* ``Cray``: Cray Compiler Environment version 8.1+.
* ``PGI``: PGI version 12.10+.
+* ``NVHPC``: NVIDIA HPC compilers version 11.0+.
* ``TI``: Texas Instruments compiler.
* ``XL``: IBM XL version 10.1+.
@@ -373,4 +376,5 @@ their associated meta-features (e.g. ``cuda_std_11``) available from the
following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
versions specified for each:
+* ``Clang``: Clang compiler 5.0+.
* ``NVIDIA``: NVIDIA nvcc compiler 7.5+.
diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst
index 85ed935e6..af9a8ab0d 100644
--- a/Help/manual/cmake-developer.7.rst
+++ b/Help/manual/cmake-developer.7.rst
@@ -23,15 +23,14 @@ in turn link to developer guides for CMake itself.
Find Modules
============
-A "find module" is a ``Find<PackageName>.cmake`` file to be loaded
-by the :command:`find_package` command when invoked for ``<PackageName>``.
+A "find module" is a ``Find<PackageName>.cmake`` file to be loaded by the
+:command:`find_package` command when invoked for ``<PackageName>``.
-The primary task of a find module is to determine whether a package
-exists on the system, set the ``<PackageName>_FOUND`` variable to reflect
-this and provide any variables, macros and imported targets required to
-use the package. A find module is useful in cases where an upstream
-library does not provide a
-:ref:`config file package <Config File Packages>`.
+The primary task of a find module is to determine whether a package is
+available, set the ``<PackageName>_FOUND`` variable to reflect this and
+provide any variables, macros and imported targets required to use the
+package. A find module is useful in cases where an upstream library does
+not provide a :ref:`config file package <Config File Packages>`.
The traditional approach is to use variables for everything, including
libraries and executables: see the `Standard Variable Names`_ section
@@ -91,55 +90,92 @@ Standard Variable Names
For a ``FindXxx.cmake`` module that takes the approach of setting
variables (either instead of or in addition to creating imported
targets), the following variable names should be used to keep things
-consistent between find modules. Note that all variables start with
-``Xxx_`` to make sure they do not interfere with other find modules; the
-same consideration applies to macros, functions and imported targets.
+consistent between Find modules. Note that all variables start with
+``Xxx_``, which (unless otherwise noted) must match exactly the name
+of the ``FindXxx.cmake`` file, including upper/lowercase.
+This prefix on the variable names ensures that they do not conflict with
+variables of other Find modules. The same pattern should also be followed
+for any macros, functions and imported targets defined by the Find module.
``Xxx_INCLUDE_DIRS``
The final set of include directories listed in one variable for use by
- client code. This should not be a cache entry.
+ client code. This should not be a cache entry (note that this also means
+ this variable should not be used as the result variable of a
+ :command:`find_path` command - see ``Xxx_INCLUDE_DIR`` below for that).
``Xxx_LIBRARIES``
- The libraries to link against to use Xxx. These should include full
- paths. This should not be a cache entry.
+ The libraries to use with the module. These may be CMake targets, full
+ absolute paths to a library binary or the name of a library that the
+ linker must find in its search path. This should not be a cache entry
+ (note that this also means this variable should not be used as the
+ result variable of a :command:`find_library` command - see
+ ``Xxx_LIBRARY`` below for that).
``Xxx_DEFINITIONS``
- Definitions to use when compiling code that uses Xxx. This really
- shouldn't include options such as ``-DHAS_JPEG`` that a client
+ The compile definitions to use when compiling code that uses the module.
+ This really shouldn't include options such as ``-DHAS_JPEG`` that a client
source-code file uses to decide whether to ``#include <jpeg.h>``
``Xxx_EXECUTABLE``
- Where to find the Xxx tool.
-
-``Xxx_Yyy_EXECUTABLE``
- Where to find the Yyy tool that comes with Xxx.
+ The full absolute path to an executable. In this case, ``Xxx`` might not
+ be the name of the module, it might be the name of the tool (usually
+ converted to all uppercase), assuming that tool has such a well-known name
+ that it is unlikely that another tool with the same name exists. It would
+ be appropriate to use this as the result variable of a
+ :command:`find_program` command.
+
+``Xxx_YYY_EXECUTABLE``
+ Similar to ``Xxx_EXECUTABLE`` except here the ``Xxx`` is always the module
+ name and ``YYY`` is the tool name (again, usually fully uppercase).
+ Prefer this form if the tool name is not very widely known or has the
+ potential to clash with another tool. For greater consistency, also
+ prefer this form if the module provides more than one executable.
``Xxx_LIBRARY_DIRS``
Optionally, the final set of library directories listed in one
- variable for use by client code. This should not be a cache entry.
+ variable for use by client code. This should not be a cache entry.
``Xxx_ROOT_DIR``
- Where to find the base directory of Xxx.
-
-``Xxx_VERSION_Yy``
- Expect Version Yy if true. Make sure at most one of these is ever true.
-
-``Xxx_WRAP_Yy``
- If False, do not try to use the relevant CMake wrapping command.
+ Where to find the base directory of the module.
+
+``Xxx_VERSION_VV``
+ Variables of this form specify whether the ``Xxx`` module being provided
+ is version ``VV`` of the module. There should not be more than one
+ variable of this form set to true for a given module. For example, a
+ module ``Barry`` might have evolved over many years and gone through a
+ number of different major versions. Version 3 of the ``Barry`` module
+ might set the variable ``Barry_VERSION_3`` to true, whereas an older
+ version of the module might set ``Barry_VERSION_2`` to true instead.
+ It would be an error for both ``Barry_VERSION_3`` and ``Barry_VERSION_2``
+ to both be set to true.
+
+``Xxx_WRAP_YY``
+ When a variable of this form is set to false, it indicates that the
+ relevant wrapping command should not be used. The wrapping command
+ depends on the module, it may be implied by the module name or it might
+ be specified by the ``YY`` part of the variable.
``Xxx_Yy_FOUND``
- If False, optional Yy part of Xxx system is not available.
+ For variables of this form, ``Yy`` is the name of a component for the
+ module. It should match exactly one of the valid component names that
+ may be passed to the :command:`find_package` command for the module.
+ If a variable of this form is set to false, it means that the ``Yy``
+ component of module ``Xxx`` was not found or is not available.
+ Variables of this form would typically be used for optional components
+ so that the caller can check whether an optional component is available.
``Xxx_FOUND``
- Set to false, or undefined, if we haven't found, or don't want to use
- Xxx.
+ When the :command:`find_package` command returns to the caller, this
+ variable will be set to true if the module was deemed to have been found
+ successfully.
``Xxx_NOT_FOUND_MESSAGE``
Should be set by config-files in the case that it has set
``Xxx_FOUND`` to FALSE. The contained message will be printed by the
:command:`find_package` command and by
- ``find_package_handle_standard_args()`` to inform the user about the
- problem.
+ :command:`find_package_handle_standard_args` to inform the user about the
+ problem. Use this instead of calling :command:`message` directly to
+ report a reason for failing to find the module or package.
``Xxx_RUNTIME_LIBRARY_DIRS``
Optionally, the runtime library search path for use when running an
@@ -160,23 +196,36 @@ same consideration applies to macros, functions and imported targets.
``Xxx_VERSION_PATCH``
The patch version of the package found, if any.
-The following names should not usually be used in CMakeLists.txt files, but
-are typically cache variables for users to edit and control the
-behaviour of find modules (like entering the path to a library manually)
+The following names should not usually be used in ``CMakeLists.txt`` files.
+They are intended for use by Find modules to specify and cache the locations
+of specific files or directories. Users are typically able to set and edit
+these variables to control the behavior of Find modules (like entering the
+path to a library manually):
``Xxx_LIBRARY``
- The path of the Xxx library (as used with :command:`find_library`, for
- example).
+ The path of the library. Use this form only when the module provides a
+ single library. It is appropriate to use this as the result variable
+ in a :command:`find_library` command.
``Xxx_Yy_LIBRARY``
- The path of the Yy library that is part of the Xxx system. It may or
- may not be required to use Xxx.
+ The path of library ``Yy`` provided by the module ``Xxx``. Use this form
+ when the module provides more than one library or where other modules may
+ also provide a library of the same name. It is also appropriate to use
+ this form as the result variable in a :command:`find_library` command.
``Xxx_INCLUDE_DIR``
- Where to find headers for using the Xxx library.
+ When the module provides only a single library, this variable can be used
+ to specify where to find headers for using the library (or more accurately,
+ the path that consumers of the library should add to their header search
+ path). It would be appropriate to use this as the result variable in a
+ :command:`find_path` command.
``Xxx_Yy_INCLUDE_DIR``
- Where to find headers for using the Yy library of the Xxx system.
+ If the module provides more than one library or where other modules may
+ also provide a library of the same name, this form is recommended for
+ specifying where to find headers for using library ``Yy`` provided by
+ the module. Again, it would be appropriate to use this as the result
+ variable in a :command:`find_path` command.
To prevent users being overwhelmed with settings to configure, try to
keep as many options as possible out of the cache, leaving at least one
@@ -185,7 +234,8 @@ not-found library (e.g. ``Xxx_ROOT_DIR``). For the same reason, mark
most cache options as advanced. For packages which provide both debug
and release binaries, it is common to create cache variables with a
``_LIBRARY_<CONFIG>`` suffix, such as ``Foo_LIBRARY_RELEASE`` and
-``Foo_LIBRARY_DEBUG``.
+``Foo_LIBRARY_DEBUG``. The :module:`SelectLibraryConfigurations` module
+can be helpful for such cases.
While these are the standard variable names, you should provide
backwards compatibility for any old names that were actually in use.
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index d9cfa7ae8..bc1fa1d85 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -57,6 +57,7 @@ Environment Variables for Languages
/envvar/CC
/envvar/CFLAGS
/envvar/CSFLAGS
+ /envvar/CUDAARCHS
/envvar/CUDACXX
/envvar/CUDAFLAGS
/envvar/CUDAHOSTCXX
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst
index 6876e1c81..89739b7d5 100644
--- a/Help/manual/cmake-file-api.7.rst
+++ b/Help/manual/cmake-file-api.7.rst
@@ -1154,3 +1154,160 @@ The members specific to ``cmakeFiles`` objects are:
``isCMake``
Optional member that is present with boolean value ``true``
if the path specifies a file in the CMake installation.
+
+Object Kind "toolchains"
+------------------------
+
+The ``toolchains`` object kind lists properties of the toolchains used during
+the build. These include the language, compiler path, ID, and version.
+
+There is only one ``toolchains`` object major version, version 1.
+
+"toolchains" version 1
+^^^^^^^^^^^^^^^^^^^^^^
+
+``toolchains`` object version 1 is a JSON object:
+
+.. code-block:: json
+
+ {
+ "kind": "toolchains",
+ "version": { "major": 1, "minor": 0 },
+ "toolchains": [
+ {
+ "language": "C",
+ "compiler": {
+ "path": "/usr/bin/cc",
+ "id": "GNU",
+ "version": "9.3.0",
+ "implicit": {
+ "includeDirectories": [
+ "/usr/lib/gcc/x86_64-linux-gnu/9/include",
+ "/usr/local/include",
+ "/usr/include/x86_64-linux-gnu",
+ "/usr/include"
+ ],
+ "linkDirectories": [
+ "/usr/lib/gcc/x86_64-linux-gnu/9",
+ "/usr/lib/x86_64-linux-gnu",
+ "/usr/lib",
+ "/lib/x86_64-linux-gnu",
+ "/lib"
+ ],
+ "linkFrameworkDirectories": [],
+ "linkLibraries": [ "gcc", "gcc_s", "c", "gcc", "gcc_s" ]
+ }
+ },
+ "sourceFileExtensions": [ "c", "m" ]
+ },
+ {
+ "language": "CXX",
+ "compiler": {
+ "path": "/usr/bin/c++",
+ "id": "GNU",
+ "version": "9.3.0",
+ "implicit": {
+ "includeDirectories": [
+ "/usr/include/c++/9",
+ "/usr/include/x86_64-linux-gnu/c++/9",
+ "/usr/include/c++/9/backward",
+ "/usr/lib/gcc/x86_64-linux-gnu/9/include",
+ "/usr/local/include",
+ "/usr/include/x86_64-linux-gnu",
+ "/usr/include"
+ ],
+ "linkDirectories": [
+ "/usr/lib/gcc/x86_64-linux-gnu/9",
+ "/usr/lib/x86_64-linux-gnu",
+ "/usr/lib",
+ "/lib/x86_64-linux-gnu",
+ "/lib"
+ ],
+ "linkFrameworkDirectories": [],
+ "linkLibraries": [
+ "stdc++", "m", "gcc_s", "gcc", "c", "gcc_s", "gcc"
+ ]
+ }
+ },
+ "sourceFileExtensions": [
+ "C", "M", "c++", "cc", "cpp", "cxx", "mm", "CPP"
+ ]
+ }
+ ]
+ }
+
+The members specific to ``toolchains`` objects are:
+
+``toolchains``
+ A JSON array whose entries are each a JSON object specifying a toolchain
+ associated with a particular language. The members of each entry 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
+ :command:`project` command. Because CMake only supports a single toolchain
+ per language, this field can be used as a key.
+
+ ``compiler``
+ A JSON object containing members:
+
+ ``path``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_COMPILER` variable is defined for the current
+ language. Its value is a JSON string holding the path to the compiler.
+
+ ``id``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_COMPILER_ID` variable is defined for the current
+ language. Its value is a JSON string holding the ID (GNU, MSVC, etc.) of
+ the compiler.
+
+ ``version``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable is defined for the
+ current language. Its value is a JSON string holding the version of the
+ compiler.
+
+ ``target``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_COMPILER_TARGET` variable is defined for the
+ current language. Its value is a JSON string holding the cross-compiling
+ target of the compiler.
+
+ ``implicit``
+ A JSON object containing members:
+
+ ``includeDirectories``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES` variable is
+ defined for the current language. Its value is a JSON array of JSON
+ strings where each string holds a path to an implicit include
+ directory for the compiler.
+
+ ``linkDirectories``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES` variable is
+ defined for the current language. Its value is a JSON array of JSON
+ strings where each string holds a path to an implicit link directory
+ for the compiler.
+
+ ``linkFrameworkDirectories``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES` variable
+ is defined for the current language. Its value is a JSON array of JSON
+ strings where each string holds a path to an implicit link framework
+ directory for the compiler.
+
+ ``linkLibraries``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES` variable is defined
+ for the current language. Its value is a JSON array of JSON strings
+ where each string holds a path to an implicit link library for the
+ compiler.
+
+ ``sourceFileExtensions``
+ Optional member that is present when the
+ :variable:`CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS` variable is defined for
+ the current language. Its value is a JSON array of JSON strings where each
+ each string holds a file extension (without the leading dot) for the
+ language.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 482b14e31..ca4ea3e0a 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -46,7 +46,8 @@ Available boolean expressions are:
Logical Operators
-----------------
-``$<BOOL:string>``
+.. genex:: $<BOOL:string>
+
Converts ``string`` to ``0`` or ``1``. Evaluates to ``0`` if any of the
following is true:
@@ -57,23 +58,27 @@ Logical Operators
Otherwise evaluates to ``1``.
-``$<AND:conditions>``
+.. genex:: $<AND:conditions>
+
where ``conditions`` is a comma-separated list of boolean expressions.
Evaluates to ``1`` if all conditions are ``1``.
Otherwise evaluates to ``0``.
-``$<OR:conditions>``
+.. genex:: $<OR:conditions>
+
where ``conditions`` is a comma-separated list of boolean expressions.
Evaluates to ``1`` if at least one of the conditions is ``1``.
Otherwise evaluates to ``0``.
-``$<NOT:condition>``
+.. genex:: $<NOT:condition>
+
``0`` if ``condition`` is ``1``, else ``1``.
String Comparisons
------------------
-``$<STREQUAL:string1,string2>``
+.. genex:: $<STREQUAL:string1,string2>
+
``1`` if ``string1`` and ``string2`` are equal, else ``0``.
The comparison is case-sensitive. For a case-insensitive comparison,
combine with a :ref:`string transforming generator expression
@@ -83,101 +88,150 @@ String Comparisons
$<STREQUAL:$<UPPER_CASE:${foo}>,"BAR"> # "1" if ${foo} is any of "BAR", "Bar", "bar", ...
-``$<EQUAL:value1,value2>``
+.. genex:: $<EQUAL:value1,value2>
+
``1`` if ``value1`` and ``value2`` are numerically equal, else ``0``.
-``$<IN_LIST:string,list>``
+
+.. genex:: $<IN_LIST:string,list>
+
``1`` if ``string`` is member of the semicolon-separated ``list``, else ``0``.
Uses case-sensitive comparisons.
-``$<VERSION_LESS:v1,v2>``
+
+.. genex:: $<VERSION_LESS:v1,v2>
+
``1`` if ``v1`` is a version less than ``v2``, else ``0``.
-``$<VERSION_GREATER:v1,v2>``
+
+.. genex:: $<VERSION_GREATER:v1,v2>
+
``1`` if ``v1`` is a version greater than ``v2``, else ``0``.
-``$<VERSION_EQUAL:v1,v2>``
+
+.. genex:: $<VERSION_EQUAL:v1,v2>
+
``1`` if ``v1`` is the same version as ``v2``, else ``0``.
-``$<VERSION_LESS_EQUAL:v1,v2>``
+
+.. genex:: $<VERSION_LESS_EQUAL:v1,v2>
+
``1`` if ``v1`` is a version less than or equal to ``v2``, else ``0``.
-``$<VERSION_GREATER_EQUAL:v1,v2>``
- ``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
+.. genex:: $<VERSION_GREATER_EQUAL:v1,v2>
+
+ ``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
Variable Queries
----------------
-``$<TARGET_EXISTS:target>``
+.. genex:: $<TARGET_EXISTS:target>
+
``1`` if ``target`` exists, else ``0``.
-``$<CONFIG:cfgs>``
+
+.. genex:: $<CONFIG:cfgs>
+
``1`` if config is any one of the entries in ``cfgs``, else ``0``. This is a
case-insensitive comparison. The mapping in
:prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by this
expression when it is evaluated on a property on an :prop_tgt:`IMPORTED`
target.
-``$<PLATFORM_ID:platform_ids>``
+
+.. genex:: $<PLATFORM_ID:platform_ids>
+
where ``platform_ids`` is a comma-separated list.
``1`` if the CMake's platform id matches any one of the entries in
``platform_ids``, otherwise ``0``.
See also the :variable:`CMAKE_SYSTEM_NAME` variable.
-``$<C_COMPILER_ID:compiler_ids>``
+
+.. genex:: $<C_COMPILER_ID:compiler_ids>
+
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the C compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<CXX_COMPILER_ID:compiler_ids>``
+
+.. genex:: $<CXX_COMPILER_ID:compiler_ids>
+
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the CXX compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<CUDA_COMPILER_ID:compiler_ids>``
+
+.. genex:: $<CUDA_COMPILER_ID:compiler_ids>
+
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``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<OBJC_COMPILER_ID:compiler_ids>``
+
+.. genex:: $<OBJC_COMPILER_ID:compiler_ids>
+
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``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<OBJCXX_COMPILER_ID:compiler_ids>``
+
+.. genex:: $<OBJCXX_COMPILER_ID:compiler_ids>
+
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``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<Fortran_COMPILER_ID:compiler_ids>``
+
+.. genex:: $<Fortran_COMPILER_ID:compiler_ids>
+
where ``compiler_ids`` is a comma-separated list.
``1`` if the CMake's compiler id of the Fortran compiler matches any one
of the entries in ``compiler_ids``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<ISPC_COMPILER_ID:compiler_ids>``
+
+.. genex:: $<ISPC_COMPILER_ID:compiler_ids>
+
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``.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<C_COMPILER_VERSION:version>``
+
+.. genex:: $<C_COMPILER_VERSION:version>
+
``1`` if the version of the C compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<CXX_COMPILER_VERSION:version>``
+
+.. genex:: $<CXX_COMPILER_VERSION:version>
+
``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<CUDA_COMPILER_VERSION:version>``
+
+.. genex:: $<CUDA_COMPILER_VERSION:version>
+
``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<OBJC_COMPILER_VERSION:version>``
+
+.. genex:: $<OBJC_COMPILER_VERSION:version>
+
``1`` if the version of the OBJC compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<OBJCXX_COMPILER_VERSION:version>``
+
+.. genex:: $<OBJCXX_COMPILER_VERSION:version>
+
``1`` if the version of the OBJCXX compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<Fortran_COMPILER_VERSION:version>``
+
+.. genex:: $<Fortran_COMPILER_VERSION:version>
+
``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<ISPC_COMPILER_VERSION:version>``
+
+.. genex:: $<ISPC_COMPILER_VERSION:version>
+
``1`` if the version of the ISPC compiler matches ``version``, otherwise ``0``.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<TARGET_POLICY:policy>``
+
+.. genex:: $<TARGET_POLICY:policy>
+
``1`` if the ``policy`` was NEW when the 'head' target was created,
else ``0``. If the ``policy`` was not set, the warning message for the policy
will be emitted. This generator expression only works for a subset of
policies.
-``$<COMPILE_FEATURES:features>``
+
+.. genex:: $<COMPILE_FEATURES:features>
+
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
@@ -189,7 +243,8 @@ Variable Queries
.. _`Boolean COMPILE_LANGUAGE Generator Expression`:
-``$<COMPILE_LANG_AND_ID:language,compiler_ids>``
+.. genex:: $<COMPILE_LANG_AND_ID:language,compiler_ids>
+
``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
@@ -225,7 +280,8 @@ Variable Queries
$<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:Clang>>:COMPILING_C_WITH_CLANG>
)
-``$<COMPILE_LANGUAGE:languages>``
+.. genex:: $<COMPILE_LANGUAGE:languages>
+
``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
@@ -270,7 +326,8 @@ Variable Queries
.. _`Boolean LINK_LANGUAGE Generator Expression`:
-``$<LINK_LANG_AND_ID:language,compiler_ids>``
+.. genex:: $<LINK_LANG_AND_ID:language,compiler_ids>
+
``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
@@ -309,7 +366,8 @@ Variable Queries
``$<LINK_LANGUAGE:language>`` for constraints about the usage of this
generator expression.
-``$<LINK_LANGUAGE:languages>``
+.. genex:: $<LINK_LANGUAGE:languages>
+
``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
@@ -371,14 +429,16 @@ Variable Queries
evaluation will give ``C`` as link language, so the second pass will
correctly add target ``libother`` as link dependency.
-``$<DEVICE_LINK:list>``
+.. genex:: $<DEVICE_LINK:list>
+
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
policy :policy:`CMP0105`. This expression can only be used to specify link
options.
-``$<HOST_LINK:list>``
+.. genex:: $<HOST_LINK:list>
+
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
@@ -434,11 +494,16 @@ Escaped Characters
String literals to escape the special meaning a character would otherwise have:
-``$<ANGLE-R>``
+.. genex:: $<ANGLE-R>
+
A literal ``>``. Used for example to compare strings that contain a ``>``.
-``$<COMMA>``
+
+.. genex:: $<COMMA>
+
A literal ``,``. Used for example to compare strings which contain a ``,``.
-``$<SEMICOLON>``
+
+.. genex:: $<SEMICOLON>
+
A literal ``;``. Used to prevent list expansion on an argument with ``;``.
.. _`Conditional Generator Expressions`:
@@ -449,11 +514,13 @@ Conditional Expressions
Conditional generator expressions depend on a boolean condition
that must be ``0`` or ``1``.
-``$<condition:true_string>``
+.. genex:: $<condition:true_string>
+
Evaluates to ``true_string`` if ``condition`` is ``1``.
Otherwise evaluates to the empty string.
-``$<IF:condition,true_string,false_string>``
+.. genex:: $<IF:condition,true_string,false_string>
+
Evaluates to ``true_string`` if ``condition`` is ``1``.
Otherwise evaluates to ``false_string``.
@@ -472,22 +539,34 @@ otherwise expands to the empty string.
String Transformations
----------------------
-``$<JOIN:list,string>``
+.. genex:: $<JOIN:list,string>
+
Joins the list with the content of ``string``.
-``$<REMOVE_DUPLICATES:list>``
+
+.. genex:: $<REMOVE_DUPLICATES:list>
+
Removes duplicated items in the given ``list``.
-``$<FILTER:list,INCLUDE|EXCLUDE,regex>``
+
+.. genex:: $<FILTER:list,INCLUDE|EXCLUDE,regex>
+
Includes or removes items from ``list`` that match the regular expression ``regex``.
-``$<LOWER_CASE:string>``
+
+.. genex:: $<LOWER_CASE:string>
+
Content of ``string`` converted to lower case.
-``$<UPPER_CASE:string>``
+
+.. genex:: $<UPPER_CASE:string>
+
Content of ``string`` converted to upper case.
-``$<GENEX_EVAL:expr>``
+.. genex:: $<GENEX_EVAL:expr>
+
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.
-``$<TARGET_GENEX_EVAL:tgt,expr>``
+
+.. genex:: $<TARGET_GENEX_EVAL:tgt,expr>
+
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.
@@ -526,62 +605,99 @@ String Transformations
Variable Queries
----------------
-``$<CONFIG>``
+.. genex:: $<CONFIG>
+
Configuration name.
-``$<CONFIGURATION>``
+
+.. genex:: $<CONFIGURATION>
+
Configuration name. Deprecated since CMake 3.0. Use ``CONFIG`` instead.
-``$<PLATFORM_ID>``
+
+.. genex:: $<PLATFORM_ID>
+
The current system's CMake platform id.
See also the :variable:`CMAKE_SYSTEM_NAME` variable.
-``$<C_COMPILER_ID>``
+
+.. genex:: $<C_COMPILER_ID>
+
The CMake's compiler id of the C compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<CXX_COMPILER_ID>``
+
+.. genex:: $<CXX_COMPILER_ID>
+
The CMake's compiler id of the CXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<CUDA_COMPILER_ID>``
+
+.. genex:: $<CUDA_COMPILER_ID>
+
The CMake's compiler id of the CUDA compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<OBJC_COMPILER_ID>``
+
+.. genex:: $<OBJC_COMPILER_ID>
+
The CMake's compiler id of the OBJC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<OBJCXX_COMPILER_ID>``
+
+.. genex:: $<OBJCXX_COMPILER_ID>
+
The CMake's compiler id of the OBJCXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<Fortran_COMPILER_ID>``
+
+.. genex:: $<Fortran_COMPILER_ID>
+
The CMake's compiler id of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<ISPC_COMPILER_ID>``
+
+.. genex:: $<ISPC_COMPILER_ID>
+
The CMake's compiler id of the ISPC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
-``$<C_COMPILER_VERSION>``
+
+.. genex:: $<C_COMPILER_VERSION>
+
The version of the C compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<CXX_COMPILER_VERSION>``
+
+.. genex:: $<CXX_COMPILER_VERSION>
+
The version of the CXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<CUDA_COMPILER_VERSION>``
+
+.. genex:: $<CUDA_COMPILER_VERSION>
+
The version of the CUDA compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<OBJC_COMPILER_VERSION>``
+
+.. genex:: $<OBJC_COMPILER_VERSION>
+
The version of the OBJC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<OBJCXX_COMPILER_VERSION>``
+
+.. genex:: $<OBJCXX_COMPILER_VERSION>
+
The version of the OBJCXX compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<Fortran_COMPILER_VERSION>``
+
+.. genex:: $<Fortran_COMPILER_VERSION>
+
The version of the Fortran compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<ISPC_COMPILER_VERSION>``
+
+.. genex:: $<ISPC_COMPILER_VERSION>
+
The version of the ISPC compiler used.
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-``$<COMPILE_LANGUAGE>``
+
+.. genex:: $<COMPILE_LANGUAGE>
+
The compile language of source files when evaluating compile options.
See :ref:`the related boolean expression
<Boolean COMPILE_LANGUAGE Generator Expression>`
``$<COMPILE_LANGUAGE:language>``
for notes about the portability of this generator expression.
-``$<LINK_LANGUAGE>``
+
+.. genex:: $<LINK_LANGUAGE>
+
The link language of target when evaluating link options.
See :ref:`the related boolean expression
<Boolean LINK_LANGUAGE Generator Expression>` ``$<LINK_LANGUAGE:language>``
@@ -608,14 +724,19 @@ In the following, "the ``tgt`` filename" means the name of the ``tgt``
binary file. This has to be distinguished from "the target name",
which is just the string ``tgt``.
-``$<TARGET_NAME_IF_EXISTS:tgt>``
+.. genex:: $<TARGET_NAME_IF_EXISTS:tgt>
+
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
expression is evaluated on.
-``$<TARGET_FILE:tgt>``
+
+.. genex:: $<TARGET_FILE:tgt>
+
Full path to the ``tgt`` binary file.
-``$<TARGET_FILE_BASE_NAME:tgt>``
+
+.. genex:: $<TARGET_FILE_BASE_NAME:tgt>
+
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``.
@@ -632,36 +753,48 @@ which is just the string ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_FILE_PREFIX:tgt>``
+
+.. genex:: $<TARGET_FILE_PREFIX:tgt>
+
Prefix of the ``tgt`` filename (such as ``lib``).
See also the :prop_tgt:`PREFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_FILE_SUFFIX:tgt>``
+
+.. genex:: $<TARGET_FILE_SUFFIX:tgt>
+
Suffix of the ``tgt`` filename (extension such as ``.so`` or ``.exe``).
See also the :prop_tgt:`SUFFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_FILE_NAME:tgt>``
+
+.. genex:: $<TARGET_FILE_NAME:tgt>
+
The ``tgt`` filename.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_FILE_DIR:tgt>``
+
+.. genex:: $<TARGET_FILE_DIR:tgt>
+
Directory of the ``tgt`` binary file.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_LINKER_FILE:tgt>``
+
+.. genex:: $<TARGET_LINKER_FILE:tgt>
+
File used when linking to the ``tgt`` target. This will usually
be the library that ``tgt`` represents (``.a``, ``.lib``, ``.so``),
but for a shared library on DLL platforms, it would be the ``.lib``
import library associated with the DLL.
-``$<TARGET_LINKER_FILE_BASE_NAME:tgt>``
+
+.. genex:: $<TARGET_LINKER_FILE_BASE_NAME:tgt>
+
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``.
@@ -677,7 +810,9 @@ which is just the string ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_LINKER_FILE_PREFIX:tgt>``
+
+.. genex:: $<TARGET_LINKER_FILE_PREFIX:tgt>
+
Prefix of file used to link target ``tgt``.
See also the :prop_tgt:`PREFIX` and :prop_tgt:`IMPORT_PREFIX` target
@@ -685,7 +820,9 @@ which is just the string ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_LINKER_FILE_SUFFIX:tgt>``
+
+.. genex:: $<TARGET_LINKER_FILE_SUFFIX:tgt>
+
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").
@@ -695,36 +832,49 @@ which is just the string ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_LINKER_FILE_NAME:tgt>``
+
+.. genex:: $<TARGET_LINKER_FILE_NAME:tgt>
+
Name of file used to link target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_LINKER_FILE_DIR:tgt>``
+
+.. genex:: $<TARGET_LINKER_FILE_DIR:tgt>
+
Directory of file used to link target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_SONAME_FILE:tgt>``
+
+.. genex:: $<TARGET_SONAME_FILE:tgt>
+
File with soname (``.so.3``) where ``tgt`` is the name of a target.
-``$<TARGET_SONAME_FILE_NAME:tgt>``
+.. genex:: $<TARGET_SONAME_FILE_NAME:tgt>
+
Name of file with soname (``.so.3``).
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_SONAME_FILE_DIR:tgt>``
+
+.. genex:: $<TARGET_SONAME_FILE_DIR:tgt>
+
Directory of with soname (``.so.3``).
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_PDB_FILE:tgt>``
+
+.. genex:: $<TARGET_PDB_FILE:tgt>
+
Full path to the linker generated program database file (.pdb)
where ``tgt`` is the name of a target.
See also the :prop_tgt:`PDB_NAME` and :prop_tgt:`PDB_OUTPUT_DIRECTORY`
target properties and their configuration specific variants
:prop_tgt:`PDB_NAME_<CONFIG>` and :prop_tgt:`PDB_OUTPUT_DIRECTORY_<CONFIG>`.
-``$<TARGET_PDB_FILE_BASE_NAME:tgt>``
+
+.. genex:: $<TARGET_PDB_FILE_BASE_NAME:tgt>
+
Base name of the linker generated program database file (.pdb)
where ``tgt`` is the name of a target.
@@ -740,23 +890,31 @@ which is just the string ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_PDB_FILE_NAME:tgt>``
+
+.. genex:: $<TARGET_PDB_FILE_NAME:tgt>
+
Name of the linker generated program database file (.pdb).
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_PDB_FILE_DIR:tgt>``
+
+.. genex:: $<TARGET_PDB_FILE_DIR:tgt>
+
Directory of the linker generated program database file (.pdb).
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_BUNDLE_DIR:tgt>``
+
+.. genex:: $<TARGET_BUNDLE_DIR:tgt>
+
Full path to the bundle directory (``my.app``, ``my.framework``, or
``my.bundle``) where ``tgt`` is the name of a target.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_BUNDLE_CONTENT_DIR:tgt>``
+
+.. genex:: $<TARGET_BUNDLE_CONTENT_DIR:tgt>
+
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
@@ -765,17 +923,23 @@ which is just the string ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-``$<TARGET_PROPERTY:tgt,prop>``
+
+.. genex:: $<TARGET_PROPERTY:tgt,prop>
+
Value of the property ``prop`` on the target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
-``$<TARGET_PROPERTY:prop>``
+
+.. genex:: $<TARGET_PROPERTY:prop>
+
Value of the property ``prop`` on the target for which the expression
is being evaluated. Note that for generator expressions in
:ref:`Target Usage Requirements` this is the consuming target rather
than the target specifying the requirement.
-``$<INSTALL_PREFIX>``
+
+.. 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.
@@ -783,30 +947,43 @@ which is just the string ``tgt``.
Output-Related Expressions
--------------------------
-``$<TARGET_NAME:...>``
+.. genex:: $<TARGET_NAME:...>
+
Marks ``...`` as being the name of a target. This is required if exporting
targets to multiple dependent export sets. The ``...`` must be a literal
name of a target- it may not contain generator expressions.
-``$<LINK_ONLY:...>``
+
+.. genex:: $<LINK_ONLY:...>
+
Content of ``...`` except when evaluated in a link interface while
propagating :ref:`Target Usage Requirements`, in which case it is the
empty string.
Intended for use only in an :prop_tgt:`INTERFACE_LINK_LIBRARIES` target
property, perhaps via the :command:`target_link_libraries` command,
to specify private link dependencies without other usage requirements.
-``$<INSTALL_INTERFACE:...>``
+
+.. genex:: $<INSTALL_INTERFACE:...>
+
Content of ``...`` when the property is exported using :command:`install(EXPORT)`,
and empty otherwise.
-``$<BUILD_INTERFACE:...>``
+
+.. genex:: $<BUILD_INTERFACE:...>
+
Content of ``...`` when the property is exported using :command:`export`, or
when the target is used by another target in the same buildsystem. Expands to
the empty string otherwise.
-``$<MAKE_C_IDENTIFIER:...>``
+
+.. genex:: $<MAKE_C_IDENTIFIER:...>
+
Content of ``...`` converted to a C identifier. The conversion follows the
same behavior as :command:`string(MAKE_C_IDENTIFIER)`.
-``$<TARGET_OBJECTS:objLib>``
+
+.. genex:: $<TARGET_OBJECTS:objLib>
+
List of objects resulting from build of ``objLib``.
-``$<SHELL_PATH:...>``
+
+.. genex:: $<SHELL_PATH:...>
+
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.
@@ -816,6 +993,26 @@ Output-Related Expressions
``;`` 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:...>
+
+ .. versionadded:: 3.20
+
+ Only valid in :command:`add_custom_command` and :command:`add_custom_target`
+ as the outer-most generator expression in an argument.
+ With the :generator:`Ninja Multi-Config` generator, generator expressions
+ in ``...`` are evaluated using the custom command's "output config".
+ With other generators, the content of ``...`` is evaluated normally.
+
+.. genex:: $<COMMAND_CONFIG:...>
+
+ .. versionadded:: 3.20
+
+ Only valid in :command:`add_custom_command` and :command:`add_custom_target`
+ as the outer-most generator expression in an argument.
+ With the :generator:`Ninja Multi-Config` generator, generator expressions
+ in ``...`` are evaluated using the custom command's "command config".
+ With other generators, the content of ``...`` is evaluated normally.
+
Debugging
=========
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 431797fb9..17c1a1e5c 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -15,7 +15,6 @@ These modules are loaded using the :command:`include` command.
.. toctree::
:maxdepth: 1
- /module/AddFileDependencies
/module/AndroidTestUtilities
/module/BundleUtilities
/module/CheckCCompilerFlag
@@ -75,7 +74,6 @@ These modules are loaded using the :command:`include` command.
/module/CTestUseLaunchers
/module/Dart
/module/DeployQt4
- /module/Documentation
/module/ExternalData
/module/ExternalProject
/module/FeatureSummary
@@ -98,11 +96,8 @@ These modules are loaded using the :command:`include` command.
/module/TestForSTDNamespace
/module/UseEcos
/module/UseJava
- /module/UseJavaClassFilelist
- /module/UseJavaSymlinks
/module/UseSWIG
/module/UsewxWidgets
- /module/WriteCompilerDetectionHeader
Find Modules
^^^^^^^^^^^^
@@ -276,15 +271,20 @@ Deprecated Utility Modules
.. toctree::
:maxdepth: 1
+ /module/AddFileDependencies
/module/CMakeDetermineVSServicePack
/module/CMakeExpandImportedTargets
/module/CMakeForceCompiler
/module/CMakeParseArguments
+ /module/Documentation
/module/MacroAddFileDependencies
/module/TestCXXAcceptsFlag
+ /module/UseJavaClassFilelist
+ /module/UseJavaSymlinks
/module/UsePkgConfig
/module/Use_wxWindows
/module/WriteBasicConfigVersionFile
+ /module/WriteCompilerDetectionHeader
Deprecated Find Modules
=======================
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index fa10f664c..bd6b2f0ca 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.20
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0120: The WriteCompilerDetectionHeader module is removed. </policy/CMP0120>
+ CMP0119: LANGUAGE source file property explicitly compiles as language. </policy/CMP0119>
+ CMP0118: The GENERATED source file property is now visible in all directories. </policy/CMP0118>
+ CMP0117: MSVC RTTI flag /GR is not added to CMAKE_CXX_FLAGS by default. </policy/CMP0117>
+ CMP0116: Ninja generators transform DEPFILEs from add_custom_command(). </policy/CMP0116>
+ CMP0115: Source file extensions must be explicit. </policy/CMP0115>
+
Policies Introduced by CMake 3.19
=================================
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index 6f137c459..467818dfa 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -29,337 +29,839 @@ is using Git, ``CMakePresets.json`` may be tracked, and
Format
======
- The files are a JSON document with an object as the root:
+The files are a JSON document with an object as the root:
- .. literalinclude:: presets/example.json
- :language: json
+.. literalinclude:: presets/example.json
+ :language: json
- The root object recognizes the following fields:
+The root object recognizes the following fields:
- ``version``
+``version``
- A required integer representing the version of the JSON schema. Currently,
- the only supported version is 1.
+ A required integer representing the version of the JSON schema.
+ The supported versions are ``1`` and ``2``.
- ``cmakeMinimumRequired``
+``cmakeMinimumRequired``
- An optional object representing the minimum version of CMake needed to
- build this project. This object consists of the following fields:
+ An optional object representing the minimum version of CMake needed to
+ build this project. This object consists of the following fields:
- ``major``
+ ``major``
- An optional integer representing the major version.
+ An optional integer representing the major version.
- ``minor``
+ ``minor``
- An optional integer representing the minor version.
+ An optional integer representing the minor version.
- ``patch``
+ ``patch``
- An optional integer representing the patch version.
+ An optional integer representing the patch version.
- ``vendor``
+``vendor``
- An optional map containing vendor-specific information. CMake does not
- interpret the contents of this field except to verify that it is a map if
- it does exist. However, the keys should be a vendor-specific domain name
- 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.
+ 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.
- ``configurePresets``
+``configurePresets``
- An optional array of configure preset objects. Each preset may contain the
- following fields:
+ An optional array of `Configure Preset`_ objects.
+ This is allowed in preset files specifying version 1 or above.
- ``name``
+``buildPresets``
+
+ An optional array of `Build Preset`_ objects.
+ This is allowed in preset files specifying version 2 or above.
+
+``testPresets``
+
+ An optional array of `Test Preset`_ objects.
+ This is allowed in preset files specifying version 2 or above.
+
+Configure Preset
+^^^^^^^^^^^^^^^^
+
+Each entry of the ``configurePresets`` array is a JSON object
+that may contain the following fields:
+
+``name``
+
+ A required string representing the machine-friendly name of the preset.
+ This identifier is used in the :ref:`cmake --preset <CMake Options>` option.
+ There must not be two configure presets in the union of ``CMakePresets.json``
+ and ``CMakeUserPresets.json`` in the same directory with the same name.
+ However, a configure preset may have the same name as a build or test preset.
+
+``hidden``
+
+ An optional boolean specifying whether or not a preset should be hidden.
+ If a preset is hidden, it cannot be used in the ``--preset=`` argument,
+ will not show up in the :manual:`CMake GUI <cmake-gui(1)>`, and does not
+ have to have a valid ``generator`` or ``binaryDir``, even from
+ inheritance. ``hidden`` presets are intended to be used as a base for
+ other presets to inherit via the ``inherits`` field.
+
+``inherits``
+
+ An optional array of strings representing the names of presets to inherit
+ from. The preset will inherit all of the fields from the ``inherits``
+ presets by default (except ``name``, ``hidden``, ``inherits``,
+ ``description``, and ``displayName``), but can override them as
+ desired. If multiple ``inherits`` presets provide conflicting values for
+ the same field, the earlier preset in the ``inherits`` list will be
+ preferred. Presets in ``CMakePresets.json`` may not inherit from presets
+ in ``CMakeUserPresets.json``.
+
+ This field can also be a string, which is equivalent to an array
+ containing one string.
+
+``vendor``
+
+ An optional map containing vendor-specific information. CMake does not
+ interpret the contents of this field except to verify that it is a map
+ if it does exist. However, it should follow the same conventions as the
+ root-level ``vendor`` field. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+``displayName``
+
+ An optional string with a human-friendly name of the preset.
+
+``description``
+
+ An optional string with a human-friendly description of the preset.
+
+``generator``
+
+ An optional string representing the generator to use for the preset. If
+ ``generator`` is not specified, it must be inherited from the
+ ``inherits`` preset (unless this preset is ``hidden``).
+
+ 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.
+
+``architecture``, ``toolset``
+
+ Optional fields representing the platform and toolset, respectively, for
+ generators that support them. Each may be either a string or an object
+ with the following fields:
+
+ ``value``
+
+ An optional string representing the value.
+
+ ``strategy``
+
+ An optional string telling CMake how to handle the ``architecture`` or
+ ``toolset`` field. Valid values are:
+
+ ``"set"``
+
+ Set the respective value. This will result in an error for generators
+ that do not support the respective field.
+
+ ``"external"``
+
+ Do not set the value, even if the generator supports it. This is
+ useful if, for example, a preset uses the Ninja generator, and an IDE
+ knows how to set up the Visual C++ environment from the
+ ``architecture`` and ``toolset`` fields. In that case, CMake will
+ ignore the field, but the IDE can use them to set up the environment
+ before invoking CMake.
+
+``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``).
+
+``cmakeExecutable``
+
+ An optional string representing the path to the CMake executable to use
+ for this preset. This is reserved for use by IDEs, and is not used by
+ CMake itself. IDEs that use this field should expand any macros in it.
+
+``cacheVariables``
+
+ An optional map of cache variables. The key is the variable name (which
+ may not be an empty string), and the value is either ``null``, a boolean
+ (which is equivalent to a value of ``"TRUE"`` or ``"FALSE"`` and a type
+ of ``BOOL``), a string representing the value of the variable (which
+ supports `macro expansion`_), or an object with the following fields:
+
+ ``type``
+
+ An optional string representing the type of the variable.
+
+ ``value``
+
+ A required string or boolean representing the value of the variable.
+ A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``. This field
+ supports `macro expansion`_.
+
+ Cache variables are inherited through the ``inherits`` field, and the
+ preset's variables will be the union of its own ``cacheVariables`` and
+ the ``cacheVariables`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+``environment``
+
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or
+ a string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment. This field supports `macro expansion`_, and environment
+ variables in this map may reference each other, and may be listed in any
+ order, as long as such references do not cause a cycle (for example,
+ if ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment`` and
+ the ``environment`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+``warnings``
+
+ An optional object specifying the warnings to enable. The object may
+ contain the following fields:
+
+ ``dev``
+
+ An optional boolean. Equivalent to passing ``-Wdev`` or ``-Wno-dev``
+ on the command line. This may not be set to ``false`` if ``errors.dev``
+ is set to ``true``.
+
+ ``deprecated``
+
+ An optional boolean. Equivalent to passing ``-Wdeprecated`` or
+ ``-Wno-deprecated`` on the command line. This may not be set to
+ ``false`` if ``errors.deprecated`` is set to ``true``.
+
+ ``uninitialized``
+
+ An optional boolean. Setting this to ``true`` is equivalent to passing
+ ``--warn-uninitialized`` on the command line.
+
+ ``unusedCli``
+
+ An optional boolean. Setting this to ``false`` is equivalent to passing
+ ``--no-warn-unused-cli`` on the command line.
+
+ ``systemVars``
+
+ An optional boolean. Setting this to ``true`` is equivalent to passing
+ ``--check-system-vars`` on the command line.
+
+``errors``
+
+ An optional object specifying the errors to enable. The object may
+ contain the following fields:
+
+ ``dev``
+
+ An optional boolean. Equivalent to passing ``-Werror=dev`` or
+ ``-Wno-error=dev`` on the command line. This may not be set to ``true``
+ if ``warnings.dev`` is set to ``false``.
+
+ ``deprecated``
+
+ An optional boolean. Equivalent to passing ``-Werror=deprecated`` or
+ ``-Wno-error=deprecated`` on the command line. This may not be set to
+ ``true`` if ``warnings.deprecated`` is set to ``false``.
+
+``debug``
+
+ An optional object specifying debug options. The object may contain the
+ following fields:
+
+ ``output``
+
+ An optional boolean. Setting this to ``true`` is equivalent to passing
+ ``--debug-output`` on the command line.
+
+ ``tryCompile``
+
+ An optional boolean. Setting this to ``true`` is equivalent to passing
+ ``--debug-trycompile`` on the command line.
+
+ ``find``
+
+ An optional boolean. Setting this to ``true`` is equivalent to passing
+ ``--debug-find`` on the command line.
+
+Build Preset
+^^^^^^^^^^^^
+
+Each entry of the ``buildPresets`` array is a JSON object
+that may contain the following fields:
+
+``name``
+
+ A required string representing the machine-friendly name of the preset.
+ This identifier is used in the
+ :ref:`cmake --build --preset <Build Tool Mode>` option.
+ There must not be two build presets in the union of ``CMakePresets.json``
+ and ``CMakeUserPresets.json`` in the same directory with the same name.
+ However, a build preset may have the same name as a configure or test preset.
+
+``hidden``
+
+ An optional boolean specifying whether or not a preset should be hidden.
+ If a preset is hidden, it cannot be used in the ``--preset`` argument
+ and does not have to have a valid ``configurePreset``, even from
+ inheritance. ``hidden`` presets are intended to be used as a base for
+ other presets to inherit via the ``inherits`` field.
+
+``inherits``
+
+ An optional array of strings representing the names of presets to
+ inherit from. The preset will inherit all of the fields from the
+ ``inherits`` presets by default (except ``name``, ``hidden``,
+ ``inherits``, ``description``, and ``displayName``), but can override
+ them as desired. If multiple ``inherits`` presets provide conflicting
+ values for the same field, the earlier preset in the ``inherits`` list
+ will be preferred. Presets in ``CMakePresets.json`` may not inherit from
+ presets in ``CMakeUserPresets.json``.
+
+ This field can also be a string, which is equivalent to an array
+ containing one string.
+
+``vendor``
+
+ An optional map containing vendor-specific information. CMake does not
+ interpret the contents of this field except to verify that it is a map
+ if it does exist. However, it should follow the same conventions as the
+ root-level ``vendor`` field. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+``displayName``
+
+ An optional string with a human-friendly name of the preset.
+
+``description``
+
+ An optional string with a human-friendly description of the preset.
- A required string representing the machine-friendly name of the preset.
- This identifier is used in the ``--preset`` argument. There must not be
- two presets in the union of ``CMakePresets.json`` and
- ``CMakeUserPresets.json`` in the same directory with the same name.
+``environment``
- ``hidden``
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or
+ a string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment. This field supports macro expansion, and environment
+ variables in this map may reference each other, and may be listed in any
+ order, as long as such references do not cause a cycle (for example, if
+ ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
- An optional boolean specifying whether or not a preset should be hidden.
- If a preset is hidden, it cannot be used in the ``--preset=`` argument,
- will not show up in the :manual:`CMake GUI <cmake-gui(1)>`, and does not
- have to have a valid ``generator`` or ``binaryDir``, even from
- inheritance. ``hidden`` presets are intended to be used as a base for
- other presets to inherit via the ``inherits`` field.
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment``
+ and the ``environment`` from all its parents. If multiple presets in
+ this union define the same variable, the standard rules of ``inherits``
+ are applied. Setting a variable to ``null`` causes it to not be set,
+ even if a value was inherited from another preset.
- ``inherits``
+``configurePreset``
- An optional array of strings representing the names of presets to inherit
- from. The preset will inherit all of the fields from the ``inherits``
- presets by default (except ``name``, ``hidden``, ``inherits``,
- ``description``, and ``displayName``), but can override them as
- desired. If multiple ``inherits`` presets provide conflicting values for
- the same field, the earlier preset in the ``inherits`` list will be
- preferred. Presets in ``CMakePresets.json`` may not inherit from presets
- in ``CMakeUserPresets.json``.
+ An optional string specifying the name of a configure preset to
+ associate with this build preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless this
+ preset is hidden). The build directory is inferred from the configure
+ preset, so the build will take place in the same ``binaryDir`` that the
+ configuration did.
- This field can also be a string, which is equivalent to an array
- containing one string.
+``inheritConfigureEnvironment``
- ``vendor``
+ An optional boolean that defaults to true. If true, the environment
+ variables from the associated configure preset are inherited after all
+ inherited build preset environments, but before environment variables
+ explicitly specified in this build preset.
- An optional map containing vendor-specific information. CMake does not
- interpret the contents of this field except to verify that it is a map
- if it does exist. However, it should follow the same conventions as the
- root-level ``vendor`` field. If vendors use their own per-preset
- ``vendor`` field, they should implement inheritance in a sensible manner
- when appropriate.
+``jobs``
- ``displayName``
+ An optional integer. Equivalent to passing ``--parallel`` or ``-j`` on
+ the command line.
- An optional string with a human-friendly name of the preset.
+``targets``
- ``description``
+ An optional string or array of strings. Equivalent to passing
+ ``--target`` or ``-t`` on the command line. Vendors may ignore the
+ targets property or hide build presets that explicitly specify targets.
+ This field supports macro expansion.
- An optional string with a human-friendly description of the preset.
+``configuration``
- ``generator``
+ An optional string. Equivalent to passing ``--config`` on the command
+ line.
- 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``).
+``cleanFirst``
- 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.
+ An optional bool. If true, equivalent to passing ``--clean-first`` on
+ the command line.
- ``architecture``
- ``toolset``
+``verbose``
- Optional fields representing the platform and toolset, respectively, for
- generators that support them. Each may be either a string or an object
- with the following fields:
+ An optional bool. If true, equivalent to passing ``--verbose`` on the
+ command line.
- ``value``
+``nativeToolOptions``
- An optional string representing the value.
+ An optional array of strings. Equivalent to passing options after ``--``
+ on the command line. The array values support macro expansion.
- ``strategy``
+Test Preset
+^^^^^^^^^^^
- An optional string telling CMake how to handle the ``architecture`` or
- ``toolset`` field. Valid values are:
+Each entry of the ``testPresets`` array is a JSON object
+that may contain the following fields:
- ``"set"``
+``name``
- Set the respective value. This will result in an error for generators
- that do not support the respective field.
+ A required string representing the machine-friendly name of the preset.
+ This identifier is used in the :ref:`ctest --preset <CTest Options>` option.
+ There must not be two test presets in the union of ``CMakePresets.json``
+ and ``CMakeUserPresets.json`` in the same directory with the same name.
+ However, a test preset may have the same name as a configure or build preset.
- ``"external"``
+``hidden``
- Do not set the value, even if the generator supports it. This is
- useful if, for example, a preset uses the Ninja generator, and an IDE
- knows how to set up the Visual C++ environment from the
- ``architecture`` and ``toolset`` fields. In that case, CMake will
- ignore the field, but the IDE can use them to set up the environment
- before invoking CMake.
+ An optional boolean specifying whether or not a preset should be hidden.
+ If a preset is hidden, it cannot be used in the ``--preset`` argument
+ and does not have to have a valid ``configurePreset``, even from
+ inheritance. ``hidden`` presets are intended to be used as a base for
+ other presets to inherit via the ``inherits`` field.
- ``binaryDir``
+``inherits``
- 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``).
+ An optional array of strings representing the names of presets to
+ inherit from. The preset will inherit all of the fields from the
+ ``inherits`` presets by default (except ``name``, ``hidden``,
+ ``inherits``, ``description``, and ``displayName``), but can override
+ them as desired. If multiple ``inherits`` presets provide conflicting
+ values for the same field, the earlier preset in the ``inherits`` list
+ will be preferred. Presets in ``CMakePresets.json`` may not inherit from
+ presets in ``CMakeUserPresets.json``.
- ``cmakeExecutable``
+ This field can also be a string, which is equivalent to an array
+ containing one string.
- An optional string representing the path to the CMake executable to use
- for this preset. This is reserved for use by IDEs, and is not used by
- CMake itself. IDEs that use this field should expand any macros in it.
+``vendor``
- ``cacheVariables``
+ An optional map containing vendor-specific information. CMake does not
+ interpret the contents of this field except to verify that it is a map
+ if it does exist. However, it should follow the same conventions as the
+ root-level ``vendor`` field. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
- An optional map of cache variables. The key is the variable name (which
- may not be an empty string), and the value is either ``null``, a boolean
- (which is equivalent to a value of ``"TRUE"`` or ``"FALSE"`` and a type
- of ``BOOL``), a string representing the value of the variable (which
- supports macro expansion), or an object with the following fields:
+``displayName``
- ``type``
+ An optional string with a human-friendly name of the preset.
- An optional string representing the type of the variable.
+``description``
- ``value``
+ An optional string with a human-friendly description of the preset.
- A required string or boolean representing the value of the variable.
- A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``. This field
+``environment``
+
+ An optional map of environment variables. The key is the variable name
+ (which may not be an empty string), and the value is either ``null`` or
+ a string representing the value of the variable. Each variable is set
+ regardless of whether or not a value was given to it by the process's
+ environment. This field supports macro expansion, and environment
+ variables in this map may reference each other, and may be listed in any
+ order, as long as such references do not cause a cycle (for example, if
+ ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment``
+ and the ``environment`` from all its parents. If multiple presets in
+ this union define the same variable, the standard rules of ``inherits``
+ are applied. Setting a variable to ``null`` causes it to not be set,
+ even if a value was inherited from another preset.
+
+``configurePreset``
+
+ An optional string specifying the name of a configure preset to
+ associate with this test preset. If ``configurePreset`` is not
+ specified, it must be inherited from the inherits preset (unless this
+ preset is hidden). The build directory is inferred from the configure
+ preset, so tests will run in the same ``binaryDir`` that the
+ configuration did and build did.
+
+``inheritConfigureEnvironment``
+
+ An optional boolean that defaults to true. If true, the environment
+ variables from the associated configure preset are inherited after all
+ inherited test preset environments, but before environment variables
+ explicitly specified in this test preset.
+
+``configuration``
+
+ An optional string. Equivalent to passing ``--build-config`` on the
+ command line.
+
+``overwriteConfigurationFile``
+
+ An optional array of configuration options to overwrite options
+ specified in the CTest configuration file. Equivalent to passing
+ ``--overwrite`` for each value in the array. The array values
+ support macro expansion.
+
+``output``
+
+ An optional object specifying output options. The object may contain the
+ following fields.
+
+ ``shortProgress``
+
+ An optional bool. If true, equivalent to passing ``--progress`` on the
+ command line.
+
+ ``verbosity``
+
+ An optional string specifying verbosity level. Must be one of the
+ following:
+
+ ``default``
+
+ Equivalent to passing no verbosity flags on the command line.
+
+ ``verbose``
+
+ Equivalent to passing ``--verbose`` on the command line.
+
+ ``extra``
+
+ Equivalent to passing ``--extra-verbose`` on the command line.
+
+ ``debug``
+
+ An optional bool. If true, equivalent to passing ``--debug`` on the
+ command line.
+
+ ``outputOnFailure``
+
+ An optional bool. If true, equivalent to passing
+ ``--output-on-failure`` on the command line.
+
+ ``quiet``
+
+ An optional bool. If true, equivalent to passing ``--quiet`` on the
+ command line.
+
+ ``outputLogFile``
+
+ An optional string specifying a path to a log file. Equivalent to
+ passing ``--output-log`` on the command line. This field supports
+ macro expansion.
+
+ ``labelSummary``
+
+ An optional bool. If false, equivalent to passing
+ ``--no-label-summary`` on the command line.
+
+ ``subprojectSummary``
+
+ An optional bool. If false, equivalent to passing
+ ``--no-subproject-summary`` on the command line.
+
+ ``maxPassedTestOutputSize``
+
+ An optional integer specifying the maximum output for passed tests in
+ bytes. Equivalent to passing ``--test-output-size-passed`` on the
+ command line.
+
+ ``maxFailedTestOutputSize``
+
+ An optional integer specifying the maximum output for failed tests in
+ bytes. Equivalent to passing ``--test-output-size-failed`` on the
+ command line.
+
+ ``maxTestNameWidth``
+
+ An optional integer specifying the maximum width of a test name to
+ output. Equivalent to passing ``--max-width`` on the command line.
+
+``filter``
+
+ An optional object specifying how to filter the tests to run. The object
+ may contain the following fields.
+
+ ``include``
+
+ An optional object specifying which tests to include. The object may
+ contain the following fields.
+
+ ``name``
+
+ An optional string specifying a regex for test names. Equivalent to
+ passing ``--tests-regex`` on the command line. This field supports
+ macro expansion.
+
+
+ ``label``
+
+ An optional string specifying a regex for test labels. Equivalent to
+ passing ``--label-regex`` on the command line. This field supports
+ macro expansion.
+
+ ``useUnion``
+
+ An optional bool. Equivalent to passing ``--union`` on the command
+ line.
+
+ ``index``
+
+ An optional object specifying tests to include by test index. The
+ object may contain the following fields. Can also be an optional
+ string specifying a file with the command line syntax for
+ ``--tests-information``. If specified as a string, this field
+ supports macro expansion.
+
+ ``start``
+
+ An optional integer specifying a test index to start testing at.
+
+ ``end``
+
+ An optional integer specifying a test index to stop testing at.
+
+ ``stride``
+
+ An optional integer specifying the increment.
+
+ ``specificTests``
+
+ An optional array of integers specifying specific test indices to
+ run.
+
+ ``exclude``
+
+ An optional object specifying which tests to exclude. The object may
+ contain the following fields.
+
+ ``name``
+
+ An optional string specifying a regex for test names. Equivalent to
+ passing ``--exclude-regex`` on the command line. This field supports
+ macro expansion.
+
+ ``label``
+
+ An optional string specifying a regex for test labels. Equivalent to
+ passing ``--label-exclude`` on the command line. This field supports
+ macro expansion.
+
+ ``fixtures``
+
+ An optional object specifying which fixtures to exclude from adding
+ tests. The object may contain the following fields.
+
+ ``any``
+
+ An optional string specifying a regex for text fixtures to exclude
+ from adding any tests. Equivalent to ``--fixture-exclude-any`` on
+ the command line. This field supports macro expansion.
+
+ ``setup``
+
+ An optional string specifying a regex for text fixtures to exclude
+ from adding setup tests. Equivalent to ``--fixture-exclude-setup``
+ on the command line. This field supports macro expansion.
+
+ ``cleanup``
+
+ An optional string specifying a regex for text fixtures to exclude
+ from adding cleanup tests. Equivalent to
+ ``--fixture-exclude-cleanup`` on the command line. This field
supports macro expansion.
- Cache variables are inherited through the ``inherits`` field, and the
- preset's variables will be the union of its own ``cacheVariables`` and
- the ``cacheVariables`` from all its parents. If multiple presets in this
- union define the same variable, the standard rules of ``inherits`` are
- applied. Setting a variable to ``null`` causes it to not be set, even if
- a value was inherited from another preset.
+``execution``
+
+ An optional object specifying options for test execution. The object may
+ contain the following fields.
+
+ ``stopOnFailure``
+
+ An optional bool. If true, equivalent to passing ``--stop-on-failure``
+ on the command line.
+
+ ``enableFailover``
+
+ An optional bool. If true, equivalent to passing ``-F`` on the command
+ line.
+
+ ``jobs``
+
+ An optional integer. Equivalent to passing ``--parallel`` on the
+ command line.
+
+ ``resourceSpecFile``
+
+ An optional string. Equivalent to passing ``--resource-spec-file`` on
+ the command line. This field supports macro expansion.
+
+ ``testLoad``
- ``environment``
+ An optional integer. Equivalent to passing ``--test-load`` on the
+ command line.
- An optional map of environment variables. The key is the variable name
- (which may not be an empty string), and the value is either ``null`` or
- a string representing the value of the variable. Each variable is set
- regardless of whether or not a value was given to it by the process's
- environment. This field supports macro expansion, and environment
- variables in this map may reference each other, and may be listed in any
- order, as long as such references do not cause a cycle (for example,
- if ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.)
+ ``showOnly``
- Environment variables are inherited through the ``inherits`` field, and
- the preset's environment will be the union of its own ``environment`` and
- the ``environment`` from all its parents. If multiple presets in this
- union define the same variable, the standard rules of ``inherits`` are
- applied. Setting a variable to ``null`` causes it to not be set, even if
- a value was inherited from another preset.
+ An optional string. Equivalent to passing ``--show-only`` on the
+ command line. The string must be one of the following values:
- ``warnings``
+ ``human``
- An optional object specifying the warnings to enable. The object may
- contain the following fields:
+ ``json-v1``
- ``dev``
+ ``repeat``
- An optional boolean. Equivalent to passing ``-Wdev`` or ``-Wno-dev``
- on the command line. This may not be set to ``false`` if ``errors.dev``
- is set to ``true``.
+ An optional object specifying how to repeat tests. Equivalent to
+ passing ``--repeat`` on the command line. The object must have the
+ following fields.
- ``deprecated``
+ ``mode``
- An optional boolean. Equivalent to passing ``-Wdeprecated`` or
- ``-Wno-deprecated`` on the command line. This may not be set to
- ``false`` if ``errors.deprecated`` is set to ``true``.
+ A required string. Must be one of the following values:
- ``uninitialized``
+ ``until-fail``
- An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--warn-uninitialized`` on the command line.
+ ``until-pass``
- ``unusedCli``
+ ``after-timeout``
- An optional boolean. Setting this to ``false`` is equivalent to passing
- ``--no-warn-unused-cli`` on the command line.
+ ``count``
- ``systemVars``
+ A required integer.
- An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--check-system-vars`` on the command line.
+ ``interactiveDebugging``
- ``errors``
+ An optional bool. If true, equivalent to passing
+ ``--interactive-debug-mode 1`` on the command line. If false,
+ equivalent to passing ``--interactive-debug-mode 0`` on the command
+ line.
- An optional object specifying the errors to enable. The object may
- contain the following fields:
+ ``scheduleRandom``
- ``dev``
+ An optional bool. If true, equivalent to passing ``--schedule-random``
+ on the command line.
- An optional boolean. Equivalent to passing ``-Werror=dev`` or
- ``-Wno-error=dev`` on the command line. This may not be set to ``true``
- if ``warnings.dev`` is set to ``false``.
+ ``timeout``
- ``deprecated``
+ An optional integer. Equivalent to passing ``--timeout`` on the
+ command line.
- An optional boolean. Equivalent to passing ``-Werror=deprecated`` or
- ``-Wno-error=deprecated`` on the command line. This may not be set to
- ``true`` if ``warnings.deprecated`` is set to ``false``.
+ ``noTestsAction``
- ``debug``
+ An optional string specifying the behavior if no tests are found. Must
+ be one of the following values:
- An optional object specifying debug options. The object may contain the
- following fields:
+ ``default``
- ``output``
+ Equivalent to not passing any value on the command line.
- An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--debug-output`` on the command line.
+ ``error``
- ``tryCompile``
+ Equivalent to passing ``--no-tests=error`` on the command line.
- An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--debug-trycompile`` on the command line.
+ ``ignore``
- ``find``
+ Equivalent to passing ``--no-tests=ignore`` on the command line.
- An optional boolean. Setting this to ``true`` is equivalent to passing
- ``--debug-find`` on the command line.
+Macro Expansion
+^^^^^^^^^^^^^^^
- As mentioned above, some fields support macro expansion. Macros are
- recognized in the form ``$<macro-namespace>{<macro-name>}``. All macros are
- evaluated in the context of the preset being used, even if the macro is in a
- field that was inherited from another preset. For example, if the ``Base``
- preset sets variable ``PRESET_NAME`` to ``${presetName}``, and the
- ``Derived`` preset inherits from ``Base``, ``PRESET_NAME`` will be set to
- ``Derived``.
+As mentioned above, some fields support macro expansion. Macros are
+recognized in the form ``$<macro-namespace>{<macro-name>}``. All macros are
+evaluated in the context of the preset being used, even if the macro is in a
+field that was inherited from another preset. For example, if the ``Base``
+preset sets variable ``PRESET_NAME`` to ``${presetName}``, and the
+``Derived`` preset inherits from ``Base``, ``PRESET_NAME`` will be set to
+``Derived``.
- It is an error to not put a closing brace at the end of a macro name. For
- example, ``${sourceDir`` is invalid. A dollar sign (``$``) followed by
- anything other than a left curly brace (``{``) with a possible namespace is
- interpreted as a literal dollar sign.
+It is an error to not put a closing brace at the end of a macro name. For
+example, ``${sourceDir`` is invalid. A dollar sign (``$``) followed by
+anything other than a left curly brace (``{``) with a possible namespace is
+interpreted as a literal dollar sign.
- Recognized macros include:
+Recognized macros include:
- ``${sourceDir}``
+``${sourceDir}``
- Path to the project source directory.
+ Path to the project source directory.
- ``${sourceParentDir}``
+``${sourceParentDir}``
- Path to the project source directory's parent directory.
+ Path to the project source directory's parent directory.
- ``${sourceDirName}``
+``${sourceDirName}``
- The last filename component of ``${sourceDir}``. For example, if
- ``${sourceDir}`` is ``/path/to/source``, this would be ``source``.
+ The last filename component of ``${sourceDir}``. For example, if
+ ``${sourceDir}`` is ``/path/to/source``, this would be ``source``.
- ``${presetName}``
+``${presetName}``
- Name specified in the preset's ``name`` field.
+ Name specified in the preset's ``name`` field.
- ``${generator}``
+``${generator}``
- Generator specified in the preset's ``generator`` field.
+ Generator specified in the preset's ``generator`` field. For build and
+ test presets, this will evaluate to the generator specified by
+ ``configurePreset``.
- ``${dollar}``
+``${dollar}``
- A literal dollar sign (``$``).
+ A literal dollar sign (``$``).
- ``$env{<variable-name>}``
+``$env{<variable-name>}``
- Environment variable with name ``<variable-name>``. The variable name may
- not be an empty string. If the variable is defined in the ``environment``
- field, that value is used instead of the value from the parent environment.
- If the environment variable is not defined, this evaluates as an empty
- string.
+ Environment variable with name ``<variable-name>``. The variable name may
+ not be an empty string. If the variable is defined in the ``environment``
+ field, that value is used instead of the value from the parent environment.
+ If the environment variable is not defined, this evaluates as an empty
+ string.
- Note that while Windows environment variable names are case-insensitive,
- variable names within a preset are still case-sensitive. This may lead to
- unexpected results when using inconsistent casing. For best results, keep
- the casing of environment variable names consistent.
+ Note that while Windows environment variable names are case-insensitive,
+ variable names within a preset are still case-sensitive. This may lead to
+ unexpected results when using inconsistent casing. For best results, keep
+ the casing of environment variable names consistent.
- ``$penv{<variable-name>}``
+``$penv{<variable-name>}``
- Similar to ``$env{<variable-name>}``, except that the value only comes from
- the parent environment, and never from the ``environment`` field. This
- allows you to prepend or append values to existing environment variables.
- For example, setting ``PATH`` to ``/path/to/ninja/bin:$penv{PATH}`` will
- prepend ``/path/to/ninja/bin`` to the ``PATH`` environment variable. This
- is needed because ``$env{<variable-name>}`` does not allow circular
- references.
+ Similar to ``$env{<variable-name>}``, except that the value only comes from
+ the parent environment, and never from the ``environment`` field. This
+ allows you to prepend or append values to existing environment variables.
+ For example, setting ``PATH`` to ``/path/to/ninja/bin:$penv{PATH}`` will
+ prepend ``/path/to/ninja/bin`` to the ``PATH`` environment variable. This
+ is needed because ``$env{<variable-name>}`` does not allow circular
+ references.
- ``$vendor{<macro-name>}``
+``$vendor{<macro-name>}``
- An extension point for vendors to insert their own macros. CMake will not
- be able to use presets which have a ``$vendor{<macro-name>}`` macro, and
- effectively ignores such presets. However, it will still be able to use
- other presets from the same file.
+ An extension point for vendors to insert their own macros. CMake will not
+ be able to use presets which have a ``$vendor{<macro-name>}`` macro, and
+ effectively ignores such presets. However, it will still be able to use
+ other presets from the same file.
- CMake does not make any attempt to interpret ``$vendor{<macro-name>}``
- macros. However, to avoid name collisions, IDE vendors should prefix
- ``<macro-name>`` with a very short (preferably <= 4 characters) vendor
- identifier prefix, followed by a ``.``, followed by the macro name. For
- example, the Example IDE could have ``$vendor{xide.ideInstallDir}``.
+ CMake does not make any attempt to interpret ``$vendor{<macro-name>}``
+ macros. However, to avoid name collisions, IDE vendors should prefix
+ ``<macro-name>`` with a very short (preferably <= 4 characters) vendor
+ identifier prefix, followed by a ``.``, followed by the macro name. For
+ example, the Example IDE could have ``$vendor{xide.ideInstallDir}``.
Schema
======
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 5c8a05a0e..af170dabd 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -196,6 +196,7 @@ Properties on Targets
/prop_tgt/EXCLUDE_FROM_ALL
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG
+ /prop_tgt/EXPORT_COMPILE_COMMANDS
/prop_tgt/EXPORT_NAME
/prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER
@@ -354,6 +355,7 @@ Properties on Targets
/prop_tgt/UNITY_BUILD_CODE_AFTER_INCLUDE
/prop_tgt/UNITY_BUILD_CODE_BEFORE_INCLUDE
/prop_tgt/UNITY_BUILD_MODE
+ /prop_tgt/UNITY_BUILD_UNIQUE_ID
/prop_tgt/VERSION
/prop_tgt/VISIBILITY_INLINES_HIDDEN
/prop_tgt/VS_CONFIGURATION_TYPE
@@ -397,6 +399,10 @@ Properties on Targets
/prop_tgt/WIN32_EXECUTABLE
/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS
/prop_tgt/XCODE_ATTRIBUTE_an-attribute
+ /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_PATH
/prop_tgt/XCODE_EXPLICIT_FILE_TYPE
/prop_tgt/XCODE_GENERATE_SCHEME
/prop_tgt/XCODE_LINK_BUILD_PHASE_MODE
diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst
index d8d61729e..f156f9587 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -48,6 +48,8 @@ and ``rcc`` for virtual file system content generation. These tools may be
automatically invoked by :manual:`cmake(1)` if the appropriate conditions
are met. The automatic tool invocation may be used with both Qt 4 and Qt 5.
+.. _`Qt AUTOMOC`:
+
AUTOMOC
^^^^^^^
@@ -77,8 +79,9 @@ automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
Not included ``moc_<basename>.cpp`` files will be generated in custom
folders to avoid name collisions and included in a separate
-``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp`` file which is compiled
-into the target.
+file which is compiled into the target, named either
+``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp`` or
+``<AUTOGEN_BUILD_DIR>/mocs_compilation_$<CONFIG>.cpp``.
* See :prop_tgt:`AUTOGEN_BUILD_DIR`.
diff --git a/Help/manual/cmake-server.7.rst b/Help/manual/cmake-server.7.rst
index 8f10b9f0e..6c8d0f446 100644
--- a/Help/manual/cmake-server.7.rst
+++ b/Help/manual/cmake-server.7.rst
@@ -3,742 +3,5 @@
cmake-server(7)
***************
-.. only:: html
-
- .. contents::
-
-.. deprecated:: 3.15
-
- This will be removed from a future version of CMake.
- Clients should use the :manual:`cmake-file-api(7)` instead.
-
-Introduction
-============
-
-:manual:`cmake(1)` is capable of providing semantic information about
-CMake code it executes to generate a buildsystem. If executed with
-the ``-E server`` command line options, it starts in a long running mode
-and allows a client to request the available information via a JSON protocol.
-
-The protocol is designed to be useful to IDEs, refactoring tools, and
-other tools which have a need to understand the buildsystem in entirety.
-
-A single :manual:`cmake-buildsystem(7)` may describe buildsystem contents
-and build properties which differ based on
-:manual:`generation-time context <cmake-generator-expressions(7)>`
-including:
-
-* The Platform (eg, Windows, APPLE, Linux).
-* The build configuration (eg, Debug, Release, Coverage).
-* The Compiler (eg, MSVC, GCC, Clang) and compiler version.
-* The language of the source files compiled.
-* Available compile features (eg CXX variadic templates).
-* CMake policies.
-
-The protocol aims to provide information to tooling to satisfy several
-needs:
-
-#. Provide a complete and easily parsed source of all information relevant
- to the tooling as it relates to the source code. There should be no need
- for tooling to parse generated buildsystems to access include directories
- or compile definitions for example.
-#. Semantic information about the CMake buildsystem itself.
-#. Provide a stable interface for reading the information in the CMake cache.
-#. Information for determining when cmake needs to be re-run as a result of
- file changes.
-
-
-Operation
-=========
-
-Start :manual:`cmake(1)` in the server command mode, supplying the path to
-the build directory to process::
-
- cmake -E server (--debug|--pipe=<NAMED_PIPE>)
-
-The server will communicate using stdin/stdout (with the ``--debug`` parameter)
-or using a named pipe (with the ``--pipe=<NAMED_PIPE>`` parameter). Note
-that "named pipe" refers to a local domain socket on Unix and to a named pipe
-on Windows.
-
-When connecting to the server (via named pipe or by starting it in ``--debug``
-mode), the server will reply with a hello message::
-
- [== "CMake Server" ==[
- {"supportedProtocolVersions":[{"major":1,"minor":0}],"type":"hello"}
- ]== "CMake Server" ==]
-
-Messages sent to and from the process are wrapped in magic strings::
-
- [== "CMake Server" ==[
- {
- ... some JSON message ...
- }
- ]== "CMake Server" ==]
-
-The server is now ready to accept further requests via the named pipe
-or stdin.
-
-
-Debugging
-=========
-
-CMake server mode can be asked to provide statistics on execution times, etc.
-or to dump a copy of the response into a file. This is done passing a "debug"
-JSON object as a child of the request.
-
-The debug object supports the "showStats" key, which takes a boolean and makes
-the server mode return a "zzzDebug" object with stats as part of its response.
-"dumpToFile" takes a string value and will cause the cmake server to copy
-the response into the given filename.
-
-This is a response from the cmake server with "showStats" set to true::
-
- [== "CMake Server" ==[
- {
- "cookie":"",
- "errorMessage":"Waiting for type \"handshake\".",
- "inReplyTo":"unknown",
- "type":"error",
- "zzzDebug": {
- "dumpFile":"/tmp/error.txt",
- "jsonSerialization":0.011016,
- "size":111,
- "totalTime":0.025995
- }
- }
- ]== "CMake Server" ==]
-
-The server has made a copy of this response into the file /tmp/error.txt and
-took 0.011 seconds to turn the JSON response into a string, and it took 0.025
-seconds to process the request in total. The reply has a size of 111 bytes.
-
-
-Protocol API
-============
-
-
-General Message Layout
-----------------------
-
-All messages need to have a "type" value, which identifies the type of
-message that is passed back or forth. E.g. the initial message sent by the
-server is of type "hello". Messages without a type will generate an response
-of type "error".
-
-All requests sent to the server may contain a "cookie" value. This value
-will he handed back unchanged in all responses triggered by the request.
-
-All responses will contain a value "inReplyTo", which may be empty in
-case of parse errors, but will contain the type of the request message
-in all other cases.
-
-
-Type "reply"
-^^^^^^^^^^^^
-
-This type is used by the server to reply to requests.
-
-The message may -- depending on the type of the original request --
-contain values.
-
-Example::
-
- [== "CMake Server" ==[
- {"cookie":"zimtstern","inReplyTo":"handshake","type":"reply"}
- ]== "CMake Server" ==]
-
-
-Type "error"
-^^^^^^^^^^^^
-
-This type is used to return an error condition to the client. It will
-contain an "errorMessage".
-
-Example::
-
- [== "CMake Server" ==[
- {"cookie":"","errorMessage":"Protocol version not supported.","inReplyTo":"handshake","type":"error"}
- ]== "CMake Server" ==]
-
-
-Type "progress"
-^^^^^^^^^^^^^^^
-
-When the server is busy for a long time, it is polite to send back replies of
-type "progress" to the client. These will contain a "progressMessage" with a
-string describing the action currently taking place as well as
-"progressMinimum", "progressMaximum" and "progressCurrent" with integer values
-describing the range of progress.
-
-Messages of type "progress" will be followed by more "progress" messages or with
-a message of type "reply" or "error" that complete the request.
-
-"progress" messages may not be emitted after the "reply" or "error" message for
-the request that triggered the responses was delivered.
-
-
-Type "message"
-^^^^^^^^^^^^^^
-
-A message is triggered when the server processes a request and produces some
-form of output that should be displayed to the user. A Message has a "message"
-with the actual text to display as well as a "title" with a suggested dialog
-box title.
-
-Example::
-
- [== "CMake Server" ==[
- {"cookie":"","message":"Something happened.","title":"Title Text","inReplyTo":"handshake","type":"message"}
- ]== "CMake Server" ==]
-
-
-Type "signal"
-^^^^^^^^^^^^^
-
-The server can send signals when it detects changes in the system state. Signals
-are of type "signal", have an empty "cookie" and "inReplyTo" field and always
-have a "name" set to show which signal was sent.
-
-
-Specific Signals
-----------------
-
-The cmake server may sent signals with the following names:
-
-"dirty" Signal
-^^^^^^^^^^^^^^
-
-The "dirty" signal is sent whenever the server determines that the configuration
-of the project is no longer up-to-date. This happens when any of the files that have
-an influence on the build system is changed.
-
-The "dirty" signal may look like this::
-
- [== "CMake Server" ==[
- {
- "cookie":"",
- "inReplyTo":"",
- "name":"dirty",
- "type":"signal"}
- ]== "CMake Server" ==]
-
-
-"fileChange" Signal
-^^^^^^^^^^^^^^^^^^^
-
-The "fileChange" signal is sent whenever a watched file is changed. It contains
-the "path" that has changed and a list of "properties" with the kind of change
-that was detected. Possible changes are "change" and "rename".
-
-The "fileChange" signal looks like this::
-
- [== "CMake Server" ==[
- {
- "cookie":"",
- "inReplyTo":"",
- "name":"fileChange",
- "path":"/absolute/CMakeLists.txt",
- "properties":["change"],
- "type":"signal"}
- ]== "CMake Server" ==]
-
-
-Specific Message Types
-----------------------
-
-
-Type "hello"
-^^^^^^^^^^^^
-
-The initial message send by the cmake server on startup is of type "hello".
-This is the only message ever sent by the server that is not of type "reply",
-"progress" or "error".
-
-It will contain "supportedProtocolVersions" with an array of server protocol
-versions supported by the cmake server. These are JSON objects with "major" and
-"minor" keys containing non-negative integer values. Some versions may be marked
-as experimental. These will contain the "isExperimental" key set to true. Enabling
-these requires a special command line argument when starting the cmake server mode.
-
-Within a "major" version all "minor" versions are fully backwards compatible.
-New "minor" versions may introduce functionality in such a way that existing
-clients of the same "major" version will continue to work, provided they
-ignore keys in the output that they do not know about.
-
-Example::
-
- [== "CMake Server" ==[
- {"supportedProtocolVersions":[{"major":0,"minor":1}],"type":"hello"}
- ]== "CMake Server" ==]
-
-
-Type "handshake"
-^^^^^^^^^^^^^^^^
-
-The first request that the client may send to the server is of type "handshake".
-
-This request needs to pass one of the "supportedProtocolVersions" of the "hello"
-type response received earlier back to the server in the "protocolVersion" field.
-Giving the "major" version of the requested protocol version will make the server
-use the latest minor version of that protocol. Use this if you do not explicitly
-need to depend on a specific minor version.
-
-Protocol version 1.0 requires the following attributes to be set:
-
- * "sourceDirectory" with a path to the sources
- * "buildDirectory" with a path to the build directory
- * "generator" with the generator name
- * "extraGenerator" (optional!) with the extra generator to be used
- * "platform" with the generator platform (if supported by the generator)
- * "toolset" with the generator toolset (if supported by the generator)
-
-Protocol version 1.2 makes all but the build directory optional, provided
-there is a valid cache in the build directory that contains all the other
-information already.
-
-Example::
-
- [== "CMake Server" ==[
- {"cookie":"zimtstern","type":"handshake","protocolVersion":{"major":0},
- "sourceDirectory":"/home/code/cmake", "buildDirectory":"/tmp/testbuild",
- "generator":"Ninja"}
- ]== "CMake Server" ==]
-
-which will result in a response type "reply"::
-
- [== "CMake Server" ==[
- {"cookie":"zimtstern","inReplyTo":"handshake","type":"reply"}
- ]== "CMake Server" ==]
-
-indicating that the server is ready for action.
-
-
-Type "globalSettings"
-^^^^^^^^^^^^^^^^^^^^^
-
-This request can be sent after the initial handshake. It will return a
-JSON structure with information on cmake state.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"globalSettings"}
- ]== "CMake Server" ==]
-
-which will result in a response type "reply"::
-
- [== "CMake Server" ==[
- {
- "buildDirectory": "/tmp/test-build",
- "capabilities": {
- "generators": [
- {
- "extraGenerators": [],
- "name": "Watcom WMake",
- "platformSupport": false,
- "toolsetSupport": false
- },
- <...>
- ],
- "serverMode": false,
- "version": {
- "isDirty": false,
- "major": 3,
- "minor": 6,
- "patch": 20160830,
- "string": "3.6.20160830-gd6abad",
- "suffix": "gd6abad"
- }
- },
- "checkSystemVars": false,
- "cookie": "",
- "extraGenerator": "",
- "generator": "Ninja",
- "debugOutput": false,
- "inReplyTo": "globalSettings",
- "sourceDirectory": "/home/code/cmake",
- "trace": false,
- "traceExpand": false,
- "type": "reply",
- "warnUninitialized": false,
- "warnUnused": false,
- "warnUnusedCli": true
- }
- ]== "CMake Server" ==]
-
-
-Type "setGlobalSettings"
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-This request can be sent to change the global settings attributes. Unknown
-attributes are going to be ignored. Read-only attributes reported by
-"globalSettings" are all capabilities, buildDirectory, generator,
-extraGenerator and sourceDirectory. Any attempt to set these will be ignored,
-too.
-
-All other settings will be changed.
-
-The server will respond with an empty reply message or an error.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"setGlobalSettings","debugOutput":true}
- ]== "CMake Server" ==]
-
-CMake will reply to this with::
-
- [== "CMake Server" ==[
- {"inReplyTo":"setGlobalSettings","type":"reply"}
- ]== "CMake Server" ==]
-
-
-Type "configure"
-^^^^^^^^^^^^^^^^
-
-This request will configure a project for build.
-
-To configure a build directory already containing cmake files, it is enough to
-set "buildDirectory" via "setGlobalSettings". To create a fresh build directory
-you also need to set "currentGenerator" and "sourceDirectory" via "setGlobalSettings"
-in addition to "buildDirectory".
-
-You may a list of strings to "configure" via the "cacheArguments" key. These
-strings will be interpreted similar to command line arguments related to
-cache handling that are passed to the cmake command line client.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"configure", "cacheArguments":["-Dsomething=else"]}
- ]== "CMake Server" ==]
-
-CMake will reply like this (after reporting progress for some time)::
-
- [== "CMake Server" ==[
- {"cookie":"","inReplyTo":"configure","type":"reply"}
- ]== "CMake Server" ==]
-
-
-Type "compute"
-^^^^^^^^^^^^^^
-
-This request will generate build system files in the build directory and
-is only available after a project was successfully "configure"d.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"compute"}
- ]== "CMake Server" ==]
-
-CMake will reply (after reporting progress information)::
-
- [== "CMake Server" ==[
- {"cookie":"","inReplyTo":"compute","type":"reply"}
- ]== "CMake Server" ==]
-
-
-Type "codemodel"
-^^^^^^^^^^^^^^^^
-
-The "codemodel" request can be used after a project was "compute"d successfully.
-
-It will list the complete project structure as it is known to cmake.
-
-The reply will contain a key "configurations", which will contain a list of
-configuration objects. Configuration objects are used to destinquish between
-different configurations the build directory might have enabled. While most
-generators only support one configuration, others might support several.
-
-Each configuration object can have the following keys:
-
-"name"
- contains the name of the configuration. The name may be empty.
-"projects"
- contains a list of project objects, one for each build project.
-
-Project objects define one (sub-)project defined in the cmake build system.
-
-Each project object can have the following keys:
-
-"name"
- contains the (sub-)projects name.
-"minimumCMakeVersion"
- contains the minimum cmake version allowed for this project, null if the
- project doesn't specify one.
-"hasInstallRule"
- true if the project contains any install rules, false otherwise.
-"sourceDirectory"
- contains the current source directory
-"buildDirectory"
- contains the current build directory.
-"targets"
- contains a list of build system target objects.
-
-Target objects define individual build targets for a certain configuration.
-
-Each target object can have the following keys:
-
-"name"
- contains the name of the target.
-"type"
- defines the type of build of the target. Possible values are
- "STATIC_LIBRARY", "MODULE_LIBRARY", "SHARED_LIBRARY", "OBJECT_LIBRARY",
- "EXECUTABLE", "UTILITY" and "INTERFACE_LIBRARY".
-"fullName"
- contains the full name of the build result (incl. extensions, etc.).
-"sourceDirectory"
- contains the current source directory.
-"buildDirectory"
- contains the current build directory.
-"isGeneratorProvided"
- true if the target is auto-created by a generator, false otherwise
-"hasInstallRule"
- true if the target contains any install rules, false otherwise.
-"installPaths"
- full path to the destination directories defined by target install rules.
-"artifacts"
- with a list of build artifacts. The list is sorted with the most
- important artifacts first (e.g. a .DLL file is listed before a
- .PDB file on windows).
-"linkerLanguage"
- contains the language of the linker used to produce the artifact.
-"linkLibraries"
- with a list of libraries to link to. This value is encoded in the
- system's native shell format.
-"linkFlags"
- with a list of flags to pass to the linker. This value is encoded in
- the system's native shell format.
-"linkLanguageFlags"
- with the flags for a compiler using the linkerLanguage. This value is
- encoded in the system's native shell format.
-"frameworkPath"
- with the framework path (on Apple computers). This value is encoded
- in the system's native shell format.
-"linkPath"
- with the link path. This value is encoded in the system's native shell
- format.
-"sysroot"
- with the sysroot path.
-"fileGroups"
- contains the source files making up the target.
-
-FileGroups are used to group sources using similar settings together.
-
-Each fileGroup object may contain the following keys:
-
-"language"
- contains the programming language used by all files in the group.
-"compileFlags"
- with a string containing all the flags passed to the compiler
- when building any of the files in this group. This value is encoded in
- the system's native shell format.
-"includePath"
- with a list of include paths. Each include path is an object
- containing a "path" with the actual include path and "isSystem" with a bool
- value informing whether this is a normal include or a system include. This
- value is encoded in the system's native shell format.
-"defines"
- with a list of defines in the form "SOMEVALUE" or "SOMEVALUE=42". This
- value is encoded in the system's native shell format.
-"sources"
- with a list of source files.
-
-All file paths in the fileGroup are either absolute or relative to the
-sourceDirectory of the target.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"codemodel"}
- ]== "CMake Server" ==]
-
-CMake will reply::
-
- [== "CMake Server" ==[
- {
- "configurations": [
- {
- "name": "",
- "projects": [
- {
- "buildDirectory": "/tmp/build/Source/CursesDialog/form",
- "name": "CMAKE_FORM",
- "sourceDirectory": "/home/code/src/cmake/Source/CursesDialog/form",
- "targets": [
- {
- "artifacts": [ "/tmp/build/Source/CursesDialog/form/libcmForm.a" ],
- "buildDirectory": "/tmp/build/Source/CursesDialog/form",
- "fileGroups": [
- {
- "compileFlags": " -std=gnu11",
- "defines": [ "CURL_STATICLIB", "LIBARCHIVE_STATIC" ],
- "includePath": [ { "path": "/tmp/build/Utilities" }, <...> ],
- "isGenerated": false,
- "language": "C",
- "sources": [ "fld_arg.c", <...> ]
- }
- ],
- "fullName": "libcmForm.a",
- "linkerLanguage": "C",
- "name": "cmForm",
- "sourceDirectory": "/home/code/src/cmake/Source/CursesDialog/form",
- "type": "STATIC_LIBRARY"
- }
- ]
- },
- <...>
- ]
- }
- ],
- "cookie": "",
- "inReplyTo": "codemodel",
- "type": "reply"
- }
- ]== "CMake Server" ==]
-
-
-Type "ctestInfo"
-^^^^^^^^^^^^^^^^
-
-The "ctestInfo" request can be used after a project was "compute"d successfully.
-
-It will list the complete project test structure as it is known to cmake.
-
-The reply will contain a key "configurations", which will contain a list of
-configuration objects. Configuration objects are used to destinquish between
-different configurations the build directory might have enabled. While most
-generators only support one configuration, others might support several.
-
-Each configuration object can have the following keys:
-
-"name"
- contains the name of the configuration. The name may be empty.
-"projects"
- contains a list of project objects, one for each build project.
-
-Project objects define one (sub-)project defined in the cmake build system.
-
-Each project object can have the following keys:
-
-"name"
- contains the (sub-)projects name.
-"ctestInfo"
- contains a list of test objects.
-
-Each test object can have the following keys:
-
-"ctestName"
- contains the name of the test.
-"ctestCommand"
- contains the test command.
-"properties"
- contains a list of test property objects.
-
-Each test property object can have the following keys:
-
-"key"
- contains the test property key.
-"value"
- contains the test property value.
-
-
-Type "cmakeInputs"
-^^^^^^^^^^^^^^^^^^
-
-The "cmakeInputs" requests will report files used by CMake as part
-of the build system itself.
-
-This request is only available after a project was successfully
-"configure"d.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"cmakeInputs"}
- ]== "CMake Server" ==]
-
-CMake will reply with the following information::
-
- [== "CMake Server" ==[
- {"buildFiles":
- [
- {"isCMake":true,"isTemporary":false,"sources":["/usr/lib/cmake/...", ... ]},
- {"isCMake":false,"isTemporary":false,"sources":["CMakeLists.txt", ...]},
- {"isCMake":false,"isTemporary":true,"sources":["/tmp/build/CMakeFiles/...", ...]}
- ],
- "cmakeRootDirectory":"/usr/lib/cmake",
- "sourceDirectory":"/home/code/src/cmake",
- "cookie":"",
- "inReplyTo":"cmakeInputs",
- "type":"reply"
- }
- ]== "CMake Server" ==]
-
-All file names are either relative to the top level source directory or
-absolute.
-
-The list of files which "isCMake" set to true are part of the cmake installation.
-
-The list of files witch "isTemporary" set to true are part of the build directory
-and will not survive the build directory getting cleaned out.
-
-
-Type "cache"
-^^^^^^^^^^^^
-
-The "cache" request will list the cached configuration values.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"cache"}
- ]== "CMake Server" ==]
-
-CMake will respond with the following output::
-
- [== "CMake Server" ==[
- {
- "cookie":"","inReplyTo":"cache","type":"reply",
- "cache":
- [
- {
- "key":"SOMEVALUE",
- "properties":
- {
- "ADVANCED":"1",
- "HELPSTRING":"This is not helpful"
- }
- "type":"STRING",
- "value":"TEST"}
- ]
- }
- ]== "CMake Server" ==]
-
-The output can be limited to a list of keys by passing an array of key names
-to the "keys" optional field of the "cache" request.
-
-
-Type "fileSystemWatchers"
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The server can watch the filesystem for changes. The "fileSystemWatchers"
-command will report on the files and directories watched.
-
-Example::
-
- [== "CMake Server" ==[
- {"type":"fileSystemWatchers"}
- ]== "CMake Server" ==]
-
-CMake will respond with the following output::
-
- [== "CMake Server" ==[
- {
- "cookie":"","inReplyTo":"fileSystemWatchers","type":"reply",
- "watchedFiles": [ "/absolute/path" ],
- "watchedDirectories": [ "/absolute" ]
- }
- ]== "CMake Server" ==]
+The :manual:`cmake(1)` server mode has been removed since CMake 3.20.
+Clients should use the :manual:`cmake-file-api(7)` instead.
diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst
index 88cddf642..1ededee18 100644
--- a/Help/manual/cmake-toolchains.7.rst
+++ b/Help/manual/cmake-toolchains.7.rst
@@ -359,6 +359,10 @@ CMake uses the following steps to select one of the environments:
* Else, an error diagnostic will be issued that neither the NDK or
Standalone Toolchain can be found.
+.. versionadded:: 3.20
+ If an Android NDK is selected, its version number is reported
+ in the :variable:`CMAKE_ANDROID_NDK_VERSION` variable.
+
.. _`Cross Compiling for Android with the NDK`:
Cross Compiling for Android with the NDK
@@ -386,7 +390,8 @@ Configure use of an Android NDK with the following variables:
:variable:`CMAKE_ANDROID_ARCH_ABI`
Set to the Android ABI (architecture). If not specified, this
- variable will default to ``armeabi``.
+ variable will default to the first supported ABI in the list of
+ ``armeabi``, ``armeabi-v7a`` and ``arm64-v8a``.
The :variable:`CMAKE_ANDROID_ARCH` variable will be computed
from ``CMAKE_ANDROID_ARCH_ABI`` automatically.
Also see the :variable:`CMAKE_ANDROID_ARM_MODE` and
@@ -394,7 +399,6 @@ Configure use of an Android NDK with the following variables:
:variable:`CMAKE_ANDROID_NDK`
Set to the absolute path to the Android NDK root directory.
- A ``${CMAKE_ANDROID_NDK}/platforms`` directory must exist.
If not specified, a default for this variable will be chosen
as specified :ref:`above <Cross Compiling for Android>`.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 56239ac73..4317dd407 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -278,6 +278,7 @@ Variables that Describe the System
/variable/ANDROID
/variable/APPLE
/variable/BORLAND
+ /variable/CMAKE_ANDROID_NDK_VERSION
/variable/CMAKE_CL_64
/variable/CMAKE_COMPILER_2005
/variable/CMAKE_HOST_APPLE
@@ -336,6 +337,7 @@ Variables that Control the Build
/variable/CMAKE_ANDROID_ARM_MODE
/variable/CMAKE_ANDROID_ARM_NEON
/variable/CMAKE_ANDROID_ASSETS_DIRECTORIES
+ /variable/CMAKE_ANDROID_EXCEPTIONS
/variable/CMAKE_ANDROID_GUI
/variable/CMAKE_ANDROID_JAR_DEPENDENCIES
/variable/CMAKE_ANDROID_JAR_DIRECTORIES
@@ -349,6 +351,7 @@ Variables that Control the Build
/variable/CMAKE_ANDROID_PROCESS_MAX
/variable/CMAKE_ANDROID_PROGUARD
/variable/CMAKE_ANDROID_PROGUARD_CONFIG_PATH
+ /variable/CMAKE_ANDROID_RTTI
/variable/CMAKE_ANDROID_SECURE_PROPS_PATH
/variable/CMAKE_ANDROID_SKIP_ANT_STEP
/variable/CMAKE_ANDROID_STANDALONE_TOOLCHAIN
@@ -386,6 +389,7 @@ Variables that Control the Build
/variable/CMAKE_DEFAULT_BUILD_TYPE
/variable/CMAKE_DEFAULT_CONFIGS
/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS
+ /variable/CMAKE_DEPENDS_USE_COMPILER
/variable/CMAKE_ENABLE_EXPORTS
/variable/CMAKE_EXE_LINKER_FLAGS
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
@@ -467,6 +471,7 @@ Variables that Control the Build
/variable/CMAKE_TRY_COMPILE_TARGET_TYPE
/variable/CMAKE_UNITY_BUILD
/variable/CMAKE_UNITY_BUILD_BATCH_SIZE
+ /variable/CMAKE_UNITY_BUILD_UNIQUE_ID
/variable/CMAKE_USE_RELATIVE_PATHS
/variable/CMAKE_VISIBILITY_INLINES_HIDDEN
/variable/CMAKE_VS_GLOBALS
@@ -523,6 +528,7 @@ Variables for Languages
/variable/CMAKE_LANG_ARCHIVE_APPEND
/variable/CMAKE_LANG_ARCHIVE_CREATE
/variable/CMAKE_LANG_ARCHIVE_FINISH
+ /variable/CMAKE_LANG_BYTE_ORDER
/variable/CMAKE_LANG_COMPILER
/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN
/variable/CMAKE_LANG_COMPILER_ID
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 921f5c424..157ea5f9d 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -377,12 +377,13 @@ Options
about:tracing tab of Google Chrome or using a plugin for a tool like Trace
Compass.
-``--preset=<preset>``
+``--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 :manual:`CMake GUI <cmake-gui(1)>` can
+ 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)`.
@@ -392,6 +393,10 @@ Options
a variable called ``MYVAR`` to ``1``, but the user sets it to ``2`` with a
``-D`` argument, the value ``2`` is preferred.
+``--list-presets, --list-presets=<[configure | build | test | all]>``
+ Lists the available presets. If no option is specified only configure presets
+ will be listed. The current working directory must contain CMake preset files.
+
.. _`Build Tool Mode`:
Build a Project
@@ -402,13 +407,24 @@ project binary tree:
.. code-block:: shell
- cmake --build <dir> [<options>] [-- <build-tool-options>]
+ cmake --build [<dir> | --preset <preset>] [<options>] [-- <build-tool-options>]
This abstracts a native build tool's command-line interface with the
following options:
``--build <dir>``
- Project binary directory to be built. This is required and must be first.
+ Project binary directory to be built. This is required (unless a preset
+ is specified) and must be first.
+
+``--preset <preset>``, ``--preset=<preset>``
+ Use a build preset to specify build options. The project binary directory
+ is inferred from the ``configurePreset`` key. The current working directory
+ must contain CMake preset files.
+ See :manual:`preset <cmake-presets(7)>` for more details.
+
+``--list-presets``
+ Lists the available build presets. The current working directory must
+ contain CMake preset files.
``--parallel [<jobs>], -j [<jobs>]``
The maximum number of concurrent processes to use when building.
@@ -580,6 +596,7 @@ Available commands are:
``serverMode``
``true`` if cmake supports server-mode and ``false`` otherwise.
+ Always false since CMake 3.20.
``cat <files>...``
Concatenate files and print on the standard output.
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 00df24b38..175359d6c 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -25,9 +25,21 @@ CMake-generated build trees created for projects that use the
:command:`enable_testing` and :command:`add_test` commands have testing support.
This program will run the tests and report results.
+.. _`CTest Options`:
+
Options
=======
+``--preset <preset>``, ``--preset=<preset>``
+ Use a test preset to specify test options. The project binary directory
+ is inferred from the ``configurePreset`` key. The current working directory
+ must contain CMake preset files.
+ See :manual:`preset <cmake-presets(7)>` for more details.
+
+``--list-presets``
+ Lists the available test presets. The current working directory must contain
+ CMake preset files.
+
``-C <cfg>, --build-config <cfg>``
Choose configuration to test.
@@ -324,6 +336,9 @@ Options
``--build-and-test``
See `Build and Test Mode`_.
+``--test-dir <dir>``
+Specify the directory in which to look for tests.
+
``--test-output-size-passed <size>``
Limit the output for passed tests to ``<size>`` bytes.
diff --git a/Help/manual/presets/example.json b/Help/manual/presets/example.json
index d3b6f4a6a..dfc2910a2 100644
--- a/Help/manual/presets/example.json
+++ b/Help/manual/presets/example.json
@@ -1,8 +1,8 @@
{
- "version": 1,
+ "version": 2,
"cmakeMinimumRequired": {
"major": 3,
- "minor": 19,
+ "minor": 20,
"patch": 0
},
"configurePresets": [
@@ -37,6 +37,20 @@
"generator": "Ninja Multi-Config"
}
],
+ "buildPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "default",
+ "configurePreset": "default",
+ "output": {"outputOnFailure": true},
+ "execution": {"noTestsAction": "error", "stopOnFailure": true}
+ }
+ ],
"vendor": {
"example.com/ExampleIDE/1.0": {
"autoFormat": false
diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json
index 57b063ea8..f8faf3dd7 100644
--- a/Help/manual/presets/schema.json
+++ b/Help/manual/presets/schema.json
@@ -2,13 +2,38 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "The presets specify the generator and the build directory, and optionally a list of variables and other arguments to pass to CMake.",
- "properties": {
- "version": {
- "type": "integer",
- "description": "A required integer representing the version of the JSON schema. Currently, the only supported version is 1.",
- "minimum": 1,
- "maximum": 1
+ "oneOf": [
+ {
+ "properties": {
+ "version": {
+ "const": 1,
+ "description": "A required integer representing the version of the JSON schema."
+ },
+ "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"},
+ "vendor": { "$ref": "#/definitions/vendor" },
+ "configurePresets": { "$ref": "#/definitions/configurePresets"}
+ },
+ "additionalProperties": false
},
+ {
+ "properties": {
+ "version": {
+ "const": 2,
+ "description": "A required integer representing the version of the JSON schema."
+ },
+ "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"},
+ "vendor": { "$ref": "#/definitions/vendor" },
+ "configurePresets": { "$ref": "#/definitions/configurePresets"},
+ "buildPresets": { "$ref": "#/definitions/buildPresets"},
+ "testPresets": { "$ref": "#/definitions/testPresets"}
+ },
+ "additionalProperties": false
+ }
+ ],
+ "required": [
+ "version"
+ ],
+ "definitions": {
"cmakeMinimumRequired": {
"type": "object",
"description": "An optional object representing the minimum version of CMake needed to build this project.",
@@ -47,7 +72,7 @@
},
"hidden": {
"type": "boolean",
- "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset= argument, will not show up in the CMake GUI, and does not have to have a valid generator or binaryDir, even from inheritance. hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset= argument, will not show up in the CMake GUI, and does not have to have a valid generator or binaryDir, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
},
"inherits": {
"anyOf": [
@@ -58,7 +83,7 @@
},
{
"type": "array",
- "description": "An optional array of strings representing the names of presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and longDescription), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json may not inherit from presets in CMakeUserPresets.json.",
+ "description": "An optional array of strings representing the names of presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json may not inherit from presets in CMakeUserPresets.json.",
"items": {
"type": "string",
"description": "An optional string representing the name of the preset to inherit from.",
@@ -283,10 +308,444 @@
],
"additionalProperties": false
}
+ },
+ "buildPresets": {
+ "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": {
+ "name": {
+ "type": "string",
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, or test) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
+ "minLength": 1
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument, will not show up in the CMake GUI, and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ },
+ "inherits": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string representing the name of the build preset to inherit from.",
+ "minLength": 1
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the names of build presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json may not inherit from presets in CMakeUserPresets.json.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the name of the preset to inherit from.",
+ "minLength": 1
+ }
+ }
+ ]
+ },
+ "configurePreset": {
+ "type": "string",
+ "description": "An optional string specifying the name of a configure preset to associate with this build preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset.",
+ "minLength": 1
+ },
+ "vendor": {
+ "type": "object",
+ "description": "An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the root-level vendor field. If vendors use their own per-preset vendor field, they should implement inheritance in a sensible manner when appropriate.",
+ "properties": {}
+ },
+ "displayName": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "description": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "inheritConfigureEnvironment": {
+ "type": "boolean",
+ "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited build preset environments, but before environment variables explicitly specified in this build preset."
+ },
+ "environment": {
+ "type": "object",
+ "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable."
+ }
+ ]
+ },
+ "propertyNames": {
+ "pattern": "^.+$"
+ }
+ },
+ "jobs": {
+ "type": "integer",
+ "description": "An optional integer. Equivalent to passing --parallel or -j on the command line."
+ },
+ "targets": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets."
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets.",
+ "items": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --target or -t on the command line. Vendors may ignore the targets property or hide build presets that explicitly specify targets."
+ }
+ }
+ ]
+ },
+ "configuration": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --config on the command line."
+ },
+ "cleanFirst": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --clean-first on the command line."
+ },
+ "verbose": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --verbose on the command line."
+ },
+ "nativeToolOptions": {
+ "type": "array",
+ "description": "An optional array of strings. Equivalent to passing options after -- on the command line.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing an option to pass after -- on the command line."
+ }
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "testPresets": {
+ "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": {
+ "name": {
+ "type": "string",
+ "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, or test) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.",
+ "minLength": 1
+ },
+ "hidden": {
+ "type": "boolean",
+ "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument, will not show up in the CMake GUI, and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field."
+ },
+ "inherits": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "An optional string representing the name of the test preset to inherit from.",
+ "minLength": 1
+ },
+ {
+ "type": "array",
+ "description": "An optional array of strings representing the names of test presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json may not inherit from presets in CMakeUserPresets.json.",
+ "items": {
+ "type": "string",
+ "description": "An optional string representing the name of the preset to inherit from.",
+ "minLength": 1
+ }
+ }
+ ]
+ },
+ "configurePreset": {
+ "type": "string",
+ "description": "An optional string specifying the name of a configure preset to associate with this test preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset.",
+ "minLength": 1
+ },
+ "vendor": {
+ "type": "object",
+ "description": "An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the root-level vendor field. If vendors use their own per-preset vendor field, they should implement inheritance in a sensible manner when appropriate.",
+ "properties": {}
+ },
+ "displayName": {
+ "type": "string",
+ "description": "An optional string with a human-friendly name of the preset."
+ },
+ "description": {
+ "type": "string",
+ "description": "An optional string with a human-friendly description of the preset."
+ },
+ "inheritConfigureEnvironment": {
+ "type": "boolean",
+ "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited test preset environments, but before environment variables explicitly specified in this test preset."
+ },
+ "environment": {
+ "type": "object",
+ "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.",
+ "properties": {},
+ "additionalProperties": {
+ "anyOf": [
+ {
+ "type": "null",
+ "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset."
+ },
+ {
+ "type": "string",
+ "description": "A string representing the value of the variable."
+ }
+ ]
+ },
+ "propertyNames": {
+ "pattern": "^.+$"
+ }
+ },
+ "configuration": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --build-config on the command line."
+ },
+ "overwriteConfigurationFile": {
+ "type": "array",
+ "description": "An optional array of configuration options to overwrite options specified in the CTest configuration file. Equivalent to passing ``--overwrite`` for each value in the array.",
+ "items": {
+ "type": "string",
+ "description": "An option written as a key-value pair in the form \"key=value\"."
+ }
+ },
+ "output": {
+ "type": "object",
+ "description": "An optional object specifying output options.",
+ "properties": {
+ "shortProgress": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --progress on the command line."
+ },
+ "verbosity": {
+ "type": "string",
+ "description": "An optional string specifying verbosity level. Valid values are \"default\" (equivalent to passing no verbosity flags on the command line), \"verbose\" (equivalent to passing --verbose on the command line), and \"extra\" (equivalent to passing --extra-verbose on the command line).",
+ "enum": [
+ "default", "verbose", "extra"
+ ]
+ },
+ "debug": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --debug on the command line."
+ },
+ "outputOnFailure": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --output-on-failure on the command line."
+ },
+ "quiet": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --quiet on the command line."
+ },
+ "outputLogFile": {
+ "type": "string",
+ "description": "An optional string specifying a path to a log file. Equivalent to passing --output-log on the command line."
+ },
+ "labelSummary": {
+ "type": "boolean",
+ "description": "An optional boolean. If false, equivalent to passing --no-label-summary on the command line."
+ },
+ "subprojectSummary": {
+ "type": "boolean",
+ "description": "An optional boolean. If false, equivalent to passing --no-subproject-summary on the command line."
+ },
+ "maxPassedTestOutputSize": {
+ "type": "integer",
+ "description": "An optional integer specifying the maximum output for passed tests in bytes. Equivalent to passing --test-output-size-passed on the command line."
+ },
+ "maxFailedTestOutputSize": {
+ "type": "integer",
+ "description": "An optional integer specifying the maximum output for failed tests in bytes. Equivalent to passing --test-output-size-failed on the command line."
+ },
+ "maxTestNameWidth": {
+ "type": "integer",
+ "description": "An optional integer specifying the maximum width of a test name to output. Equivalent to passing --max-width on the command line."
+ }
+ },
+ "additionalProperties": false
+ },
+ "filter": {
+ "type": "object",
+ "description": "An optional object specifying how to filter the tests to run.",
+ "properties": {
+ "include": {
+ "type": "object",
+ "description": "An optional object specifying which tests to include.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test names. Equivalent to passing --tests-regex on the command line."
+ },
+ "label": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test labels. Equivalent to passing --label-regex on the command line."
+ },
+ "index": {
+ "anyOf": [
+ {
+ "type": "object",
+ "description": "An optional object specifying tests to include by test index.",
+ "properties": {
+ "start": {
+ "type": "integer",
+ "description": "An optional integer specifying a test index to start testing at."
+ },
+ "end": {
+ "type": "integer",
+ "description": "An optional integer specifying a test index to stop testing at."
+ },
+ "stride": {
+ "type": "integer",
+ "description": "An optional integer specifying the increment."
+ },
+ "specificTests": {
+ "type": "array",
+ "description": "An optional array of integers specifying specific test indices to run.",
+ "items": {
+ "type": "integer",
+ "description": "An integer specifying the test to run by index."
+ }
+ }
+ },
+ "additionalProperties": false
+ },
+ {
+ "type": "string",
+ "description": "An optional string specifying a file with the command line syntax for --tests-information."
+ }
+ ]
+ },
+ "useUnion": {
+ "type": "boolean",
+ "description": "An optional boolean. Equivalent to passing --union on the command line."
+ }
+ },
+ "additionalProperties": false
+ },
+ "exclude": {
+ "type": "object",
+ "description": "An optional object specifying which tests to exclude.",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test names. Equivalent to passing --exclude-regex on the command line."
+ },
+ "label": {
+ "type": "string",
+ "description": "An optional string specifying a regex for test labels. Equivalent to passing --label-exclude on the command line."
+ },
+ "fixtures": {
+ "type": "object",
+ "description": "An optional object specifying which fixtures to exclude from adding tests.",
+ "properties": {
+ "any": {
+ "type": "string",
+ "description": "An optional string specifying a regex for text fixtures to exclude from adding any tests. Equivalent to --fixture-exclude-any on the command line."
+ },
+ "setup": {
+ "type": "string",
+ "description": "An optional string specifying a regex for text fixtures to exclude from adding setup tests. Equivalent to --fixture-exclude-setup on the command line."
+ },
+ "cleanup": {
+ "type": "string",
+ "description": "An optional string specifying a regex for text fixtures to exclude from adding cleanup tests. Equivalent to --fixture-exclude-cleanup on the command line."
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ },
+ "execution": {
+ "type": "object",
+ "description": "An optional object specifying options for test execution.",
+ "properties": {
+ "stopOnFailure": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --stop-on-failure on the command line."
+ },
+ "enableFailover": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing -F on the command line."
+ },
+ "jobs": {
+ "type": "integer",
+ "description": "An optional integer. Equivalent to passing --parallel on the command line."
+ },
+ "resourceSpecFile": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --resource-spec-file on the command line."
+ },
+ "testLoad": {
+ "type": "integer",
+ "description": "An optional integer. Equivalent to passing --test-load on the command line."
+ },
+ "showOnly": {
+ "type": "string",
+ "description": "An optional string. Equivalent to passing --show-only on the command line. Value must be \"human\" or \"json-v1\".",
+ "enum": [
+ "human", "json-v1"
+ ]
+ },
+ "repeat": {
+ "type": "object",
+ "description": "An optional object specifying how to repeat tests. Equivalent to passing --repeat on the command line.",
+ "properties": {
+ "mode": {
+ "type": "string",
+ "description": "A required string. Must be one of the following values: \"until-fail\", \"until-pass\", or \"after-timeout\".",
+ "enum": [
+ "until-fail", "until-pass", "after-timeout"
+ ]
+ },
+ "count": {
+ "type": "integer",
+ "description": "A required integer."
+ }
+ },
+ "required": [
+ "mode", "count"
+ ],
+ "additionalProperties": false
+ },
+ "interactiveDebugging": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --interactive-debug-mode 1 on the command line. If false, equivalent to passing --interactive-debug-mode 0 on the command line."
+ },
+ "scheduleRandom": {
+ "type": "boolean",
+ "description": "An optional boolean. If true, equivalent to passing --schedule-random on the command line."
+ },
+ "timeout": {
+ "type": "integer",
+ "description": "An optional integer. Equivalent to passing --timeout on the command line."
+ },
+ "noTestsAction": {
+ "type": "string",
+ "description": "An optional string specifying the behavior if no tests are found. Must be one of the following values: \"default\" (equivalent to not passing any value on the command line), \"error\" (equivalent to passing --no-tests=error on the command line), or \"ignore\" (equivalent to passing --no-tests-ignore on the command line).",
+ "enum": [
+ "default", "error", "ignore"
+ ]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false
+ }
}
- },
- "required": [
- "version"
- ],
- "additionalProperties": false
+ }
}
diff --git a/Help/module/UseJavaClassFilelist.rst b/Help/module/UseJavaClassFilelist.rst
index b9cd4769e..29949bef8 100644
--- a/Help/module/UseJavaClassFilelist.rst
+++ b/Help/module/UseJavaClassFilelist.rst
@@ -1 +1,6 @@
-.. cmake-module:: ../../Modules/UseJavaClassFilelist.cmake
+UseJavaClassFilelist
+--------------------
+
+.. versionchanged:: 3.20
+ This module was previously documented by mistake and was never meant for
+ direct inclusion by project code. See the :module:`UseJava` module.
diff --git a/Help/module/UseJavaSymlinks.rst b/Help/module/UseJavaSymlinks.rst
index 2fab8e8dd..1058a68b3 100644
--- a/Help/module/UseJavaSymlinks.rst
+++ b/Help/module/UseJavaSymlinks.rst
@@ -1 +1,6 @@
-.. cmake-module:: ../../Modules/UseJavaSymlinks.cmake
+UseJavaSymlinks
+---------------
+
+.. versionchanged:: 3.20
+ This module was previously documented by mistake and was never meant for
+ direct inclusion by project code. See the :module:`UseJava` module.
diff --git a/Help/policy/CMP0026.rst b/Help/policy/CMP0026.rst
index 3401d4a9a..e08fd54a4 100644
--- a/Help/policy/CMP0026.rst
+++ b/Help/policy/CMP0026.rst
@@ -9,12 +9,12 @@ determine the eventual location of build targets. This relies on the
assumption that all necessary information is available at
configure-time to determine the final location and filename of the
target. However, this property is not fully determined until later at
-generate-time. At generate time, the ``$<TARGET_FILE>`` generator
+generate-time. At generate time, the :genex:`$<TARGET_FILE>` generator
expression can be used to determine the eventual :prop_tgt:`LOCATION` of a target
output.
Code which reads the :prop_tgt:`LOCATION` target property can be ported to
-use the ``$<TARGET_FILE>`` generator expression together with the
+use the :genex:`$<TARGET_FILE>` generator expression together with the
:command:`file(GENERATE)` subcommand to generate a file containing
the target location.
diff --git a/Help/policy/CMP0051.rst b/Help/policy/CMP0051.rst
index 053bc9757..3558909f7 100644
--- a/Help/policy/CMP0051.rst
+++ b/Help/policy/CMP0051.rst
@@ -3,7 +3,7 @@ CMP0051
.. versionadded:: 3.1
-List TARGET_OBJECTS in SOURCES target property.
+List :genex:`TARGET_OBJECTS` in SOURCES target property.
CMake 3.0 and lower did not include the ``TARGET_OBJECTS``
:manual:`generator expression <cmake-generator-expressions(7)>` when
diff --git a/Help/policy/CMP0115.rst b/Help/policy/CMP0115.rst
new file mode 100644
index 000000000..7f82c4326
--- /dev/null
+++ b/Help/policy/CMP0115.rst
@@ -0,0 +1,34 @@
+CMP0115
+-------
+
+.. versionadded:: 3.20
+
+Source file extensions must be explicit.
+
+In CMake 3.19 and below, if a source file could not be found by the name
+specified, it would append a list of known extensions to the name to see if
+the file with the extension could be found. For example, this would allow the
+user to run:
+
+.. code-block:: cmake
+
+ add_executable(exe main)
+
+and put ``main.c`` in the executable without specifying the extension.
+
+Starting in CMake 3.20, CMake prefers all source files to have their extensions
+explicitly listed:
+
+.. code-block:: cmake
+
+ add_executable(exe main.c)
+
+The ``OLD`` behavior for this policy is to implicitly append known extensions
+to source files if they can't be found. The ``NEW`` behavior of this policy is
+to not append known extensions and require them to be explicit.
+
+This policy was introduced in CMake version 3.20. 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/CMP0116.rst b/Help/policy/CMP0116.rst
new file mode 100644
index 000000000..18e5a96d6
--- /dev/null
+++ b/Help/policy/CMP0116.rst
@@ -0,0 +1,41 @@
+CMP0116
+-------
+
+.. versionadded:: 3.20
+
+Ninja generators transform ``DEPFILE`` s from :command:`add_custom_command`.
+
+In CMake 3.19 and below, files given to the ``DEPFILE`` argument of
+:command:`add_custom_command` were passed directly to Ninja's ``depfile``
+variable without any path resolution. This meant that if
+:command:`add_custom_command` was called from a subdirectory (created by
+:command:`add_subdirectory`), the ``DEPFILE`` argument would have to be either
+an absolute path or a path relative to :variable:`CMAKE_BINARY_DIR`, rather
+than :variable:`CMAKE_CURRENT_BINARY_DIR`. In addition, no transformation was
+done on the file listed in ``DEPFILE``, which meant that the paths within the
+``DEPFILE`` had the same restrictions.
+
+Starting with CMake 3.20, the ``DEPFILE`` argument is relative to
+:variable:`CMAKE_CURRENT_BINARY_DIR` (unless it is absolute), and the paths in
+the ``DEPFILE`` are also relative to :variable:`CMAKE_CURRENT_BINARY_DIR`.
+CMake automatically transforms the paths in the ``DEPFILE`` (unless they are
+absolute) after the custom command is run. The file listed in ``DEPFILE`` is
+not modified in any way. Instead, CMake writes the transformation to its own
+internal file, and passes this internal file to Ninja's ``depfile`` variable.
+This transformation happens regardless of whether or not ``DEPFILE`` is
+relative, and regardless of whether or not :command:`add_custom_command` is
+called from a subdirectory.
+
+The ``OLD`` behavior for this policy is to pass the ``DEPFILE`` to Ninja
+unaltered. The ``NEW`` behavior for this policy is to transform the ``DEPFILE``
+after running the custom command. The status of ``CMP0116`` is recorded at the
+time of the custom command's creation, and you can have custom commands in the
+same directory with different values for ``CMP0116`` by setting the policy
+before each custom command.
+
+This policy was introduced in CMake version 3.20. Unlike most policies,
+CMake version |release| does *not* warn by default when this policy is not set
+(unless ``DEPFILE`` is used in a subdirectory) and simply uses ``OLD``
+behavior. See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0116 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
diff --git a/Help/policy/CMP0117.rst b/Help/policy/CMP0117.rst
new file mode 100644
index 000000000..0c4dd3068
--- /dev/null
+++ b/Help/policy/CMP0117.rst
@@ -0,0 +1,43 @@
+CMP0117
+-------
+
+.. versionadded:: 3.20
+
+MSVC RTTI flag ``/GR`` is not added to
+:variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` by default.
+
+When using MSVC-like compilers in CMake 3.19 and below, the RTTI flag
+``/GR`` is added to :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` by
+default. This behavior is left from support for MSVC versions from Visual
+Studio 2003 and below that did not enable RTTI by default. It is no longer
+necessary. Furthermore, it is problematic for projects that want to change
+to ``/GR-`` programmatically. In particular, it requires string editing of
+the :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` variable with knowledge
+of the CMake builtin default so it can be replaced.
+
+CMake 3.20 and above prefer to leave out ``/GR`` from the value of
+:variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` by default.
+
+This policy provides compatibility with projects that have not been updated
+to expect the lack of the ``/GR`` flag. The policy setting takes effect as
+of the first :command:`project` or :command:`enable_language` command that
+initializes :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>`.
+
+.. note::
+
+ Once the policy has taken effect at the top of a project for a given
+ language, that choice must be used throughout the tree for that language.
+ In projects that have nested projects in subdirectories, be sure to
+ convert everything together.
+
+The ``OLD`` behavior for this policy is to place the MSVC ``/GR`` flag in the
+default :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` cache entry. The
+``NEW`` behavior for this policy is to *not* place the MSVC ``/GR`` flag in
+the default cache entry.
+
+This policy was introduced in CMake version 3.20. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0118.rst b/Help/policy/CMP0118.rst
new file mode 100644
index 000000000..aa7e0f7f8
--- /dev/null
+++ b/Help/policy/CMP0118.rst
@@ -0,0 +1,25 @@
+CMP0118
+-------
+
+.. versionadded:: 3.20
+
+The :prop_sf:`GENERATED` source file property is now visible in all directories.
+
+Whether or not a source file is generated is an all-or-nothing global
+property of the source. Consequently, the associated ``GENERATED``
+property is now visible from any directory scope, not only from the scope
+for which it was set.
+
+Additionally, the ``GENERATED`` property may now be set only to boolean
+values, and may not be turned off once turned on.
+
+The ``OLD`` behavior of this policy is to only allow ``GENERATED`` to be
+visible from the directory scope for which it was set. The ``NEW``
+behavior on the other hand allows it to be visible from any scope.
+
+This policy was introduced in CMake version 3.20. 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 with regard
+to visibility of the ``GENERATED`` property. However, CMake does warn
+about setting the ``GENERATED`` property to a non-boolean value.
diff --git a/Help/policy/CMP0119.rst b/Help/policy/CMP0119.rst
new file mode 100644
index 000000000..61c8bdc43
--- /dev/null
+++ b/Help/policy/CMP0119.rst
@@ -0,0 +1,36 @@
+CMP0119
+-------
+
+.. versionadded:: 3.20
+
+:prop_sf:`LANGUAGE` source file property explicitly compiles as specified
+language.
+
+The :prop_sf:`LANGUAGE` source file property is documented to mean that the
+source file is written in the specified language. In CMake 3.19 and below,
+setting this property causes CMake to compile the source file using the
+compiler for the specified language. However, it only passes an explicit
+flag to tell the compiler to treat the source as the specified language
+for MSVC-like, XL, and Embarcadero compilers for the ``CXX`` language.
+CMake 3.20 and above prefer to also explicitly tell the compiler to use
+the specified language using a flag such as ``-x c`` on all compilers
+for which such flags are known.
+
+This policy provides compatibility for projects that have not been updated
+to expect this behavior. For example, some projects were setting the
+``LANGUAGE`` property to ``C`` on assembly-language ``.S`` source files
+in order to compile them using the C compiler. Such projects should be
+updated to use ``enable_language(ASM)``, for which CMake will often choose
+the C compiler as the assembler on relevant platforms anyway.
+
+The ``OLD`` behavior for this policy is to interpret the ``LANGUAGE <LANG>``
+property using its undocumented meaning to "use the ``<LANG>`` compiler".
+The ``NEW`` behavior for this policy is to interpret the ``LANGUAGE <LANG>``
+property using its documented meaning to "compile as a ``<LANG>`` source".
+
+This policy was introduced in CMake version 3.20. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0120.rst b/Help/policy/CMP0120.rst
new file mode 100644
index 000000000..9d2f6c973
--- /dev/null
+++ b/Help/policy/CMP0120.rst
@@ -0,0 +1,47 @@
+CMP0120
+-------
+
+.. versionadded:: 3.20
+
+The :module:`WriteCompilerDetectionHeader` module is removed.
+
+CMake versions 3.1 through 3.19 provide this module to generate a
+C++ compatibility layer by re-using information from CMake's table of
+preprocessor checks for :manual:`cmake-compile-features(7)`. However:
+
+* Those granular features have been superseded by meta-features for
+ :ref:`Requiring Language Standards` such as ``cxx_std_11``. Therefore
+ no new granular feature checks will be added and projects will need to
+ use other means to conditionally use new C++ features.
+
+* The module exposes some of CMake's implementation details directly
+ to C++ translation units.
+
+* The module's approach effectively provides a header file with CMake,
+ thus tying the version of the header to the version of CMake.
+ Many projects found that the :module:`WriteCompilerDetectionHeader` was
+ best used by manually generating its header locally with a recent version
+ of CMake and then bundling it with the project source so that it could
+ be used with older CMake versions.
+
+For reasons including the above, CMake 3.20 and above prefer to not
+provide the :module:`WriteCompilerDetectionHeader` module. This policy
+provides compatibility for projects that have not been ported away from
+it. Projects using the module should be updated to stop using it.
+Alternatives include:
+
+* Bundle a copy of the generated header in the project's source.
+* Use a third-party alternative, such as the CC0-licensed `Hedley`_.
+* Drop support for compilers too old to provide the features natively.
+
+The ``OLD`` behavior of this policy is for inclusion of the deprecated
+:module:`WriteCompilerDetectionHeader` module to work. The ``NEW``
+behavior is for inclusion of the module to fail as if it does not exist.
+
+This policy was introduced in CMake version 3.20. 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
+
+.. _`Hedley`: https://nemequ.github.io/hedley/
diff --git a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
index e8e314881..6bbb870f1 100644
--- a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
@@ -30,3 +30,6 @@ The features known to this version of CMake are:
``cuda_std_20``
Compiler mode is at least CUDA/C++ 20.
+
+``cuda_std_23``
+ Compiler mode is at least CUDA/C++ 23.
diff --git a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
index bac32744b..73c0b34ee 100644
--- a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -37,6 +37,8 @@ but it does not necessarily imply complete conformance to that standard.
``cxx_std_20``
Compiler mode is at least C++ 20.
+``cxx_std_23``
+ Compiler mode is at least C++ 23.
Low level individual compile features
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/prop_sf/GENERATED.rst b/Help/prop_sf/GENERATED.rst
index 48ff70c7b..6ef458022 100644
--- a/Help/prop_sf/GENERATED.rst
+++ b/Help/prop_sf/GENERATED.rst
@@ -3,6 +3,9 @@ GENERATED
Is this source file generated as part of the build or CMake process.
+.. versionchanged:: 3.20
+ The GENERATED source file property is now visible in all directories.
+
Tells the internal CMake engine that a source file is generated by an outside
process such as another build step, or the execution of CMake itself.
This information is then used to exempt the file from any existence or
@@ -34,3 +37,11 @@ or :prop_tgt:`AUTORCC` functionality, the :prop_gbl:`AUTOGEN_SOURCE_GROUP`,
:prop_gbl:`AUTOMOC_SOURCE_GROUP` and :prop_gbl:`AUTORCC_SOURCE_GROUP` target
properties may influence where the generated sources are grouped in the project's
file lists.
+
+.. note::
+
+ Starting with CMake 3.20 the ``GENERATED`` source file property can be set
+ and retrieved from any directory scope. It is an all-or-nothing property.
+ It also can no longer be removed or unset if it was set to ``TRUE``. Policy
+ :policy:`CMP0118` was introduced to allow supporting the ``OLD`` behavior
+ for some time.
diff --git a/Help/prop_sf/LANGUAGE.rst b/Help/prop_sf/LANGUAGE.rst
index 1dd2554d5..f14c176ca 100644
--- a/Help/prop_sf/LANGUAGE.rst
+++ b/Help/prop_sf/LANGUAGE.rst
@@ -1,7 +1,7 @@
LANGUAGE
--------
-What programming language is the file.
+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
@@ -9,3 +9,9 @@ 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
for headers or files that should not be compiled.
+
+.. versionchanged:: 3.20
+ Setting this property causes the source file to be compiled as the
+ specified language, using explicit flags if possible. Previously it
+ only caused the specified language's compiler to be used.
+ See policy :policy:`CMP0119`.
diff --git a/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY.rst
index 42210696b..677e06df0 100644
--- a/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY.rst
+++ b/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY.rst
@@ -3,7 +3,7 @@ ARCHIVE_OUTPUT_DIRECTORY
.. |XXX| replace:: :ref:`ARCHIVE <Archive Output Artifacts>`
.. |xxx| replace:: archive
-.. |CMAKE_XXX_OUTPUT_DIRECTORY| replace:: CMAKE_ARCHIVE_OUTPUT_DIRECTORY
+.. |CMAKE_XXX_OUTPUT_DIRECTORY| replace:: :variable:`CMAKE_ARCHIVE_OUTPUT_DIRECTORY`
.. include:: XXX_OUTPUT_DIRECTORY.txt
See also the :prop_tgt:`ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>` target property.
diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index c18859b56..52d96e02f 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -137,7 +137,8 @@ parent directory path of the ``moc`` input file. This scheme allows to have
All not included ``moc`` output files will be included automatically by the
CMake generated file
-- ``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp``,
+- ``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp``, or
+- ``<AUTOGEN_BUILD_DIR>/mocs_compilation_$<CONFIG>.cpp``,
which is added to the target's sources.
diff --git a/Help/prop_tgt/CUDA_STANDARD.rst b/Help/prop_tgt/CUDA_STANDARD.rst
index fcc472568..6517035a2 100644
--- a/Help/prop_tgt/CUDA_STANDARD.rst
+++ b/Help/prop_tgt/CUDA_STANDARD.rst
@@ -9,7 +9,7 @@ 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``.
+Supported values are ``98``, ``03``, ``11``, ``14``, ``17``, ``20``, ``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 f322ffe1f..be0dab565 100644
--- a/Help/prop_tgt/CXX_STANDARD.rst
+++ b/Help/prop_tgt/CXX_STANDARD.rst
@@ -11,7 +11,7 @@ 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``, and ``20``.
+Supported values are ``98``, ``11``, ``14``, ``17``, ``20``, ``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/EXPORT_COMPILE_COMMANDS.rst b/Help/prop_tgt/EXPORT_COMPILE_COMMANDS.rst
new file mode 100644
index 000000000..0b1145c4e
--- /dev/null
+++ b/Help/prop_tgt/EXPORT_COMPILE_COMMANDS.rst
@@ -0,0 +1,9 @@
+EXPORT_COMPILE_COMMANDS
+-----------------------
+
+.. versionadded:: 3.20
+
+Enable/Disable output of compile commands during generation for a target.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_EXPORT_COMPILE_COMMANDS` if it is set when a target is created.
diff --git a/Help/prop_tgt/IMPORTED_OBJECTS.rst b/Help/prop_tgt/IMPORTED_OBJECTS.rst
index bbbcd866d..f3577eb99 100644
--- a/Help/prop_tgt/IMPORTED_OBJECTS.rst
+++ b/Help/prop_tgt/IMPORTED_OBJECTS.rst
@@ -3,11 +3,91 @@ IMPORTED_OBJECTS
.. versionadded:: 3.9
-A :ref:`semicolon-separated list <CMake Language Lists>` of absolute paths to the object
-files on disk for an :ref:`imported <Imported targets>`
+A :ref:`semicolon-separated list <CMake Language Lists>` of absolute paths
+to the object files on disk for an :ref:`imported <Imported targets>`
:ref:`object library <object libraries>`.
Ignored for non-imported targets.
Projects may skip ``IMPORTED_OBJECTS`` if the configuration-specific
-property :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` is set instead.
+property :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` is set instead, except in
+situations as noted in the section below.
+
+
+Xcode Generator Considerations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.20
+
+For Apple platforms, a project may be built for more than one architecture.
+This is controlled by the :variable:`CMAKE_OSX_ARCHITECTURES` variable.
+For all but the :generator:`Xcode` generator, CMake invokes compilers once
+per source file and passes multiple ``-arch`` flags, leading to a single
+object file which will be a universal binary. Such object files work well
+when listed in the ``IMPORTED_OBJECTS`` of a separate CMake build, even for
+the :generator:`Xcode` generator. But producing such object files with the
+:generator:`Xcode` generator is more difficult, since it invokes the compiler
+once per architecture for each source file. Unlike the other generators,
+it does not generate universal object file binaries.
+
+A further complication with the :generator:`Xcode` generator is that when
+targeting device platforms (iOS, tvOS or watchOS), the :generator:`Xcode`
+generator has the ability to use either the device or simulator SDK without
+needing CMake to be re-run. The SDK can be selected at build time.
+But since some architectures can be supported by both the device and the
+simulator SDKs (e.g. ``arm64`` with Xcode 12 or later), not all combinations
+can be represented in a single universal binary. The only solution in this
+case is to have multiple object files.
+
+``IMPORTED_OBJECTS`` doesn't support generator expressions, so every file
+it lists needs to be valid for every architecture and SDK. If incorporating
+object files that are not universal binaries, the path and/or file name of
+each object file has to somehow encapsulate the different architectures and
+SDKs. With the :generator:`Xcode` generator, Xcode variables of the form
+``$(...)`` can be used to represent these aspects and Xcode will substitute
+the appropriate values at build time. CMake doesn't interpret these
+variables and embeds them unchanged in the Xcode project file.
+``$(CURRENT_ARCH)`` can be used to represent the architecture, while
+``$(EFFECTIVE_PLATFORM_NAME)`` can be used to differentiate between SDKs.
+
+The following shows one example of how these two variables can be used to
+refer to an object file whose location depends on both the SDK and the
+architecture:
+
+.. code-block:: cmake
+
+ add_library(someObjs OBJECT IMPORTED)
+
+ set_property(TARGET someObjs PROPERTY IMPORTED_OBJECTS
+ # Quotes are required because of the ()
+ "/path/to/somewhere/objects$(EFFECTIVE_PLATFORM_NAME)/$(CURRENT_ARCH)/func.o"
+ )
+
+ # Example paths:
+ # /path/to/somewhere/objects-iphoneos/arm64/func.o
+ # /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:
+
+.. 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"
+ )
+
+ # 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)``.
diff --git a/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
index b12ca3887..238395a23 100644
--- a/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
+++ b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
@@ -3,7 +3,18 @@ IMPORTED_OBJECTS_<CONFIG>
.. versionadded:: 3.9
-<CONFIG>-specific version of :prop_tgt:`IMPORTED_OBJECTS` property.
+``<CONFIG>``-specific version of :prop_tgt:`IMPORTED_OBJECTS` property.
Configuration names correspond to those provided by the project from
which the target is imported.
+
+
+Xcode Generator Considerations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Do not use this ``<CONFIG>``-specific property if you need to use Xcode
+variables like ``$(CURRENT_ARCH)`` or ``$(EFFECTIVE_PLATFORM_NAME)`` in
+the value. The ``<CONFIG>``-specific properties will be ignored in such
+cases because CMake cannot determine whether a file exists at the
+configuration-specific path at configuration time. For such cases, use
+:prop_tgt:`IMPORTED_OBJECTS` instead.
diff --git a/Help/prop_tgt/INSTALL_NAME_DIR.rst b/Help/prop_tgt/INSTALL_NAME_DIR.rst
index 747615ac8..8faefb71c 100644
--- a/Help/prop_tgt/INSTALL_NAME_DIR.rst
+++ b/Help/prop_tgt/INSTALL_NAME_DIR.rst
@@ -12,5 +12,5 @@ This property is initialized by the value of the variable
created.
This property supports :manual:`generator expressions <cmake-generator-expressions(7)>`.
-In particular, the ``$<INSTALL_PREFIX>`` generator expression can be used to set the
-directory relative to the install-time prefix.
+In particular, the :genex:`$<INSTALL_PREFIX>` generator expression can be
+used to set the directory relative to the install-time prefix.
diff --git a/Help/prop_tgt/LANG_CLANG_TIDY.rst b/Help/prop_tgt/LANG_CLANG_TIDY.rst
index 7fc23721c..af16d3c5b 100644
--- a/Help/prop_tgt/LANG_CLANG_TIDY.rst
+++ b/Help/prop_tgt/LANG_CLANG_TIDY.rst
@@ -3,7 +3,7 @@
.. versionadded:: 3.6
-This property is implemented only when ``<LANG>`` is ``C`` or ``CXX``.
+This property is implemented only when ``<LANG>`` is ``C``, ``CXX``, ``OBJC`` or ``OBJCXX``.
Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing a command
line for the ``clang-tidy`` tool. The :ref:`Makefile Generators`
diff --git a/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY.rst
index 785a57bbf..9fbe90408 100644
--- a/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY.rst
+++ b/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY.rst
@@ -3,7 +3,7 @@ LIBRARY_OUTPUT_DIRECTORY
.. |XXX| replace:: :ref:`LIBRARY <Library Output Artifacts>`
.. |xxx| replace:: library
-.. |CMAKE_XXX_OUTPUT_DIRECTORY| replace:: CMAKE_LIBRARY_OUTPUT_DIRECTORY
+.. |CMAKE_XXX_OUTPUT_DIRECTORY| replace:: :variable:`CMAKE_LIBRARY_OUTPUT_DIRECTORY`
.. include:: XXX_OUTPUT_DIRECTORY.txt
See also the :prop_tgt:`LIBRARY_OUTPUT_DIRECTORY_<CONFIG>` target property.
diff --git a/Help/prop_tgt/OBJCXX_STANDARD.rst b/Help/prop_tgt/OBJCXX_STANDARD.rst
index 1067153e6..96088af96 100644
--- a/Help/prop_tgt/OBJCXX_STANDARD.rst
+++ b/Help/prop_tgt/OBJCXX_STANDARD.rst
@@ -9,7 +9,7 @@ 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``, and ``20``.
+Supported values are ``98``, ``11``, ``14``, ``17``, ``20``, ``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/RUNTIME_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.rst
index 12390f50a..3c375463c 100644
--- a/Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.rst
+++ b/Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.rst
@@ -3,7 +3,7 @@ RUNTIME_OUTPUT_DIRECTORY
.. |XXX| replace:: :ref:`RUNTIME <Runtime Output Artifacts>`
.. |xxx| replace:: runtime
-.. |CMAKE_XXX_OUTPUT_DIRECTORY| replace:: CMAKE_RUNTIME_OUTPUT_DIRECTORY
+.. |CMAKE_XXX_OUTPUT_DIRECTORY| replace:: :variable:`CMAKE_RUNTIME_OUTPUT_DIRECTORY`
.. include:: XXX_OUTPUT_DIRECTORY.txt
See also the :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY_<CONFIG>` target property.
diff --git a/Help/prop_tgt/UNITY_BUILD.rst b/Help/prop_tgt/UNITY_BUILD.rst
index 04cede61e..f827a20a1 100644
--- a/Help/prop_tgt/UNITY_BUILD.rst
+++ b/Help/prop_tgt/UNITY_BUILD.rst
@@ -70,6 +70,11 @@ a number of measures to help address such problems:
problems with specific files than disabling unity builds for an entire
target.
+* Projects can set :prop_tgt:`UNITY_BUILD_UNIQUE_ID` to cause a valid
+ C-identifier to be generated which is unique per file in a unity
+ build. This can be used to avoid problems with anonymous namespaces
+ in unity builds.
+
* The :prop_tgt:`UNITY_BUILD_CODE_BEFORE_INCLUDE` and
:prop_tgt:`UNITY_BUILD_CODE_AFTER_INCLUDE` target properties can be used
to inject code into the unity source files before and after every
diff --git a/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst b/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst
new file mode 100644
index 000000000..2c95e027c
--- /dev/null
+++ b/Help/prop_tgt/UNITY_BUILD_UNIQUE_ID.rst
@@ -0,0 +1,55 @@
+UNITY_BUILD_UNIQUE_ID
+---------------------
+
+.. versionadded:: 3.20
+
+The name of a valid C-identifier which is set to a unique per-file
+value during unity builds.
+
+When this property is populated and when :prop_tgt:`UNITY_BUILD`
+is true, the property value is used to define a compiler definition
+of the specified name. The value of the defined symbol is unspecified,
+but it is unique per file path.
+
+Given:
+
+.. code-block:: cmake
+
+ set_target_properties(myTarget PROPERTIES
+ UNITY_BUILD "ON"
+ UNITY_BUILD_UNIQUE_ID "MY_UNITY_ID"
+ )
+
+the ``MY_UNITY_ID`` symbol is defined to a unique per-file value.
+
+One known use case for this identifier is to disambiguate the
+variables in an anonymous namespace in a limited scope.
+Anonymous namespaces present a problem for unity builds because
+they are used to ensure that certain variables and declarations
+are scoped to a translation unit which is approximated by a
+single source file. When source files are combined in a unity
+build file, those variables in different files are combined in
+a single translation unit and the names clash. This property can
+be used to avoid that with code like the following:
+
+.. code-block:: cpp
+
+ // Needed for when unity builds are disabled
+ #ifndef MY_UNITY_ID
+ #define MY_UNITY_ID
+ #endif
+
+ namespace { namespace MY_UNITY_ID {
+ // The name 'i' clashes (or could clash) with other
+ // variables in other anonymous namespaces
+ int i = 42;
+ }}
+
+ int use_var()
+ {
+ return MY_UNITY_ID::i;
+ }
+
+The pseudononymous 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_ATTRIBUTE_an-attribute.rst b/Help/prop_tgt/XCODE_ATTRIBUTE_an-attribute.rst
index 71858c50e..fbe760815 100644
--- a/Help/prop_tgt/XCODE_ATTRIBUTE_an-attribute.rst
+++ b/Help/prop_tgt/XCODE_ATTRIBUTE_an-attribute.rst
@@ -3,9 +3,15 @@ XCODE_ATTRIBUTE_<an-attribute>
Set Xcode target attributes directly.
-Tell the :generator:`Xcode` generator to set '<an-attribute>' to a given
+Tell the :generator:`Xcode` generator to set ``<an-attribute>`` to a given
value in the generated Xcode project. Ignored on other generators.
+This offers low-level control over the generated Xcode project file.
+It is meant as a last resort for specifying settings that CMake does
+not otherwise have a way to control. Although this can override a
+setting CMake normally produces on its own, doing so bypasses CMake's
+model of the project and can break things.
+
See the :variable:`CMAKE_XCODE_ATTRIBUTE_<an-attribute>` variable
to set attributes on all targets in a directory tree.
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
new file mode 100644
index 000000000..7b6812678
--- /dev/null
+++ b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY.rst
@@ -0,0 +1,8 @@
+XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY
+----------------------------------------
+
+.. versionadded:: 3.20
+
+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.
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
new file mode 100644
index 000000000..29f8c5c03
--- /dev/null
+++ b/Help/prop_tgt/XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY.rst
@@ -0,0 +1,8 @@
+XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY
+---------------------------------------------
+
+.. versionadded:: 3.20
+
+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.
diff --git a/Help/prop_tgt/XCODE_EMBED_type.rst b/Help/prop_tgt/XCODE_EMBED_type.rst
new file mode 100644
index 000000000..90c5bc787
--- /dev/null
+++ b/Help/prop_tgt/XCODE_EMBED_type.rst
@@ -0,0 +1,14 @@
+XCODE_EMBED_<type>
+------------------
+
+.. versionadded:: 3.20
+
+Tell the :generator:`Xcode` generator to embed the specified list of items into
+the target bundle. ``<type>`` specifies the embed build phase to use.
+
+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`.
diff --git a/Help/prop_tgt/XCODE_EMBED_type_PATH.rst b/Help/prop_tgt/XCODE_EMBED_type_PATH.rst
new file mode 100644
index 000000000..887cf5721
--- /dev/null
+++ b/Help/prop_tgt/XCODE_EMBED_type_PATH.rst
@@ -0,0 +1,9 @@
+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
+to the base location of the ``Embed XXX`` build phase associated with
+``<type>``.
diff --git a/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt b/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt
index 3ae54484a..d38a96e8b 100644
--- a/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt
+++ b/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt
@@ -3,9 +3,10 @@ Output directory in which to build |XXX| target files.
This property specifies the directory into which |xxx| target files
should be built. The property value may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
-Multi-configuration generators (VS, Xcode) append a per-configuration
-subdirectory to the specified directory unless a generator expression
-is used.
+Multi-configuration generators (:ref:`Visual Studio <Visual Studio Generators>`,
+:generator:`Xcode`, :generator:`Ninja Multi-Config`) append a
+per-configuration subdirectory to the specified directory unless a generator
+expression is used.
-This property is initialized by the value of the variable
-|CMAKE_XXX_OUTPUT_DIRECTORY| if it is set when a target is created.
+This property is initialized by the value of the
+|CMAKE_XXX_OUTPUT_DIRECTORY| variable if it is set when a target is created.
diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst
new file mode 100644
index 000000000..176447d16
--- /dev/null
+++ b/Help/release/3.20.rst
@@ -0,0 +1,329 @@
+CMake 3.20 Release Notes
+************************
+
+.. only:: html
+
+ .. contents::
+
+Changes made since CMake 3.19 include the following.
+
+New Features
+============
+
+Presets
+-------
+
+* :manual:`cmake-presets(7)` gained support for build and test presets.
+
+Generators
+----------
+
+* :ref:`Makefile Generators`, for some toolchains, now use the compiler
+ to extract implicit dependencies while compiling source files.
+
+Languages
+---------
+
+* C++23 compiler modes may now be specified via the :prop_tgt:`CXX_STANDARD`,
+ :prop_tgt:`CUDA_STANDARD`, or :prop_tgt:`OBJCXX_STANDARD` target properties,
+ or via the :manual:`Compile Features <cmake-compile-features(7)>`
+ functionality's ``cxx_std_23`` meta-feature.
+
+* ``CUDA`` language support now works when ``nvcc`` is a symbolic link,
+ for example due to a ``ccache`` or ``colornvcc`` wrapper script.
+
+* The :envvar:`CUDAARCHS` environment variable was added for initializing
+ :variable:`CMAKE_CUDA_ARCHITECTURES`. Useful in cases where the compiler
+ default is unsuitable for the machine's GPU.
+
+Compilers
+---------
+
+* The NVIDIA HPC SDK compilers are now supported with compiler id ``NVHPC``.
+
+* The Intel oneAPI NextGen LLVM compilers are now supported with
+ compiler id ``IntelLLVM``:
+
+ * The ``icx``/``icpx`` C/C++ compilers on Linux, and the ``icx``
+ C/C++ compiler on Windows, are fully supported as of oneAPI 2021.1.
+
+ * The ``ifx`` Fortran compiler on Linux is partially supported.
+ As of oneAPI 2021.1, ``ifx`` does not define several identification
+ macros, so CMake identifies it as the classic ``Intel`` compiler.
+ This works in many cases because ``ifx`` accepts the same command line
+ parameters as ``ifort``. A future version of oneAPI may fix this.
+
+ * The ``ifx`` Fortran compiler on Windows is not yet supported.
+
+ The Intel oneAPI Classic compilers (``icc``, ``icpc``, and ``ifort``)
+ continue to be supported with compiler id ``Intel``.
+
+* Support was added for the IAR STM8 compiler.
+
+Platforms
+---------
+
+* CMake's support for :ref:`Cross Compiling for Android`
+ is now merged with the Android NDK's toolchain file.
+ They now have similar behavior, though some variable names differ.
+ User-facing changes include:
+
+ - ``find_*`` functions will search NDK ABI / API specific paths by default.
+
+ - The default :variable:`CMAKE_BUILD_TYPE` for Android is
+ now ``RelWithDebInfo``.
+
+ - The :variable:`CMAKE_ANDROID_NDK_VERSION` variable was added to
+ report the version of the NDK.
+
+File-Based API
+--------------
+
+* The :manual:`cmake-file-api(7)` gained a new "toolchains" object
+ kind that describes the compiler used for each enabled language.
+
+Commands
+--------
+
+* :command:`add_custom_command` and :command:`add_custom_target` now
+ support :manual:`generator expressions <cmake-generator-expressions(7)>`
+ in their ``OUTPUT`` and ``BYPRODUCTS`` options.
+
+ Their ``COMMAND``, ``WORKING_DIRECTORY``, and ``DEPENDS`` options gained
+ support for new generator expressions ``$<COMMAND_CONFIG:...>`` and
+ ``$<OUTPUT_CONFIG:...>`` that control cross-config handling when using
+ the :generator:`Ninja Multi-Config` generator.
+
+* The :command:`add_custom_command` command gained ``DEPFILE`` support on
+ :ref:`Makefile Generators`.
+
+* The :command:`add_library` command previously prohibited imported object
+ libraries when using potentially multi-architecture configurations.
+ This mostly affected the :generator:`Xcode` generator, e.g. when targeting
+ iOS or one of the other device platforms. This restriction has now been
+ removed.
+
+* The :command:`cmake_path` command was added for operations on
+ filesystem paths.
+
+* The :command:`configure_file` command gained ``USE_SOURCE_PERMISSIONS``
+ and ``FILE_PERMISSIONS`` options to support copying of permissions of the
+ source file and using specified permissions respectively.
+
+* The :command:`file(GENERATE)` command gained a ``NEWLINE_STYLE`` option to
+ specify how newlines are handled for the generated file.
+
+* The :command:`file(GENERATE)` command gained ``NO_SOURCE_PERMISSIONS``,
+ ``USE_SOURCE_PERMISSIONS``, and ``FILE_PERMISSIONS`` options for controlling
+ the permissions of the generated file.
+
+* The :command:`install(FILES)` command ``RENAME`` option learned to
+ support :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+* The :command:`target_include_directories` command gained a new option
+ ``AFTER``.
+
+* The :command:`target_sources` command now supports targets created
+ by the :command:`add_custom_target` command.
+
+* The :command:`try_run` command gained a ``WORKING_DIRECTORY`` option to
+ set the working directory in which to run the compiled check executable.
+
+Variables
+---------
+
+* The :variable:`CMAKE_<LANG>_BYTE_ORDER` variable was added to provide the
+ target architecture byte order detected from the toolchain.
+
+* The :variable:`CMAKE_RUNTIME_OUTPUT_DIRECTORY`,
+ :variable:`CMAKE_LIBRARY_OUTPUT_DIRECTORY`, and
+ :variable:`CMAKE_ARCHIVE_OUTPUT_DIRECTORY` variables now support
+ target-dependent generator expressions.
+
+Properties
+----------
+
+* The :prop_tgt:`<LANG>_CLANG_TIDY` target property and the associated
+ :variable:`CMAKE_<LANG>_CLANG_TIDY` variable learned to support
+ the ``OBJC`` and ``OBJCXX`` languages.
+
+* The :prop_tgt:`EXPORT_COMPILE_COMMANDS` target property was added
+ for the associated :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` variable
+ to allow for configuration of exporting compile commands per target.
+
+* The :prop_sf:`GENERATED` source-file property is now visible
+ from any directory scope, regardless of the scope in which it is set.
+ See policy :policy:`CMP0118`.
+
+* The :prop_tgt:`UNITY_BUILD_UNIQUE_ID` target property
+ was added to support generation of an identifier that is
+ unique per source file in unity builds. It can help to
+ resolve duplicate symbol problems with anonymous namespaces.
+
+* The :prop_tgt:`WIN32_EXECUTABLE` target property now works with Clang
+ on Windows.
+
+* The :prop_tgt:`XCODE_EMBED_FRAMEWORKS <XCODE_EMBED_<type>>` target property
+ was added to tell the :generator:`Xcode` generator to embed frameworks.
+ Aspects of the embedding can be customized with the
+ :prop_tgt:`XCODE_EMBED_FRAMEWORKS_PATH <XCODE_EMBED_<type>>`,
+ :prop_tgt:`XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY`, and
+ :prop_tgt:`XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY` target properties.
+
+Modules
+-------
+
+* The :module:`ExternalData` module :command:`ExternalData_Add_Target`
+ function gained a ``SHOW_PROGRESS <bool>`` option for controlling whether
+ or not to show progress output during the build.
+
+* The :module:`ExternalProject` module :command:`ExternalProject_Add` function
+ gained a ``CONFIGURE_HANDLED_BY_BUILD`` option. This can be used to make
+ subsequent runs of the configure step be triggered by the build step when
+ an external project dependency rebuilds instead of always re-running the
+ configure step in such cases.
+
+* The :module:`FindBoost` module gained a ``Boost_NO_WARN_NEW_VERSIONS``
+ option to silence the warning about unknown dependencies for new
+ Boost versions.
+
+* The :module:`FindCUDAToolkit` module gained support for finding CUDA
+ toolkits when ``nvcc`` is a symbolic link,
+ for example due to a ``ccache`` or ``colornvcc`` wrapper script.
+
+* The :module:`FindGDAL` module has been improved to document and mark as
+ advanced its cache variables. There is a new ``FindGDAL_SKIP_GDAL_CONFIG``
+ variable which may be used to skip over the ``gdal-config``-based search.
+ Users may also set ``GDAL_ADDITIONAL_LIBRARY_VERSIONS`` to add additional
+ versions to the library name search strategy.
+
+* The :module:`FindIntl` module now provides an imported target.
+
+* The :module:`FindOpenSSL` module learned to support a version range.
+
+* The :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython`
+ modules gained options controlling how unversioned interpreter names are
+ searched.
+
+* The :module:`UseJava` module ``add_jar()`` command's
+ ``GENERATE_NATIVE_HEADERS`` feature gained options to export the
+ generated target.
+
+* The :module:`UseSWIG` module gained the capability, for
+ :ref:`Makefile <Makefile Generators>` and :ref:`Ninja <Ninja Generators>`
+ generators, to use the ``swig`` tool to generate implicit dependencies.
+
+Autogen
+-------
+
+* The :ref:`Qt AUTOMOC` feature now works with per-config sources.
+
+CTest
+-----
+
+* :manual:`ctest(1)` gained a ``--test-dir`` option to specify the directory
+ in which to look for tests.
+
+CPack
+-----
+
+* :module:`CPack` gained the :variable:`CPACK_THREADS` variable to
+ control the number of threads used for parallelized operations,
+ such as compressing the installer package.
+
+* The :cpack_gen:`CPack DEB Generator` learned a new
+ :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS`
+ variable to specify additional search directories for
+ resolving private library dependencies when using
+ ``dpkg-shlibdeps``.
+
+* The :cpack_gen:`CPack IFW Generator` gained a new
+ :variable:`CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST` variable to
+ control visibility of the widget listing installer pages on the left side
+ of the wizard. This feature available only since QtIFW 4.0.
+
+* The :cpack_gen:`CPack NSIS Generator` gained new
+ :variable:`CPACK_NSIS_BRANDING_TEXT` and
+ :variable:`CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION` variables to change
+ the text at the bottom of the install window and change its trim position
+
+* The :cpack_gen:`CPack NSIS Generator` now correctly handles Unicode
+ characters. If you want to have a :variable:`CPACK_RESOURCE_FILE_LICENSE`
+ with UTF-8 characters, it needs to be encoded in UTF-8 BOM.
+
+* The :cpack_gen:`CPack NuGet Generator` gained options:
+
+ - :variable:`CPACK_NUGET_PACKAGE_ICON` and
+ :variable:`CPACK_NUGET_<compName>_PACKAGE_ICON`
+ allow package icons to be specified by local files.
+ - :variable:`CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION` and
+ :variable:`CPACK_NUGET_<compName>_PACKAGE_LICENSE_EXPRESSION` add
+ support for specifying licenses recognized by the
+ `Software Package Data Exchange`_ (SPDX).
+ - :variable:`CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME` and
+ :variable:`CPACK_NUGET_<compName>_PACKAGE_LICENSE_FILE_NAME` allow
+ licenses to be specified by local files.
+ - :variable:`CPACK_NUGET_PACKAGE_LANGUAGE` and
+ :variable:`CPACK_NUGET_<compName>_PACKAGE_LANGUAGE` allow the locale
+ for a package to be specified, for example ``en_CA``.
+
+.. _Software Package Data Exchange: https://spdx.org/
+
+Deprecated and Removed Features
+===============================
+
+* The :manual:`cmake-server(7)` mode has been removed.
+ Clients should use the :manual:`cmake-file-api(7)` instead.
+
+* The :module:`WriteCompilerDetectionHeader` module has been deprecated
+ via policy :policy:`CMP0120`. Projects should be ported away from it.
+
+* The :module:`TestBigEndian` module has been deprecated in favor
+ of the :variable:`CMAKE_<LANG>_BYTE_ORDER` variable.
+
+* The :module:`AddFileDependencies` module is deprecated.
+ Port projects to use :command:`set_property` directly.
+
+* The :cpack_gen:`CPack NuGet Generator` deprecated some variables to reflect
+ changes in the NuGet specification:
+
+ - :variable:`CPACK_NUGET_PACKAGE_ICONURL` and
+ :variable:`CPACK_NUGET_<compName>_PACKAGE_ICONURL` have been deprecated;
+ replace with a reference to a local icon file.
+ - :variable:`CPACK_NUGET_PACKAGE_LICENSEURL` and
+ :variable:`CPACK_NUGET_<compName>_PACKAGE_LICENSEURL` have been deprecated;
+ replace with a reference to the project's license file or SPDX
+ license expression.
+
+Other Changes
+=============
+
+* Source file extensions must now be explicit.
+ See policy :policy:`CMP0115` for details.
+
+* The :prop_sf:`LANGUAGE` source file property now forces compilation
+ as the specified language. See policy :policy:`CMP0119`.
+
+* On AIX, installation of XCOFF executables and shared libraries
+ no longer requires relinking to change the runtime search path
+ from the build-tree RPATH to the install-tree RPATH. CMake now
+ edits the XCOFF binaries directly during installation, as has
+ long been done on ELF platforms.
+
+* With MSVC-like compilers the value of
+ :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` no longer contains
+ the ``/GR`` flag for runtime type information by default.
+ See policy :policy:`CMP0117`.
+
+* Ninja generators now transform the ``DEPFILE`` generated by an
+ :command:`add_custom_command`. See policy :policy:`CMP0116` for details.
+
+* The precompiled Linux binaries provided on
+ `cmake.org <https://cmake.org/download/>`_ have changed their naming pattern
+ to ``cmake-$ver-linux-$arch``, where ``$arch`` is either ``x86_64`` or
+ ``aarch64``.
+
+* The precompiled Windows binaries provided on
+ `cmake.org <https://cmake.org/download/>`_ have changed their naming pattern
+ to ``cmake-$ver-windows-$arch``, where ``$arch`` is either ``x86_64`` or
+ ``i386``.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 6fb0f1a48..95b41fb63 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -13,6 +13,7 @@ Releases
.. toctree::
:maxdepth: 1
+ 3.20 <3.20>
3.19 <3.19>
3.18 <3.18>
3.17 <3.17>
diff --git a/Help/variable/CMAKE_ANDROID_EXCEPTIONS.rst b/Help/variable/CMAKE_ANDROID_EXCEPTIONS.rst
new file mode 100644
index 000000000..6dd44f875
--- /dev/null
+++ b/Help/variable/CMAKE_ANDROID_EXCEPTIONS.rst
@@ -0,0 +1,7 @@
+CMAKE_ANDROID_EXCEPTIONS
+------------------------
+
+.. versionadded:: 3.20
+
+When :ref:`Cross Compiling for Android with the NDK`, this variable may be set
+to specify whether exceptions are enabled.
diff --git a/Help/variable/CMAKE_ANDROID_NDK_VERSION.rst b/Help/variable/CMAKE_ANDROID_NDK_VERSION.rst
new file mode 100644
index 000000000..5428d52bc
--- /dev/null
+++ b/Help/variable/CMAKE_ANDROID_NDK_VERSION.rst
@@ -0,0 +1,8 @@
+CMAKE_ANDROID_NDK_VERSION
+-------------------------
+
+.. versionadded:: 3.20
+
+When :ref:`Cross Compiling for Android with the NDK` and using an
+Android NDK version 11 or higher, this variable is provided by
+CMake to report the NDK version number.
diff --git a/Help/variable/CMAKE_ANDROID_RTTI.rst b/Help/variable/CMAKE_ANDROID_RTTI.rst
new file mode 100644
index 000000000..0e982069e
--- /dev/null
+++ b/Help/variable/CMAKE_ANDROID_RTTI.rst
@@ -0,0 +1,7 @@
+CMAKE_ANDROID_RTTI
+------------------
+
+.. versionadded:: 3.20
+
+When :ref:`Cross Compiling for Android with the NDK`, this variable may be set
+to specify whether RTTI is enabled.
diff --git a/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst b/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst
index 0d5ccd183..ad297c3d5 100644
--- a/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst
+++ b/Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst
@@ -8,7 +8,8 @@ CMake what architecture to use for :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`.
The value must be either ``arm64`` or ``x86_64``.
The value of this variable should never be modified by project code.
-It is meant to be set as a cache entry provided by the user,
-e.g. via ``-DCMAKE_APPLE_SILICON_PROCESSOR=...``.
+It is meant to be set by a toolchain file specified by the
+:variable:`CMAKE_TOOLCHAIN_FILE` variable, or as a cache entry
+provided by the user, e.g. via ``-DCMAKE_APPLE_SILICON_PROCESSOR=...``.
See also the :envvar:`CMAKE_APPLE_SILICON_PROCESSOR` environment variable.
diff --git a/Help/variable/CMAKE_BUILD_TYPE.rst b/Help/variable/CMAKE_BUILD_TYPE.rst
index 2d35635ac..405f7d590 100644
--- a/Help/variable/CMAKE_BUILD_TYPE.rst
+++ b/Help/variable/CMAKE_BUILD_TYPE.rst
@@ -18,3 +18,8 @@ in a build tree configured to build type ``Debug``, CMake will see to
having :variable:`CMAKE_C_FLAGS_DEBUG <CMAKE_<LANG>_FLAGS_DEBUG>` settings get
added to the :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` settings. See
also :variable:`CMAKE_CONFIGURATION_TYPES`.
+
+Note that configuration names are case-insensitive. The value of this
+variable will be the same as it is specified when invoking CMake.
+For instance, if ``-DCMAKE_BUILD_TYPE=ReLeAsE`` is specified, then the
+value of ``CMAKE_BUILD_TYPE`` will be ``ReLeAsE``.
diff --git a/Help/variable/CMAKE_CUDA_ARCHITECTURES.rst b/Help/variable/CMAKE_CUDA_ARCHITECTURES.rst
index 985040d73..d88551634 100644
--- a/Help/variable/CMAKE_CUDA_ARCHITECTURES.rst
+++ b/Help/variable/CMAKE_CUDA_ARCHITECTURES.rst
@@ -5,7 +5,8 @@ CMAKE_CUDA_ARCHITECTURES
Default value for :prop_tgt:`CUDA_ARCHITECTURES` property of targets.
-This is initialized as follows depending on :variable:`CMAKE_CUDA_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>`:
+Initialized by the :envvar:`CUDAARCHS` environment variable if set.
+Otherwise as follows depending on :variable:`CMAKE_CUDA_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>`:
- For ``Clang``: the oldest architecture that works.
@@ -17,3 +18,18 @@ and compiler versions.
This variable is used to initialize the :prop_tgt:`CUDA_ARCHITECTURES` property
on all targets. See the target property for additional information.
+
+Examples
+^^^^^^^^
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION)
+
+ if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
+ set(CMAKE_CUDA_ARCHITECTURES 75)
+ endif()
+
+ project(example LANGUAGES CUDA)
+
+``CMAKE_CUDA_ARCHITECTURES`` will default to ``75`` unless overridden by the user.
diff --git a/Help/variable/CMAKE_DEPENDS_USE_COMPILER.rst b/Help/variable/CMAKE_DEPENDS_USE_COMPILER.rst
new file mode 100644
index 000000000..bdad59eaf
--- /dev/null
+++ b/Help/variable/CMAKE_DEPENDS_USE_COMPILER.rst
@@ -0,0 +1,9 @@
+CMAKE_DEPENDS_USE_COMPILER
+--------------------------
+
+.. versionadded:: 3.20
+
+For the :ref:`Makefile Generators`, source dependencies are now, for a
+selection of compilers, generated by the compiler itself. By defining this
+variable with value ``FALSE``, you can restore the legacy behavior (i.e. using
+``CMake`` for dependencies discovery).
diff --git a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst
index 724f30989..53a19dca4 100644
--- a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst
+++ b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst
@@ -28,7 +28,8 @@ form. The format of the JSON file looks like:
]
This is initialized by the :envvar:`CMAKE_EXPORT_COMPILE_COMMANDS` environment
-variable.
+variable, and initializes the :prop_tgt:`EXPORT_COMPILE_COMMANDS` target
+property for all targets.
.. note::
This option is implemented only by :ref:`Makefile Generators`
diff --git a/Help/variable/CMAKE_LANG_BYTE_ORDER.rst b/Help/variable/CMAKE_LANG_BYTE_ORDER.rst
new file mode 100644
index 000000000..78f0ae694
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_BYTE_ORDER.rst
@@ -0,0 +1,20 @@
+CMAKE_<LANG>_BYTE_ORDER
+-----------------------
+
+.. versionadded:: 3.20
+
+Byte order of ``<LANG>`` compiler target architecture, if known.
+If defined and not empty, the value is one of:
+
+``BIG_ENDIAN``
+ The target architecture is Big Endian.
+
+``LITTLE_ENDIAN``
+ The target architecture is Little Endian.
+
+This is defined for languages ``C``, ``CXX``, ``OBJC``, ``OBJCXX``,
+and ``CUDA``.
+
+If :variable:`CMAKE_OSX_ARCHITECTURES` specifies multiple architectures, the
+value of ``CMAKE_<LANG>_BYTE_ORDER`` is non-empty only if all architectures
+share the same byte order.
diff --git a/Help/variable/CMAKE_LANG_CLANG_TIDY.rst b/Help/variable/CMAKE_LANG_CLANG_TIDY.rst
index 78f0f6a21..32e27b0ad 100644
--- a/Help/variable/CMAKE_LANG_CLANG_TIDY.rst
+++ b/Help/variable/CMAKE_LANG_CLANG_TIDY.rst
@@ -4,7 +4,7 @@ CMAKE_<LANG>_CLANG_TIDY
.. versionadded:: 3.6
Default value for :prop_tgt:`<LANG>_CLANG_TIDY` target property
-when ``<LANG>`` is ``C`` or ``CXX``.
+when ``<LANG>`` is ``C``, ``CXX``, ``OBJC`` or ``OBJCXX``.
This variable is used to initialize the property on each target as it is
created. For example:
diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
index 8eb4fb612..89d9e2757 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst
@@ -25,7 +25,9 @@ include:
HP = Hewlett-Packard Compiler (hp.com)
IAR = IAR Systems (iar.com)
Intel = Intel Compiler (intel.com)
+ IntelLLVM = Intel LLVM-Based Compiler (intel.com)
MSVC = Microsoft Visual Studio (microsoft.com)
+ NVHPC = NVIDIA HPC SDK Compiler (nvidia.com)
NVIDIA = NVIDIA CUDA Compiler (nvidia.com)
OpenWatcom = Open Watcom (openwatcom.org)
PGI = The Portland Group (pgroup.com)
diff --git a/Help/variable/CMAKE_LINK_SEARCH_END_STATIC.rst b/Help/variable/CMAKE_LINK_SEARCH_END_STATIC.rst
index f4ccc0415..e86f63963 100644
--- a/Help/variable/CMAKE_LINK_SEARCH_END_STATIC.rst
+++ b/Help/variable/CMAKE_LINK_SEARCH_END_STATIC.rst
@@ -15,7 +15,7 @@ back to its starting type. This property switches the final linker
search type to ``-Bstatic`` regardless of how it started.
This variable is used to initialize the target property
-:prop_tgt:`LINK_SEARCH_END_STATIC` for all targets. If set, it's
+:prop_tgt:`LINK_SEARCH_END_STATIC` for all targets. If set, its
value is also used by the :command:`try_compile` command.
See also :variable:`CMAKE_LINK_SEARCH_START_STATIC`.
diff --git a/Help/variable/CMAKE_LINK_SEARCH_START_STATIC.rst b/Help/variable/CMAKE_LINK_SEARCH_START_STATIC.rst
index 2025c72b4..ab1837cef 100644
--- a/Help/variable/CMAKE_LINK_SEARCH_START_STATIC.rst
+++ b/Help/variable/CMAKE_LINK_SEARCH_START_STATIC.rst
@@ -16,7 +16,7 @@ when linking an executable statically (e.g. with the GNU ``-static``
option).
This variable is used to initialize the target property
-:prop_tgt:`LINK_SEARCH_START_STATIC` for all targets. If set, it's
+:prop_tgt:`LINK_SEARCH_START_STATIC` for all targets. If set, its
value is also used by the :command:`try_compile` command.
See also :variable:`CMAKE_LINK_SEARCH_END_STATIC`.
diff --git a/Help/variable/CMAKE_NO_BUILTIN_CHRPATH.rst b/Help/variable/CMAKE_NO_BUILTIN_CHRPATH.rst
index 189f59fa3..b9b045e7d 100644
--- a/Help/variable/CMAKE_NO_BUILTIN_CHRPATH.rst
+++ b/Help/variable/CMAKE_NO_BUILTIN_CHRPATH.rst
@@ -1,10 +1,17 @@
CMAKE_NO_BUILTIN_CHRPATH
------------------------
-Do not use the builtin ELF editor to fix RPATHs on installation.
+Do not use the builtin binary editor to fix runtime library search
+paths on installation.
-When an ELF binary needs to have a different RPATH after installation
-than it does in the build tree, CMake uses a builtin editor to change
-the RPATH in the installed copy. If this variable is set to true then
-CMake will relink the binary before installation instead of using its
-builtin editor.
+When an ELF or XCOFF binary needs to have a different runtime library
+search path after installation than it does in the build tree, CMake uses
+a builtin editor to change the runtime search path in the installed copy.
+If this variable is set to true then CMake will relink the binary before
+installation instead of using its builtin editor.
+
+.. versionadded:: 3.20
+
+ This variable also applies to XCOFF binaries' LIBPATH. Prior to the
+ addition of the XCOFF editor in CMake 3.20, this variable applied only
+ to ELF binaries' RPATH/RUNPATH.
diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index d35595a21..9f68741a5 100644
--- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
+++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
@@ -27,6 +27,8 @@ warn by default:
policy :policy:`CMP0102`.
* ``CMAKE_POLICY_WARNING_CMP0112`` controls the warning for
policy :policy:`CMP0112`.
+* ``CMAKE_POLICY_WARNING_CMP0116`` controls the warning for
+ policy :policy:`CMP0116`.
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_POSITION_INDEPENDENT_CODE.rst b/Help/variable/CMAKE_POSITION_INDEPENDENT_CODE.rst
index 43b1397eb..b01031713 100644
--- a/Help/variable/CMAKE_POSITION_INDEPENDENT_CODE.rst
+++ b/Help/variable/CMAKE_POSITION_INDEPENDENT_CODE.rst
@@ -5,5 +5,5 @@ Default value for :prop_tgt:`POSITION_INDEPENDENT_CODE` of targets.
This variable is used to initialize the
:prop_tgt:`POSITION_INDEPENDENT_CODE` property on all the targets.
-See that target property for additional information. If set, it's
+See that target property for additional information. If set, its
value is also used by the :command:`try_compile` command.
diff --git a/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst b/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst
index 8ad89f128..ce162157b 100644
--- a/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst
+++ b/Help/variable/CMAKE_SYSTEM_PROCESSOR.rst
@@ -1,8 +1,13 @@
CMAKE_SYSTEM_PROCESSOR
----------------------
-The name of the CPU CMake is building for.
+When not cross-compiling, this variable has the same value as the
+:variable:`CMAKE_HOST_SYSTEM_PROCESSOR` variable. In many cases,
+this will correspond to the target architecture for the build, but
+this is not guaranteed. (E.g. on Windows, the host may be ``AMD64``
+even when using a MSVC ``cl`` compiler with a 32-bit target.)
-This variable is the same as :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` if
-you build for the host system instead of the target system when
-cross compiling.
+When cross-compiling, a :variable:`CMAKE_TOOLCHAIN_FILE` should set
+the ``CMAKE_SYSTEM_PROCESSOR`` variable to match target architecture
+that it specifies (via :variable:`CMAKE_<LANG>_COMPILER` and perhaps
+:variable:`CMAKE_<LANG>_COMPILER_TARGET`).
diff --git a/Help/variable/CMAKE_UNITY_BUILD_UNIQUE_ID.rst b/Help/variable/CMAKE_UNITY_BUILD_UNIQUE_ID.rst
new file mode 100644
index 000000000..64ef18ab8
--- /dev/null
+++ b/Help/variable/CMAKE_UNITY_BUILD_UNIQUE_ID.rst
@@ -0,0 +1,8 @@
+CMAKE_UNITY_BUILD_UNIQUE_ID
+---------------------------
+
+.. versionadded:: 3.20
+
+This variable is used to initialize the :prop_tgt:`UNITY_BUILD_UNIQUE_ID`
+property of targets when they are created. It specifies the name of the
+unique identifier generated per file in a unity build.
diff --git a/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst b/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst
index 90e4c0eac..ffa0a4c7a 100644
--- a/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst
+++ b/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst
@@ -5,8 +5,14 @@ CMAKE_XCODE_ATTRIBUTE_<an-attribute>
Set Xcode target attributes directly.
-Tell the :generator:`Xcode` generator to set '<an-attribute>' to a given value
-in the generated Xcode project. Ignored on other generators.
+Tell the :generator:`Xcode` generator to set ``<an-attribute>`` to a given
+value in the generated Xcode project. Ignored on other generators.
+
+This offers low-level control over the generated Xcode project file.
+It is meant as a last resort for specifying settings that CMake does
+not otherwise have a way to control. Although this can override a
+setting CMake normally produces on its own, doing so bypasses CMake's
+model of the project and can break things.
See the :prop_tgt:`XCODE_ATTRIBUTE_<an-attribute>` target property
to set attributes on a specific target.
diff --git a/Help/variable/CTEST_MEMORYCHECK_SANITIZER_OPTIONS.rst b/Help/variable/CTEST_MEMORYCHECK_SANITIZER_OPTIONS.rst
index 6cd51fa18..b6fee2efe 100644
--- a/Help/variable/CTEST_MEMORYCHECK_SANITIZER_OPTIONS.rst
+++ b/Help/variable/CTEST_MEMORYCHECK_SANITIZER_OPTIONS.rst
@@ -5,3 +5,8 @@ CTEST_MEMORYCHECK_SANITIZER_OPTIONS
Specify the CTest ``MemoryCheckSanitizerOptions`` setting
in a :manual:`ctest(1)` dashboard client script.
+
+CTest prepends correct sanitizer options ``*_OPTIONS``
+environment variable to executed command. CTests adds
+its own ``log_path`` to sanitizer options, don't provide your
+own ``log_path``.
diff --git a/Help/variable/MSVC.rst b/Help/variable/MSVC.rst
index ca8775cb3..a2dbc2eb0 100644
--- a/Help/variable/MSVC.rst
+++ b/Help/variable/MSVC.rst
@@ -1,8 +1,7 @@
MSVC
----
-Set to ``true`` when the compiler is some version of Microsoft Visual
-C++ or another compiler simulating Visual C++. Any compiler defining
-``_MSC_VER`` is considered simulating Visual C++.
+Set to ``true`` when the compiler is some version of Microsoft Visual C++
+or another compiler simulating the Visual C++ ``cl`` command-line syntax.
See also the :variable:`MSVC_VERSION` variable.
diff --git a/Help/variable/MSVC_IDE.rst b/Help/variable/MSVC_IDE.rst
index 027d1bc8c..18e99833d 100644
--- a/Help/variable/MSVC_IDE.rst
+++ b/Help/variable/MSVC_IDE.rst
@@ -5,3 +5,10 @@ MSVC_IDE
Set to ``true`` when the target platform is the Microsoft Visual C++ IDE, as
opposed to the command line compiler.
+
+.. note::
+
+ This variable is only available after compiler detection has been performed,
+ so it is not available to toolchain files or before the first
+ :command:`project` or :command:`enable_language` call which uses an
+ MSVC-like compiler.
diff --git a/Modules/AddFileDependencies.cmake b/Modules/AddFileDependencies.cmake
index 598a52fa9..13b2600f9 100644
--- a/Modules/AddFileDependencies.cmake
+++ b/Modules/AddFileDependencies.cmake
@@ -5,24 +5,29 @@
AddFileDependencies
-------------------
+.. deprecated:: 3.20
+
Add dependencies to a source file.
.. code-block:: cmake
- ADD_FILE_DEPENDENCIES(<source> <files>)
+ add_file_dependencies(<source> <files>...)
Adds the given ``<files>`` to the dependencies of file ``<source>``.
-#]=======================================================================]
-macro(ADD_FILE_DEPENDENCIES _file)
+Do not use this command in new code. It is just a wrapper around:
+
+.. code-block:: cmake
+
+ set_property(SOURCE <source> APPEND PROPERTY OBJECT_DEPENDS <files>...)
+
+Instead use the :command:`set_property` command to append to the
+:prop_sf:`OBJECT_DEPENDS` source file property directly.
+
+#]=======================================================================]
- get_source_file_property(_deps ${_file} OBJECT_DEPENDS)
- if (_deps)
- set(_deps ${_deps} ${ARGN})
- else ()
- set(_deps ${ARGN})
- endif ()
+function(add_file_dependencies _file)
- set_source_files_properties(${_file} PROPERTIES OBJECT_DEPENDS "${_deps}")
+ set_property(SOURCE "${_file}" APPEND PROPERTY OBJECT_DEPENDS "${ARGN}")
-endmacro()
+endfunction()
diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake
index f521d2220..0beff04fd 100644
--- a/Modules/BundleUtilities.cmake
+++ b/Modules/BundleUtilities.cmake
@@ -59,9 +59,10 @@ fix each one up according to its own list of prerequisites.
Then clear all the keys and call ``verify_app`` on the final bundle to
ensure that it is truly standalone.
-As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
-which are then ignored
-(e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``).
+.. versionadded:: 3.6
+ As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
+ which are then ignored
+ (e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``).
.. code-block:: cmake
@@ -78,9 +79,10 @@ Verifies that an application ``<app>`` appears valid based on running
analysis tools on it. Calls :command:`message(FATAL_ERROR)` if the application
is not verified.
-As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
-which are then ignored
-(e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``)
+.. versionadded:: 3.6
+ As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
+ which are then ignored
+ (e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``)
.. code-block:: cmake
@@ -155,9 +157,10 @@ them. Set values associated with each key such that we can loop over
all of them and copy prerequisite libs into the bundle and then do
appropriate ``install_name_tool`` fixups.
-As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
-which are then ignored
-(e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``)
+.. versionadded:: 3.6
+ As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
+ which are then ignored
+ (e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``)
.. code-block:: cmake
@@ -215,9 +218,10 @@ Verifies that the sum of all prerequisites of all files inside the
bundle are contained within the bundle or are ``system`` libraries,
presumed to exist everywhere.
-As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
-which are then ignored
-(e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``)
+.. versionadded:: 3.6
+ As an optional parameter (``IGNORE_ITEM``) a list of file names can be passed,
+ which are then ignored
+ (e.g. ``IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe"``)
.. code-block:: cmake
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in
index eea3f5d41..7f73891fa 100644
--- a/Modules/CMakeCCompiler.cmake.in
+++ b/Modules/CMakeCCompiler.cmake.in
@@ -48,6 +48,7 @@ set(CMAKE_C_LINKER_PREFERENCE 10)
# Save compiler ABI information.
set(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@")
set(CMAKE_C_COMPILER_ABI "@CMAKE_C_COMPILER_ABI@")
+set(CMAKE_C_BYTE_ORDER "@CMAKE_C_BYTE_ORDER@")
set(CMAKE_C_LIBRARY_ARCHITECTURE "@CMAKE_C_LIBRARY_ARCHITECTURE@")
if(CMAKE_C_SIZEOF_DATA_PTR)
diff --git a/Modules/CMakeCCompilerABI.c b/Modules/CMakeCCompilerABI.c
index 08cf39bd8..f0ee21acf 100644
--- a/Modules/CMakeCCompilerABI.c
+++ b/Modules/CMakeCCompilerABI.c
@@ -17,6 +17,8 @@ int main(int argc, char* argv[])
{
int require = 0;
require += info_sizeof_dptr[argc];
+ require += info_byte_order_big_endian[argc];
+ require += info_byte_order_little_endian[argc];
#if defined(ABI_ID)
require += info_abi[argc];
#endif
diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in
index 871e18e7b..56ae7324b 100644
--- a/Modules/CMakeCUDACompiler.cmake.in
+++ b/Modules/CMakeCUDACompiler.cmake.in
@@ -12,6 +12,7 @@ set(CMAKE_CUDA11_COMPILE_FEATURES "@CMAKE_CUDA11_COMPILE_FEATURES@")
set(CMAKE_CUDA14_COMPILE_FEATURES "@CMAKE_CUDA14_COMPILE_FEATURES@")
set(CMAKE_CUDA17_COMPILE_FEATURES "@CMAKE_CUDA17_COMPILE_FEATURES@")
set(CMAKE_CUDA20_COMPILE_FEATURES "@CMAKE_CUDA20_COMPILE_FEATURES@")
+set(CMAKE_CUDA23_COMPILE_FEATURES "@CMAKE_CUDA23_COMPILE_FEATURES@")
set(CMAKE_CUDA_PLATFORM_ID "@CMAKE_CUDA_PLATFORM_ID@")
set(CMAKE_CUDA_SIMULATE_ID "@CMAKE_CUDA_SIMULATE_ID@")
@@ -31,6 +32,7 @@ set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1)
set(CMAKE_CUDA_SIZEOF_DATA_PTR "@CMAKE_CUDA_SIZEOF_DATA_PTR@")
set(CMAKE_CUDA_COMPILER_ABI "@CMAKE_CUDA_COMPILER_ABI@")
+set(CMAKE_CUDA_BYTE_ORDER "@CMAKE_CUDA_BYTE_ORDER@")
set(CMAKE_CUDA_LIBRARY_ARCHITECTURE "@CMAKE_CUDA_LIBRARY_ARCHITECTURE@")
if(CMAKE_CUDA_SIZEOF_DATA_PTR)
diff --git a/Modules/CMakeCUDACompilerABI.cu b/Modules/CMakeCUDACompilerABI.cu
index 702a7c53a..449a07944 100644
--- a/Modules/CMakeCUDACompilerABI.cu
+++ b/Modules/CMakeCUDACompilerABI.cu
@@ -8,6 +8,8 @@ int main(int argc, char* argv[])
{
int require = 0;
require += info_sizeof_dptr[argc];
+ require += info_byte_order_big_endian[argc];
+ require += info_byte_order_little_endian[argc];
#if defined(ABI_ID)
require += info_abi[argc];
#endif
diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in
index 2055de218..91039e5ae 100644
--- a/Modules/CMakeCUDACompilerId.cu.in
+++ b/Modules/CMakeCUDACompilerId.cu.in
@@ -17,7 +17,9 @@ char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
@CMAKE_CUDA_COMPILER_ID_ERROR_FOR_TEST@
const char* info_language_dialect_default = "INFO" ":" "dialect_default["
-#if __cplusplus > 201703L
+#if __cplusplus > 202002L
+ "23"
+#elif __cplusplus > 201703L
"20"
#elif __cplusplus >= 201703L
"17"
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index 58e6e2994..cb03ef405 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -154,21 +154,6 @@ if(NOT CMAKE_CUDA_COMPILE_WHOLE_COMPILATION)
"<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT>")
endif()
-if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_DEPFILE_FLAGS_CUDA)
- set(CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION
- "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M <SOURCE> -MT <OBJECT> -o $DEP_FILE")
- #The Ninja generator uses the make file dependency files to determine what
- #files need to be recompiled. Unfortunately, nvcc < 10.2 doesn't support building
- #a source file and generating the dependencies of said file in a single
- #invocation. Instead we have to state that you need to chain two commands.
- #
- #The makefile generators uses the custom CMake dependency scanner, and thus
- #it is exempt from this logic.
- list(APPEND CMAKE_CUDA_COMPILE_PTX_COMPILATION "${CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION}")
- list(APPEND CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION "${CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION}")
- list(APPEND CMAKE_CUDA_COMPILE_WHOLE_COMPILATION "${CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION}")
-endif()
-
# compile a cu file into an executable
if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
set(CMAKE_CUDA_LINK_EXECUTABLE
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 09bdc23ee..45acfe732 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -11,6 +11,7 @@ set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@")
set(CMAKE_CXX14_COMPILE_FEATURES "@CMAKE_CXX14_COMPILE_FEATURES@")
set(CMAKE_CXX17_COMPILE_FEATURES "@CMAKE_CXX17_COMPILE_FEATURES@")
set(CMAKE_CXX20_COMPILE_FEATURES "@CMAKE_CXX20_COMPILE_FEATURES@")
+set(CMAKE_CXX23_COMPILE_FEATURES "@CMAKE_CXX23_COMPILE_FEATURES@")
set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@")
set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@")
@@ -43,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;CPP)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP)
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
foreach (lang C OBJC OBJCXX)
@@ -60,6 +61,7 @@ set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
# Save compiler ABI information.
set(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@")
set(CMAKE_CXX_COMPILER_ABI "@CMAKE_CXX_COMPILER_ABI@")
+set(CMAKE_CXX_BYTE_ORDER "@CMAKE_CXX_BYTE_ORDER@")
set(CMAKE_CXX_LIBRARY_ARCHITECTURE "@CMAKE_CXX_LIBRARY_ARCHITECTURE@")
if(CMAKE_CXX_SIZEOF_DATA_PTR)
diff --git a/Modules/CMakeCXXCompilerABI.cpp b/Modules/CMakeCXXCompilerABI.cpp
index 236053452..036b96ea3 100644
--- a/Modules/CMakeCXXCompilerABI.cpp
+++ b/Modules/CMakeCXXCompilerABI.cpp
@@ -8,6 +8,8 @@ int main(int argc, char* argv[])
{
int require = 0;
require += info_sizeof_dptr[argc];
+ require += info_byte_order_big_endian[argc];
+ require += info_byte_order_little_endian[argc];
#if defined(ABI_ID)
require += info_abi[argc];
#endif
diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in
index d55d8b190..a67caba2c 100644
--- a/Modules/CMakeCXXCompilerId.cpp.in
+++ b/Modules/CMakeCXXCompilerId.cpp.in
@@ -44,7 +44,9 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
#endif
const char* info_language_dialect_default = "INFO" ":" "dialect_default["
-#if CXX_STD > 201703L
+#if CXX_STD > 202002L
+ "23"
+#elif CXX_STD > 201703L
"20"
#elif CXX_STD >= 201703L
"17"
diff --git a/Modules/CMakeCompilerABI.h b/Modules/CMakeCompilerABI.h
index 45532afdb..c5ce4dd9a 100644
--- a/Modules/CMakeCompilerABI.h
+++ b/Modules/CMakeCompilerABI.h
@@ -9,6 +9,18 @@ const char info_sizeof_dptr[] = {
/* clang-format on */
};
+/* Byte order. Only one of these will have bytes in the right order. */
+static unsigned short const info_byte_order_big_endian[] = {
+ /* INFO:byte_order string for BIG_ENDIAN */
+ 0x494E, 0x464F, 0x3A62, 0x7974, 0x655F, 0x6F72, 0x6465, 0x725B,
+ 0x4249, 0x475F, 0x454E, 0x4449, 0x414E, 0x5D00, 0x0000
+};
+static unsigned short const info_byte_order_little_endian[] = {
+ /* INFO:byte_order string for LITTLE_ENDIAN */
+ 0x4E49, 0x4F46, 0x623A, 0x7479, 0x5F65, 0x726F, 0x6564, 0x5B72,
+ 0x494C, 0x5454, 0x454C, 0x455F, 0x444E, 0x4149, 0x5D4E, 0x0000
+};
+
/* Application Binary Interface. */
/* Check for (some) ARM ABIs.
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index a0f0dfacb..214d58a8e 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -49,6 +49,7 @@ function(compiler_id_detection outvar lang)
endif()
list(APPEND ordered_compilers
Intel
+ IntelLLVM
PathScale
Embarcadero
Borland
@@ -61,6 +62,7 @@ function(compiler_id_detection outvar lang)
XLClang
XL
VisualAge
+ NVHPC
PGI
Cray
TI
diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake
index a3e5a1229..e8b9db797 100644
--- a/Modules/CMakeDetermineASMCompiler.cmake
+++ b/Modules/CMakeDetermineASMCompiler.cmake
@@ -78,6 +78,10 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_Intel "--version")
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_Intel "(ICC)")
+ list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS IntelLLVM )
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_IntelLLVM "--version")
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_IntelLLVM "(Intel[^\n]+oneAPI)")
+
list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS SunPro )
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_SunPro "-V")
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_SunPro "Sun C")
diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake
index ae3abe9b2..cd07ba983 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -59,7 +59,7 @@ else()
# finally list compilers to try
if(NOT CMAKE_C_COMPILER_INIT)
- set(CMAKE_C_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc cl bcc xlc clang)
+ set(CMAKE_C_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc cl bcc xlc icx clang)
endif()
_cmake_find_compiler(C)
@@ -134,7 +134,8 @@ else()
# variable but are not aware of CMAKE_C_COMPILER_FRONTEND_VARIANT.
# They pre-date our support for the GNU-like variant targeting the
# MSVC ABI so we do not consider that here.
- if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ if(CMAKE_C_COMPILER_ID STREQUAL "Clang"
+ OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xIntelLLVM")
if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_C_COMPILER_FRONTEND_VARIANT "MSVC")
else()
@@ -161,9 +162,10 @@ if (NOT _CMAKE_TOOLCHAIN_PREFIX)
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|QCC")
get_filename_component(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME)
- if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
+ if (COMPILER_BASENAME MATCHES "^(.+-)?(clang|g?cc)(-cl)?(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
- set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
+ set(_CMAKE_TOOLCHAIN_SUFFIX ${CMAKE_MATCH_4})
+ set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_6})
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
if(CMAKE_C_COMPILER_TARGET)
set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_C_COMPILER_TARGET}-)
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index 972adefd1..1ba537a3e 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -47,6 +47,10 @@ if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
endif()
endif()
+if(NOT "$ENV{CUDAARCHS}" STREQUAL "")
+ set(CMAKE_CUDA_ARCHITECTURES "$ENV{CUDAARCHS}" CACHE STRING "CUDA architectures")
+endif()
+
# Build a small source file to identify the compiler.
if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
set(CMAKE_CUDA_COMPILER_ID_RUN 1)
@@ -65,6 +69,10 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
set(CMAKE_CUDA_COMPILER_ID_VENDOR_REGEX_Clang "(clang version)")
CMAKE_DETERMINE_COMPILER_ID_VENDOR(CUDA "--version")
+ if(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang" AND WIN32)
+ message(FATAL_ERROR "Clang with CUDA is not yet supported on Windows. See CMake issue #20776.")
+ endif()
+
# Find the CUDA toolkit. We store the CMAKE_CUDA_COMPILER_TOOLKIT_ROOT and CMAKE_CUDA_COMPILER_LIBRARY_ROOT
# in CMakeCUDACompiler.cmake, so FindCUDAToolkit can avoid searching on future runs and the toolkit stays the same.
# This is very similar to FindCUDAToolkit, but somewhat simplified since we can issue fatal errors
@@ -163,15 +171,27 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
unset(search_paths)
if(NOT _CUDA_NVCC_EXECUTABLE)
- message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.")
+ message(FATAL_ERROR "Failed to find nvcc.\nCompiler ${CMAKE_CUDA_COMPILER_ID} requires the CUDA toolkit. Please set the CUDAToolkit_ROOT variable.")
endif()
endif()
endif()
- get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY)
- set(CMAKE_CUDA_DEVICE_LINKER "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/nvlink${CMAKE_EXECUTABLE_SUFFIX}")
- set(CMAKE_CUDA_FATBINARY "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/fatbinary${CMAKE_EXECUTABLE_SUFFIX}")
- get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY)
+ # Given that NVCC can be provided by multiple different sources (NVIDIA HPC SDK, CUDA Toolkit, distro)
+ # each of which has a different layout, we need to extract the CUDA toolkit root from the compiler
+ # itself, allowing us to support numerous different scattered toolkit layouts
+ execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda"
+ OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT)
+ if(_CUDA_NVCC_OUT MATCHES "TOP=([^\r\n]*)")
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_MATCH_1}" ABSOLUTE)
+ else()
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY)
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY)
+ endif()
+ unset(_CUDA_NVCC_OUT)
+
+ set(CMAKE_CUDA_DEVICE_LINKER "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/nvlink${CMAKE_EXECUTABLE_SUFFIX}")
+ set(CMAKE_CUDA_FATBINARY "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/fatbinary${CMAKE_EXECUTABLE_SUFFIX}")
+
# In a non-scattered installation the following are equivalent to CMAKE_CUDA_COMPILER_TOOLKIT_ROOT.
# We first check for a non-scattered installation to prefer it over a scattered installation.
@@ -209,10 +229,6 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
set(CMAKE_CUDA_COMPILER_ID_REQUIRE_SUCCESS ON)
endif()
elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang")
- if(WIN32)
- message(FATAL_ERROR "Clang with CUDA is not yet supported on Windows. See CMake issue #20776.")
- endif()
-
set(clang_test_flags "--cuda-path=\"${CMAKE_CUDA_COMPILER_LIBRARY_ROOT}\"")
if(CMAKE_CROSSCOMPILING)
# Need to pass the host target and include directories if we're crosscompiling.
diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake
index 905eb259a..fd07a5c47 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -58,7 +58,7 @@ else()
# finally list compilers to try
if(NOT CMAKE_CXX_COMPILER_INIT)
- set(CMAKE_CXX_COMPILER_LIST CC ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ aCC cl bcc xlC clang++)
+ set(CMAKE_CXX_COMPILER_LIST CC ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ aCC cl bcc xlC icpx icx clang++)
endif()
_cmake_find_compiler(CXX)
@@ -131,7 +131,8 @@ else()
# variable but are not aware of CMAKE_CXX_COMPILER_FRONTEND_VARIANT.
# They pre-date our support for the GNU-like variant targeting the
# MSVC ABI so we do not consider that here.
- if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
+ OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntelLLVM")
if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "MSVC")
else()
@@ -160,8 +161,9 @@ if (NOT _CMAKE_TOOLCHAIN_PREFIX)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC")
get_filename_component(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME)
- if (COMPILER_BASENAME MATCHES "^(.+-)(clan)?[gc]\\+\\+(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
+ if (COMPILER_BASENAME MATCHES "^(.+-)?(clang\\+\\+|g\\+\\+|clang-cl)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+ set(_CMAKE_TOOLCHAIN_SUFFIX ${CMAKE_MATCH_3})
set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
if(CMAKE_CXX_COMPILER_TARGET)
diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake
index b50e5f172..c03a85fdb 100644
--- a/Modules/CMakeDetermineCompileFeatures.cmake
+++ b/Modules/CMakeDetermineCompileFeatures.cmake
@@ -50,6 +50,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CXX14_COMPILE_FEATURES)
set(CMAKE_CXX17_COMPILE_FEATURES)
set(CMAKE_CXX20_COMPILE_FEATURES)
+ set(CMAKE_CXX23_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
@@ -60,6 +61,9 @@ function(cmake_determine_compile_features lang)
return()
endif()
+ if (CMAKE_CXX20_COMPILE_FEATURES AND CMAKE_CXX23_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES})
+ endif()
if (CMAKE_CXX17_COMPILE_FEATURES AND CMAKE_CXX20_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX17_COMPILE_FEATURES})
endif()
@@ -80,6 +84,7 @@ function(cmake_determine_compile_features lang)
${CMAKE_CXX14_COMPILE_FEATURES}
${CMAKE_CXX17_COMPILE_FEATURES}
${CMAKE_CXX20_COMPILE_FEATURES}
+ ${CMAKE_CXX23_COMPILE_FEATURES}
)
endif()
@@ -89,6 +94,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CXX14_COMPILE_FEATURES ${CMAKE_CXX14_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CXX17_COMPILE_FEATURES ${CMAKE_CXX17_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX23_COMPILE_FEATURES} PARENT_SCOPE)
message(CHECK_PASS "done")
@@ -100,6 +106,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CUDA14_COMPILE_FEATURES)
set(CMAKE_CUDA17_COMPILE_FEATURES)
set(CMAKE_CUDA20_COMPILE_FEATURES)
+ set(CMAKE_CUDA23_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
@@ -110,7 +117,10 @@ function(cmake_determine_compile_features lang)
return()
endif()
- if (CMAKE_CUDA17_COMPILE_FEATURES AND CMAKE_CUDA20_COMPILE_FEATURES)
+ if (CMAKE_CUDA20_COMPILE_FEATURES AND CMAKE_CUDA23_COMPILE_FEATURES)
+ list(REMOVE_ITEM CMAKE_CUDA23_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES})
+ endif()
+ if (CMAKE_CUDA17_COMPILE_FEATURES AND CMAKE_CUDA20_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES})
endif()
if (CMAKE_CUDA14_COMPILE_FEATURES AND CMAKE_CUDA17_COMPILE_FEATURES)
@@ -130,6 +140,7 @@ function(cmake_determine_compile_features lang)
${CMAKE_CUDA14_COMPILE_FEATURES}
${CMAKE_CUDA17_COMPILE_FEATURES}
${CMAKE_CUDA20_COMPILE_FEATURES}
+ ${CMAKE_CUDA23_COMPILE_FEATURES}
)
endif()
@@ -139,6 +150,7 @@ function(cmake_determine_compile_features lang)
set(CMAKE_CUDA14_COMPILE_FEATURES ${CMAKE_CUDA14_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CUDA17_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES} PARENT_SCOPE)
+ set(CMAKE_CUDA23_COMPILE_FEATURES ${CMAKE_CUDA23_COMPILE_FEATURES} PARENT_SCOPE)
message(CHECK_PASS "done")
diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake
index 7e5b3751b..cf028f181 100644
--- a/Modules/CMakeDetermineCompilerABI.cmake
+++ b/Modules/CMakeDetermineCompilerABI.cmake
@@ -8,6 +8,7 @@
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitIncludeInfo.cmake)
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
+include(${CMAKE_ROOT}/Modules/CMakeParseLibraryArchitecture.cmake)
include(CMakeTestCompilerCommon)
function(CMAKE_DETERMINE_COMPILER_ABI lang src)
@@ -75,12 +76,25 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
message(CHECK_PASS "done")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Detecting ${lang} compiler ABI info compiled with the following output:\n${OUTPUT}\n\n")
- file(STRINGS "${BIN}" ABI_STRINGS LIMIT_COUNT 2 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
+ file(STRINGS "${BIN}" ABI_STRINGS LIMIT_COUNT 32 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
+ set(ABI_SIZEOF_DPTR "NOTFOUND")
+ set(ABI_BYTE_ORDER "NOTFOUND")
+ set(ABI_NAME "NOTFOUND")
foreach(info ${ABI_STRINGS})
- if("${info}" MATCHES "INFO:sizeof_dptr\\[0*([^]]*)\\]")
+ if("${info}" MATCHES "INFO:sizeof_dptr\\[0*([^]]*)\\]" AND NOT ABI_SIZEOF_DPTR)
set(ABI_SIZEOF_DPTR "${CMAKE_MATCH_1}")
endif()
- if("${info}" MATCHES "INFO:abi\\[([^]]*)\\]")
+ if("${info}" MATCHES "INFO:byte_order\\[(BIG_ENDIAN|LITTLE_ENDIAN)\\]")
+ set(byte_order "${CMAKE_MATCH_1}")
+ if(ABI_BYTE_ORDER STREQUAL "NOTFOUND")
+ # Tentatively use the value because this is the first occurrence.
+ set(ABI_BYTE_ORDER "${byte_order}")
+ elseif(NOT ABI_BYTE_ORDER STREQUAL "${byte_order}")
+ # Drop value because multiple occurrences do not match.
+ set(ABI_BYTE_ORDER "")
+ endif()
+ endif()
+ if("${info}" MATCHES "INFO:abi\\[([^]]*)\\]" AND NOT ABI_NAME)
set(ABI_NAME "${CMAKE_MATCH_1}")
endif()
endforeach()
@@ -91,6 +105,10 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
set(CMAKE_${lang}_SIZEOF_DATA_PTR "${CMAKE_${lang}_SIZEOF_DATA_PTR_DEFAULT}" PARENT_SCOPE)
endif()
+ if(ABI_BYTE_ORDER)
+ set(CMAKE_${lang}_BYTE_ORDER "${ABI_BYTE_ORDER}" PARENT_SCOPE)
+ endif()
+
if(ABI_NAME)
set(CMAKE_${lang}_COMPILER_ABI "${ABI_NAME}" PARENT_SCOPE)
endif()
@@ -158,27 +176,9 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE)
set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE)
- # Detect library architecture directory name.
- if(CMAKE_LIBRARY_ARCHITECTURE_REGEX)
- foreach(dir ${implicit_dirs})
- if("${dir}" MATCHES "/lib/${CMAKE_LIBRARY_ARCHITECTURE_REGEX}$")
- get_filename_component(arch "${dir}" NAME)
- set(CMAKE_${lang}_LIBRARY_ARCHITECTURE "${arch}" PARENT_SCOPE)
- break()
- endif()
- endforeach()
- elseif(CMAKE_CXX_COMPILER_ID STREQUAL QCC)
- foreach(dir ${implicit_dirs})
- if (dir MATCHES "/lib$")
- get_filename_component(assumedArchDir "${dir}" DIRECTORY)
- get_filename_component(archParentDir "${assumedArchDir}" DIRECTORY)
- if (archParentDir STREQUAL CMAKE_SYSROOT)
- get_filename_component(archDirName "${assumedArchDir}" NAME)
- set(CMAKE_${lang}_LIBRARY_ARCHITECTURE "${archDirName}" PARENT_SCOPE)
- break()
- endif()
- endif()
- endforeach()
+ cmake_parse_library_architecture("${implicit_dirs}" architecture_flag)
+ if(architecture_flag)
+ set(CMAKE_${lang}_LIBRARY_ARCHITECTURE "${architecture_flag}" PARENT_SCOPE)
endif()
else()
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index 937a1206b..1595cfd73 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -1,6 +1,17 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+macro(__determine_compiler_id_test testflags_in userflags)
+ separate_arguments(testflags UNIX_COMMAND "${testflags_in}")
+ CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${testflags}" "${userflags}" "${src}")
+ CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
+
+ if(NOT CMAKE_${lang}_COMPILER_ID)
+ foreach(file ${COMPILER_${lang}_PRODUCED_FILES})
+ CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}")
+ endforeach()
+ endif()
+endmacro()
# Function to compile a source file to identify the compiler. This is
# used internally by CMake and should not be included by user code.
@@ -24,29 +35,36 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
# Compute the directory in which to run the test.
set(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_PLATFORM_INFO_DIR}/CompilerId${lang})
- # Try building with no extra flags and then try each set
- # of helper flags. Stop when the compiler is identified.
- foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
- foreach(testflags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}
- ""
- ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
- separate_arguments(testflags UNIX_COMMAND "${testflags}")
- CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${testflags}" "${userflags}" "${src}")
- CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
+ # If we REQUIRE_SUCCESS, i.e. TEST_FLAGS_FIRST has the correct flags, we still need to
+ # try two combinations: with COMPILER_ID_FLAGS (from user) and without (see issue #21869).
+ if(CMAKE_${lang}_COMPILER_ID_REQUIRE_SUCCESS)
+ # If there COMPILER_ID_FLAGS is empty we can error for the first invocation.
+ if("${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" STREQUAL "")
+ set(__compiler_id_require_success TRUE)
+ endif()
+
+ foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
+ __determine_compiler_id_test("${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}" "${userflags}")
if(CMAKE_${lang}_COMPILER_ID)
break()
endif()
- foreach(file ${COMPILER_${lang}_PRODUCED_FILES})
- CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}")
+ set(__compiler_id_require_success TRUE)
+ endforeach()
+ else()
+ # Try building with no extra flags and then try each set
+ # of helper flags. Stop when the compiler is identified.
+ foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
+ foreach(testflags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST} "" ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
+ __determine_compiler_id_test("${testflags}" "${userflags}")
+ if(CMAKE_${lang}_COMPILER_ID)
+ break()
+ endif()
endforeach()
if(CMAKE_${lang}_COMPILER_ID)
break()
endif()
endforeach()
- if(CMAKE_${lang}_COMPILER_ID)
- break()
- endif()
- endforeach()
+ endif()
# Check if compiler id detection gave us the compiler tool.
if(CMAKE_${lang}_COMPILER_ID_TOOL)
@@ -152,7 +170,10 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
set(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
endif()
- if(CMAKE_GENERATOR MATCHES "^Ninja" AND MSVC_${lang}_ARCHITECTURE_ID)
+ if((CMAKE_GENERATOR MATCHES "^Ninja"
+ OR ((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"))
+ AND MSVC_${lang}_ARCHITECTURE_ID)
foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang} "${userflags}")
endforeach()
@@ -161,7 +182,8 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
endif()
set(_variant "")
- if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang")
+ if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang"
+ OR "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xIntelLLVM")
if("x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC")
if(CMAKE_GENERATOR MATCHES "Visual Studio")
set(CMAKE_${lang}_COMPILER_FRONTEND_VARIANT "MSVC")
@@ -276,6 +298,16 @@ 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
+ # 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")
+ set(id_cl dpcpp.exe)
+ elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler 2021")
+ set(id_cl icx.exe)
+ elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler")
+ set(id_cl icl.exe)
+ endif()
else()
set(id_cl cl.exe)
endif()
@@ -310,9 +342,6 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(id_toolset "<NdkToolchainVersion>${CMAKE_VS_PLATFORM_TOOLSET}</NdkToolchainVersion>")
else()
set(id_toolset "<PlatformToolset>${CMAKE_VS_PLATFORM_TOOLSET}</PlatformToolset>")
- if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel")
- set(id_cl icl.exe)
- endif()
if(CMAKE_VS_PLATFORM_TOOLSET_VERSION)
set(id_sep "\\")
if(CMAKE_VS_PLATFORM_TOOLSET_VERSION VERSION_GREATER_EQUAL "14.20")
@@ -642,7 +671,7 @@ ${CMAKE_${lang}_COMPILER_ID_OUTPUT}
# Some languages may know the correct/desired set of flags and want to fail right away if they don't work.
# This is currently only used by CUDA.
- if(CMAKE_${lang}_COMPILER_ID_REQUIRE_SUCCESS)
+ if(__compiler_id_require_success)
message(FATAL_ERROR "${MSG}")
endif()
@@ -901,12 +930,17 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
# # COFF (.exe) files start with "MZ"
# if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
-# set(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE STRING "Executable file format")
+# set(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE INTERNAL "Executable file format")
# endif()
#
# Mach-O files start with MH_MAGIC or MH_CIGAM
if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface|cefaedfe|feedfacf|cffaedfe")
- set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
+ set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE INTERNAL "Executable file format")
+ endif()
+
+ # XCOFF files start with 0x01 followed by 0xDF (32-bit) or 0xF7 (64-bit).
+ if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "^01(df|f7)")
+ set(CMAKE_EXECUTABLE_FORMAT "XCOFF" CACHE INTERNAL "Executable file format")
endif()
endif()
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index 8a574086e..d7d032c01 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -59,6 +59,8 @@ else()
# af77: Apogee F77 compiler for Intergraph hardware running CLIX
# epcf90: "Edinburgh Portable Compiler" F90
# fort: Compaq (now HP) Fortran 90/95 compiler for Tru64 and Linux/Alpha
+ # ifx: Intel Fortran LLVM-based compiler
+ # ifort: Intel Classic Fortran compiler
# ifc: Intel Fortran 95 compiler for Linux/x86
# efc: Intel Fortran 95 compiler for IA64
# nagfor: NAG Fortran compiler
@@ -68,14 +70,14 @@ else()
# so if you paid for a compiler it is picked by default.
if(CMAKE_HOST_WIN32)
set(CMAKE_Fortran_COMPILER_LIST
- ifort pgf95 pgfortran lf95 fort
+ ifort ifx pgf95 pgfortran lf95 fort
flang gfortran gfortran-4 g95 f90 pgf90
pgf77 g77 f77 nag
)
else()
set(CMAKE_Fortran_COMPILER_LIST
ftn
- ifort ifc efc pgf95 pgfortran lf95 xlf95 fort
+ ifort ifc ifx efc pgf95 pgfortran lf95 xlf95 fort
flang gfortran gfortran-4 g95 f90 pgf90
frt pgf77 xlf g77 f77 nag
)
@@ -83,7 +85,7 @@ else()
# Vendor-specific compiler names.
set(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77)
- set(_Fortran_COMPILER_NAMES_Intel ifort ifc efc)
+ set(_Fortran_COMPILER_NAMES_Intel ifort ifc efc ifx)
set(_Fortran_COMPILER_NAMES_Absoft af95 af90 af77)
set(_Fortran_COMPILER_NAMES_PGI pgf95 pgfortran pgf90 pgf77)
set(_Fortran_COMPILER_NAMES_Flang flang)
diff --git a/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake b/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake
index 11f4a29b4..f90301be9 100644
--- a/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake
+++ b/Modules/CMakeExtraGeneratorDetermineCompilerMacrosAndIncludeDirs.cmake
@@ -88,7 +88,7 @@ set(ENV{LANG} C)
# Now check for C, works for gcc and Intel compiler at least
if (NOT CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS)
- if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Intel OR CMAKE_C_COMPILER_ID MATCHES Clang)
+ if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES "Intel" OR CMAKE_C_COMPILER_ID MATCHES Clang)
_DETERMINE_GCC_SYSTEM_INCLUDE_DIRS(c _dirs _defines)
set(CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS "${_dirs}" CACHE INTERNAL "C compiler system include directories")
set(CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS "${_defines}" CACHE INTERNAL "C compiler system defined macros")
@@ -99,7 +99,7 @@ endif ()
# And now the same for C++
if (NOT CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS)
- if ("${CMAKE_CXX_COMPILER_ID}" MATCHES GNU OR "${CMAKE_CXX_COMPILER_ID}" MATCHES Intel OR "${CMAKE_CXX_COMPILER_ID}" MATCHES Clang)
+ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES GNU OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES Clang)
_DETERMINE_GCC_SYSTEM_INCLUDE_DIRS(c++ _dirs _defines)
set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS "${_dirs}" CACHE INTERNAL "CXX compiler system include directories")
set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "${_defines}" CACHE INTERNAL "CXX compiler system defined macros")
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index d81fd1158..ff178f647 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -70,17 +70,18 @@ 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"))
+ set(_CMAKE_LINKER_NAMES "link")
+ set(_CMAKE_AR_NAMES "lib")
+ set(_CMAKE_MT_NAMES "mt")
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xClang")
- find_program(CMAKE_NM NAMES ${_CMAKE_TOOLCHAIN_PREFIX}nm llvm-nm HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- set(_CMAKE_ADDITIONAL_LINKER_NAMES "lld-link")
- set(_CMAKE_ADDITIONAL_AR_NAMES "llvm-lib")
+ 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(APPEND _CMAKE_TOOL_VARS NM)
endif()
- find_program(CMAKE_LINKER NAMES ${_CMAKE_ADDITIONAL_LINKER_NAMES} link HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_AR NAMES ${_CMAKE_ADDITIONAL_AR_NAMES} lib HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_MT NAMES mt HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
-
- list(APPEND _CMAKE_TOOL_VARS LINKER MT)
+ list(APPEND _CMAKE_TOOL_VARS LINKER MT AR)
# in all other cases search for ar, ranlib, etc.
else()
@@ -92,55 +93,54 @@ else()
endif()
if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang)
- set(_CMAKE_ADDITIONAL_AR_NAMES "llvm-ar")
- set(_CMAKE_ADDITIONAL_RANLIB_NAMES "llvm-ranlib")
- set(_CMAKE_ADDITIONAL_STRIP_NAMES "llvm-strip")
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC")
- set(_CMAKE_ADDITIONAL_LINKER_NAMES "lld-link")
+ set(_CMAKE_LINKER_NAMES "lld-link")
else()
- set(_CMAKE_ADDITIONAL_LINKER_NAMES "ld.lld")
+ set(_CMAKE_LINKER_NAMES "ld.lld")
endif()
- set(_CMAKE_ADDITIONAL_NM_NAMES "llvm-nm")
- set(_CMAKE_ADDITIONAL_OBJDUMP_NAMES "llvm-objdump")
- set(_CMAKE_ADDITIONAL_OBJCOPY_NAMES "llvm-objcopy")
- set(_CMAKE_ADDITIONAL_READELF_NAMES "llvm-readelf")
- set(_CMAKE_ADDITIONAL_DLLTOOL_NAMES "llvm-dlltool")
- set(_CMAKE_ADDITIONAL_ADDR2LINE_NAMES "llvm-addr2line")
+ list(APPEND _CMAKE_AR_NAMES "llvm-ar")
+ 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")
endif()
- if(NOT CMAKE_CROSSCOMPILING AND NOT "${_CMAKE_TOOLCHAIN_PREFIX}" STREQUAL "")
- list(APPEND _CMAKE_ADDITIONAL_AR_NAMES "ar")
- list(APPEND _CMAKE_ADDITIONAL_RANLIB_NAMES "ranlib")
- list(APPEND _CMAKE_ADDITIONAL_STRIP_NAMES "strip")
- list(APPEND _CMAKE_ADDITIONAL_LINKER_NAMES "ld")
- list(APPEND _CMAKE_ADDITIONAL_NM_NAMES "nm")
- list(APPEND _CMAKE_ADDITIONAL_OBJDUMP_NAMES "objdump")
- list(APPEND _CMAKE_ADDITIONAL_OBJCOPY_NAMES "objcopy")
- list(APPEND _CMAKE_ADDITIONAL_READELF_NAMES "readelf")
- list(APPEND _CMAKE_ADDITIONAL_DLLTOOL_NAMES "dlltool")
- list(APPEND _CMAKE_ADDITIONAL_ADDR2LINE_NAMES "addr2line")
- 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)
+endif()
- find_program(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar${_CMAKE_TOOLCHAIN_SUFFIX} ${_CMAKE_ADDITIONAL_AR_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+foreach(TOOL IN LISTS _CMAKE_TOOL_VARS)
+ foreach(NAME IN LISTS _CMAKE_${TOOL}_NAMES)
+ if(NOT _CMAKE_TOOLCHAIN_PREFIX STREQUAL "")
+ if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "")
+ list(PREPEND _CMAKE_${TOOL}_NAMES ${NAME}${_CMAKE_TOOLCHAIN_SUFFIX})
+ endif()
+ list(PREPEND _CMAKE_${TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${NAME})
+ endif()
+ if(NOT _CMAKE_TOOLCHAIN_SUFFIX STREQUAL "")
+ list(PREPEND _CMAKE_${TOOL}_NAMES ${_CMAKE_TOOLCHAIN_PREFIX}${NAME}${_CMAKE_TOOLCHAIN_SUFFIX})
+ endif()
+ endforeach()
+ find_program(CMAKE_${TOOL} NAMES ${_CMAKE_${TOOL}_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+endforeach()
- find_program(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib ${_CMAKE_ADDITIONAL_RANLIB_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- if(NOT CMAKE_RANLIB)
+if(NOT CMAKE_RANLIB)
set(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib")
- endif()
-
-
- find_program(CMAKE_STRIP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}strip${_CMAKE_TOOLCHAIN_SUFFIX} ${_CMAKE_ADDITIONAL_STRIP_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_LINKER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ld ${_CMAKE_ADDITIONAL_LINKER_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_NM NAMES ${_CMAKE_TOOLCHAIN_PREFIX}nm ${_CMAKE_ADDITIONAL_NM_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_OBJDUMP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objdump ${_CMAKE_ADDITIONAL_OBJDUMP_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_OBJCOPY NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objcopy ${_CMAKE_ADDITIONAL_OBJCOPY_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_READELF NAMES ${_CMAKE_TOOLCHAIN_PREFIX}readelf ${_CMAKE_ADDITIONAL_READELF_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_DLLTOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}dlltool ${_CMAKE_ADDITIONAL_DLLTOOL_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- find_program(CMAKE_ADDR2LINE NAMES ${_CMAKE_TOOLCHAIN_PREFIX}addr2line ${_CMAKE_ADDITIONAL_ADDR2LINE_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
-
- list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE)
endif()
+
if(CMAKE_PLATFORM_HAS_INSTALLNAME)
find_program(CMAKE_INSTALL_NAME_TOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}install_name_tool HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
@@ -157,7 +157,7 @@ foreach(var IN LISTS _CMAKE_TOOL_VARS)
if(_CMAKE_TOOL_CACHED)
mark_as_advanced(CMAKE_${var})
endif()
- unset(_CMAKE_ADDITIONAL_${var}_NAMES)
+ unset(_CMAKE_${var}_NAMES)
endforeach()
unset(_CMAKE_TOOL_VARS)
unset(_CMAKE_TOOL_CACHED)
diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in
index 6b51e3803..0a3db4cf6 100644
--- a/Modules/CMakeFortranCompilerId.F.in
+++ b/Modules/CMakeFortranCompilerId.F.in
@@ -22,7 +22,21 @@
PRINT *, 'INFO:simulate_version[013.00]'
# endif
#endif
-#if defined(__INTEL_COMPILER) || defined(__ICC)
+#if defined(__INTEL_LLVM_COMPILER)
+ 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.
+# if __INTEL_LLVM_COMPILER < 1000000
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
+# else
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
+# endif
+#elif defined(__INTEL_COMPILER) || defined(__ICC)
PRINT *, 'INFO:compiler[Intel]'
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
@@ -82,6 +96,23 @@
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
# endif
+#elif defined(__NVCOMPILER) || defined(__NVCOMPILER_LLVM__)
+ PRINT *, 'INFO:compiler[NVHPC]'
+# if defined(__NVCOMPILER_MAJOR__)
+# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
+# else
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# endif
+# if defined(__NVCOMPILER_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
+# else
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# endif
+# if defined(__NVCOMPILER_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
+# elif defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
#elif defined(__PGI)
PRINT *, 'INFO:compiler[PGI]'
# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
diff --git a/Modules/CMakeGraphVizOptions.cmake b/Modules/CMakeGraphVizOptions.cmake
index be4a3be36..708672258 100644
--- a/Modules/CMakeGraphVizOptions.cmake
+++ b/Modules/CMakeGraphVizOptions.cmake
@@ -29,8 +29,9 @@ Graphviz package:
dot -Tpng -o foo.png foo.dot
-The different dependency types ``PUBLIC``, ``INTERFACE`` and ``PRIVATE``
-are represented as solid, dashed and dotted edges.
+.. versionadded:: 3.10
+ The different dependency types ``PUBLIC``, ``INTERFACE`` and ``PRIVATE``
+ are represented as solid, dashed and dotted edges.
Variables specific to the Graphviz support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in
index 155551789..608adce0f 100644
--- a/Modules/CMakeOBJCCompiler.cmake.in
+++ b/Modules/CMakeOBJCCompiler.cmake.in
@@ -45,6 +45,7 @@ endforeach()
# Save compiler ABI information.
set(CMAKE_OBJC_SIZEOF_DATA_PTR "@CMAKE_OBJC_SIZEOF_DATA_PTR@")
set(CMAKE_OBJC_COMPILER_ABI "@CMAKE_OBJC_COMPILER_ABI@")
+set(CMAKE_OBJC_BYTE_ORDER "@CMAKE_OBJC_BYTE_ORDER@")
set(CMAKE_OBJC_LIBRARY_ARCHITECTURE "@CMAKE_OBJC_LIBRARY_ARCHITECTURE@")
if(CMAKE_OBJC_SIZEOF_DATA_PTR)
diff --git a/Modules/CMakeOBJCCompilerABI.m b/Modules/CMakeOBJCCompilerABI.m
index 8fa85117c..0726cd3eb 100644
--- a/Modules/CMakeOBJCCompilerABI.m
+++ b/Modules/CMakeOBJCCompilerABI.m
@@ -12,6 +12,8 @@ int main(int argc, char *argv[])
{
int require = 0;
require += info_sizeof_dptr[argc];
+ require += info_byte_order_big_endian[argc];
+ require += info_byte_order_little_endian[argc];
#if defined(ABI_ID)
require += info_abi[argc];
#endif
diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in
index b6452c464..a24582b8b 100644
--- a/Modules/CMakeOBJCXXCompiler.cmake.in
+++ b/Modules/CMakeOBJCXXCompiler.cmake.in
@@ -11,6 +11,7 @@ set(CMAKE_OBJCXX11_COMPILE_FEATURES "@CMAKE_OBJCXX11_COMPILE_FEATURES@")
set(CMAKE_OBJCXX14_COMPILE_FEATURES "@CMAKE_OBJCXX14_COMPILE_FEATURES@")
set(CMAKE_OBJCXX17_COMPILE_FEATURES "@CMAKE_OBJCXX17_COMPILE_FEATURES@")
set(CMAKE_OBJCXX20_COMPILE_FEATURES "@CMAKE_OBJCXX20_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX23_COMPILE_FEATURES "@CMAKE_OBJCXX23_COMPILE_FEATURES@")
set(CMAKE_OBJCXX_PLATFORM_ID "@CMAKE_OBJCXX_PLATFORM_ID@")
set(CMAKE_OBJCXX_SIMULATE_ID "@CMAKE_OBJCXX_SIMULATE_ID@")
@@ -55,6 +56,7 @@ set(CMAKE_OBJCXX_LINKER_PREFERENCE_PROPAGATES 1)
# Save compiler ABI information.
set(CMAKE_OBJCXX_SIZEOF_DATA_PTR "@CMAKE_OBJCXX_SIZEOF_DATA_PTR@")
set(CMAKE_OBJCXX_COMPILER_ABI "@CMAKE_OBJCXX_COMPILER_ABI@")
+set(CMAKE_OBJCXX_BYTE_ORDER "@CMAKE_OBJCXX_BYTE_ORDER@")
set(CMAKE_OBJCXX_LIBRARY_ARCHITECTURE "@CMAKE_OBJCXX_LIBRARY_ARCHITECTURE@")
if(CMAKE_OBJCXX_SIZEOF_DATA_PTR)
diff --git a/Modules/CMakeOBJCXXCompilerABI.mm b/Modules/CMakeOBJCXXCompilerABI.mm
index 288a58c8d..7b9fefccf 100644
--- a/Modules/CMakeOBJCXXCompilerABI.mm
+++ b/Modules/CMakeOBJCXXCompilerABI.mm
@@ -12,6 +12,8 @@ int main(int argc, char *argv[])
{
int require = 0;
require += info_sizeof_dptr[argc];
+ require += info_byte_order_big_endian[argc];
+ require += info_byte_order_little_endian[argc];
#if defined(ABI_ID)
require += info_abi[argc];
#endif
diff --git a/Modules/CMakeOBJCXXCompilerId.mm.in b/Modules/CMakeOBJCXXCompilerId.mm.in
index fe04de1c6..e2ac35d05 100644
--- a/Modules/CMakeOBJCXXCompilerId.mm.in
+++ b/Modules/CMakeOBJCXXCompilerId.mm.in
@@ -30,7 +30,9 @@ char const* qnxnto = "INFO" ":" "qnxnto[]";
#endif
const char* info_language_dialect_default = "INFO" ":" "dialect_default["
-#if CXX_STD > 201703L
+#if CXX_STD > 202002L
+ "23"
+#elfif CXX_STD > 201703L
"20"
#elif CXX_STD >= 201703L
"17"
diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake
index 36f2f7f1e..ad719ef5a 100644
--- a/Modules/CMakePackageConfigHelpers.cmake
+++ b/Modules/CMakePackageConfigHelpers.cmake
@@ -81,13 +81,14 @@ always relative to the installed location of the package. This works both for
relative and also for absolute locations. For absolute locations it works
only if the absolute location is a subdirectory of ``INSTALL_PREFIX``.
-If the ``INSTALL_PREFIX`` argument is passed, this is used as base path to
-calculate all the relative paths. The ``<path>`` argument must be an absolute
-path. If this argument is not passed, the :variable:`CMAKE_INSTALL_PREFIX`
-variable will be used instead. The default value is good when generating a
-FooConfig.cmake file to use your package from the install tree. When
-generating a FooConfig.cmake file to use your package from the build tree this
-option should be used.
+.. versionadded:: 3.1
+ If the ``INSTALL_PREFIX`` argument is passed, this is used as base path to
+ calculate all the relative paths. The ``<path>`` argument must be an absolute
+ path. If this argument is not passed, the :variable:`CMAKE_INSTALL_PREFIX`
+ variable will be used instead. The default value is good when generating a
+ FooConfig.cmake file to use your package from the install tree. When
+ generating a FooConfig.cmake file to use your package from the build tree this
+ option should be used.
By default ``configure_package_config_file`` also generates two helper macros,
``set_and_check()`` and ``check_required_components()`` into the
@@ -159,23 +160,28 @@ If your project has more elaborated version matching rules, you will need to
write your own custom ``ConfigVersion.cmake`` file instead of using this
macro.
-.. note:: ``COMPATIBILITY_MODE`` ``AnyNewerVersion``, ``SameMajorVersion`` and
- ``SameMinorVersion`` handle the version range if any is specified (see
- :command:`find_package` command for the details). ``ExactVersion`` is
- incompatible with version ranges and will display an author warning if one is
- specified.
-
-If ``ARCH_INDEPENDENT`` is given, the installed package version will be
-considered compatible even if it was built for a different architecture than
-the requested architecture. Otherwise, an architecture check will be performed,
-and the package will be considered compatible only if the architecture matches
-exactly. For example, if the package is built for a 32-bit architecture, the
-package is only considered compatible if it is used on a 32-bit architecture,
-unless ``ARCH_INDEPENDENT`` is given, in which case the package is considered
-compatible on any architecture.
+.. versionadded:: 3.11
+ The ``SameMinorVersion`` compatibility mode.
+
+.. versionadded:: 3.14
+ If ``ARCH_INDEPENDENT`` is given, the installed package version will be
+ considered compatible even if it was built for a different architecture than
+ the requested architecture. Otherwise, an architecture check will be performed,
+ and the package will be considered compatible only if the architecture matches
+ exactly. For example, if the package is built for a 32-bit architecture, the
+ package is only considered compatible if it is used on a 32-bit architecture,
+ unless ``ARCH_INDEPENDENT`` is given, in which case the package is considered
+ compatible on any architecture.
.. note:: ``ARCH_INDEPENDENT`` is intended for header-only libraries or similar
- packages with no binaries.
+ packages with no binaries.
+
+.. versionadded:: 3.19
+ ``COMPATIBILITY_MODE`` ``AnyNewerVersion``, ``SameMajorVersion`` and
+ ``SameMinorVersion`` handle the version range if any is specified
+ (see :command:`find_package` command for the details).
+ ``ExactVersion`` mode is incompatible with version ranges and will display an
+ author warning if one is specified.
Internally, this macro executes :command:`configure_file()` to create the
resulting version file. Depending on the ``COMPATIBILITY``, the corresponding
diff --git a/Modules/CMakeParseLibraryArchitecture.cmake b/Modules/CMakeParseLibraryArchitecture.cmake
new file mode 100644
index 000000000..aa6fd741d
--- /dev/null
+++ b/Modules/CMakeParseLibraryArchitecture.cmake
@@ -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.
+
+cmake_policy(PUSH)
+cmake_policy(SET CMP0053 NEW)
+cmake_policy(SET CMP0054 NEW)
+
+# Function parse implicit linker options.
+# This is used internally by CMake and should not be included by user
+# code.
+
+function(cmake_parse_library_architecture implicit_dirs output_var)
+ unset(library_arch)
+ # Detect library architecture directory name.
+ if(CMAKE_LIBRARY_ARCHITECTURE_REGEX)
+ foreach(dir ${implicit_dirs})
+ if("${dir}" MATCHES "/lib/${CMAKE_LIBRARY_ARCHITECTURE_REGEX}$")
+ get_filename_component(arch "${dir}" NAME)
+ set(library_arch "${arch}")
+ break()
+ endif()
+ endforeach()
+ endif()
+
+ if(CMAKE_LIBRARY_ARCHITECTURE_REGEX_VERSIONED AND NOT library_arch)
+ foreach(dir ${implicit_dirs})
+ if("${dir}" MATCHES "/${CMAKE_LIBRARY_ARCHITECTURE_REGEX_VERSIONED}$")
+ get_filename_component(arch "${dir}" DIRECTORY)
+ get_filename_component(arch "${arch}" NAME)
+ set(library_arch "${arch}")
+ break()
+ endif()
+ endforeach()
+ endif()
+
+ if(CMAKE_CXX_COMPILER_ID STREQUAL QCC)
+ foreach(dir ${implicit_dirs})
+ if (dir MATCHES "/lib$")
+ get_filename_component(assumedArchDir "${dir}" DIRECTORY)
+ get_filename_component(archParentDir "${assumedArchDir}" DIRECTORY)
+ if (archParentDir STREQUAL CMAKE_SYSROOT)
+ get_filename_component(archDirName "${assumedArchDir}" NAME)
+ set(library_arch "${archDirName}")
+ break()
+ endif()
+ endif()
+ endforeach()
+ endif()
+
+ # Return results.
+ if(library_arch)
+ set(${output_var} "${library_arch}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+cmake_policy(POP)
diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in
index 0b81c88eb..1dc12c060 100644
--- a/Modules/CMakePlatformId.h.in
+++ b/Modules/CMakePlatformId.h.in
@@ -116,6 +116,9 @@
# if defined(_M_IA64)
# define ARCHITECTURE_ID "IA64"
+# elif defined(_M_ARM64EC)
+# define ARCHITECTURE_ID "ARM64EC"
+
# elif defined(_M_X64) || defined(_M_AMD64)
# define ARCHITECTURE_ID "x64"
@@ -183,6 +186,9 @@
# elif defined(__ICC8051__)
# define ARCHITECTURE_ID "8051"
+# elif defined(__ICCSTM8__)
+# define ARCHITECTURE_ID "STM8"
+
# else /* unknown architecture */
# define ARCHITECTURE_ID ""
# endif
diff --git a/Modules/CMakeTestGNU.c b/Modules/CMakeTestGNU.c
index 933e5a212..7dcafde66 100644
--- a/Modules/CMakeTestGNU.c
+++ b/Modules/CMakeTestGNU.c
@@ -1,4 +1,5 @@
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#if defined(__GNUC__) && \
+ !(defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER))
void THIS_IS_GNU();
#endif
#ifdef __MINGW32__
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index 7529a1f43..ef5a7d5b1 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -194,6 +194,8 @@ installers. The most commonly-used variables are:
.. variable:: CPACK_PACKAGE_CHECKSUM
+ .. versionadded:: 3.7
+
An algorithm that will be used to generate an additional file with the
checksum of the package. The output file name will be::
@@ -271,6 +273,8 @@ installers. The most commonly-used variables are:
.. variable:: CPACK_VERBATIM_VARIABLES
+ .. versionadded:: 3.4
+
If set to ``TRUE``, values of variables prefixed with ``CPACK_`` will be
escaped before being written to the configuration files, so that the cpack
program receives them exactly as they were specified. If not, characters
@@ -278,6 +282,28 @@ installers. The most commonly-used variables are:
received by the cpack program. Defaults to ``FALSE`` for backwards
compatibility.
+.. variable:: CPACK_THREADS
+
+ .. versionadded:: 3.20
+
+ Number of threads to use when performing parallelized operations, such
+ as compressing the installer package.
+
+ 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.
+ 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.
+
+ .. note::
+
+ Official CMake binaries available on ``cmake.org`` ship with a ``liblzma``
+ that does not support parallel compression.
+
Variables for Source Package Generators
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -356,6 +382,8 @@ The following variables are for advanced uses of CPack:
.. variable:: CPACK_INSTALL_SCRIPTS
+ .. versionadded:: 3.16
+
Extra CMake scripts executed by CPack during its local staging
installation. They are executed before installing the files to be packaged.
The scripts are not called by a standalone install (e.g.: ``make install``).
@@ -372,6 +400,8 @@ The following variables are for advanced uses of CPack:
.. variable:: CPACK_PRE_BUILD_SCRIPTS
+ .. versionadded:: 3.19
+
List of CMake scripts to execute after CPack has installed the files to
be packaged into a staging directory and before producing the package(s)
from those files. See also :variable:`CPACK_INSTALL_SCRIPTS` and
@@ -379,6 +409,8 @@ The following variables are for advanced uses of CPack:
.. variable:: CPACK_POST_BUILD_SCRIPTS
+ .. versionadded:: 3.19
+
List of CMake scripts to execute after CPack has produced the resultant
packages and before copying them back to the build directory.
See also :variable:`CPACK_INSTALL_SCRIPTS`,
@@ -386,6 +418,8 @@ The following variables are for advanced uses of CPack:
.. variable:: CPACK_PACKAGE_FILES
+ .. versionadded:: 3.19
+
List of package files created in the staging directory, with each file
provided as a full absolute path. This variable is populated by CPack
just before invoking the post-build scripts listed in
@@ -734,6 +768,7 @@ _cpack_set_default(CPACK_INSTALL_CMAKE_PROJECTS
"${CMAKE_BINARY_DIR};${CMAKE_PROJECT_NAME};ALL;/")
_cpack_set_default(CPACK_CMAKE_GENERATOR "${CMAKE_GENERATOR}")
_cpack_set_default(CPACK_TOPLEVEL_TAG "${CPACK_SYSTEM_NAME}")
+_cpack_set_default(CPACK_THREADS 1)
# if the user has set CPACK_NSIS_DISPLAY_NAME remember it
if(DEFINED CPACK_NSIS_DISPLAY_NAME)
set(CPACK_NSIS_DISPLAY_NAME_SET TRUE)
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index 6ce0bfcc8..d57cf18ba 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -51,20 +51,28 @@ The module defines the following commands:
of a group to which it belongs.
``ESSENTIAL``
+ .. versionadded:: 3.6
+
if set, then the package manager stays disabled until that
component is updated.
``VIRTUAL``
+ .. versionadded:: 3.8
+
if set, then the component will be hidden from the installer.
It is a equivalent of the ``HIDDEN`` option from the
:command:`cpack_add_component` command.
``FORCED_INSTALLATION``
+ .. versionadded:: 3.8
+
if set, then the component must always be installed.
It is a equivalent of the ``REQUIRED`` option from the
:command:`cpack_add_component` command.
``REQUIRES_ADMIN_RIGHTS``
+ .. versionadded:: 3.8
+
set it if the component needs to be installed with elevated permissions.
``NAME``
@@ -72,14 +80,20 @@ The module defines the following commands:
By default used origin component name.
``DISPLAY_NAME``
+ .. versionadded:: 3.8
+
set to rewrite original name configured by
:command:`cpack_add_component` command.
``DESCRIPTION``
+ .. versionadded:: 3.8
+
set to rewrite original description configured by
:command:`cpack_add_component` command.
``UPDATE_TEXT``
+ .. versionadded:: 3.8
+
will be added to the component description if this is an update to
the component.
@@ -88,22 +102,32 @@ The module defines the following commands:
By default used :variable:`CPACK_PACKAGE_VERSION`.
``RELEASE_DATE``
+ .. versionadded:: 3.8
+
keep empty to auto generate.
``SCRIPT``
is a relative or absolute path to operations script
for this component.
- ``PRIORITY`` | ``SORTING_PRIORITY``
+ ``SORTING_PRIORITY``
+ .. versionadded:: 3.8
+
is priority of the component in the tree.
- The ``PRIORITY`` option is deprecated and will be removed in a future
- version of CMake. Please use ``SORTING_PRIORITY`` option instead.
- ``DEPENDS`` | ``DEPENDENCIES``
+ ``PRIORITY``
+ .. deprecated:: 3.8
+ Old name for ``SORTING_PRIORITY``.
+
+ ``DEPENDS``, ``DEPENDENCIES``
+ .. versionadded:: 3.8
+
list of dependency component or component group identifiers in
QtIFW style.
``AUTO_DEPEND_ON``
+ .. versionadded:: 3.8
+
list of identifiers of component or component group in QtIFW style
that this component has an automatic dependency on.
@@ -112,21 +136,31 @@ The module defines the following commands:
component. You can specify more then one license.
``DEFAULT``
+ .. versionadded:: 3.8
+
Possible values are: TRUE, FALSE, and SCRIPT.
Set to FALSE to disable the component in the installer or to SCRIPT
to resolved during runtime (don't forget add the file of the script
as a value of the ``SCRIPT`` option).
``USER_INTERFACES``
+ .. versionadded:: 3.7
+
is a list of <file_path> ('.ui' files) representing pages to load.
``TRANSLATIONS``
+ .. versionadded:: 3.8
+
is a list of <file_path> ('.qm' files) representing translations to load.
``REPLACES``
+ .. versionadded:: 3.10
+
list of identifiers of component or component group to replace.
``CHECKABLE``
+ .. versionadded:: 3.10
+
Possible values are: TRUE, FALSE.
Set to FALSE if you want to hide the checkbox for an item.
This is useful when only a few subcomponents should be selected
@@ -162,13 +196,19 @@ The module defines the following commands:
command.
``VIRTUAL``
+ .. versionadded:: 3.8
+
if set, then the group will be hidden from the installer.
Note that setting this on a root component does not work.
``FORCED_INSTALLATION``
+ .. versionadded:: 3.8
+
if set, then the group must always be installed.
``REQUIRES_ADMIN_RIGHTS``
+ .. versionadded:: 3.8
+
set it if the component group needs to be installed with elevated
permissions.
@@ -177,14 +217,20 @@ The module defines the following commands:
By default used origin component group name.
``DISPLAY_NAME``
+ .. versionadded:: 3.8
+
set to rewrite original name configured by
:command:`cpack_add_component_group` command.
``DESCRIPTION``
+ .. versionadded:: 3.8
+
set to rewrite original description configured by
:command:`cpack_add_component_group` command.
``UPDATE_TEXT``
+ .. versionadded:: 3.8
+
will be added to the component group description if this is an update to
the component group.
@@ -193,22 +239,30 @@ The module defines the following commands:
By default used :variable:`CPACK_PACKAGE_VERSION`.
``RELEASE_DATE``
+ .. versionadded:: 3.8
+
keep empty to auto generate.
``SCRIPT``
is a relative or absolute path to operations script
for this component group.
- ``PRIORITY`` | ``SORTING_PRIORITY``
+ ``SORTING_PRIORITY``
is priority of the component group in the tree.
- The ``PRIORITY`` option is deprecated and will be removed in a future
- version of CMake. Please use ``SORTING_PRIORITY`` option instead.
- ``DEPENDS`` | ``DEPENDENCIES``
+ ``PRIORITY``
+ .. deprecated:: 3.8
+ Old name for ``SORTING_PRIORITY``.
+
+ ``DEPENDS``, ``DEPENDENCIES``
+ .. versionadded:: 3.8
+
list of dependency component or component group identifiers in
QtIFW style.
``AUTO_DEPEND_ON``
+ .. versionadded:: 3.8
+
list of identifiers of component or component group in QtIFW style
that this component group has an automatic dependency on.
@@ -217,6 +271,8 @@ The module defines the following commands:
component group. You can specify more then one license.
``DEFAULT``
+ .. versionadded:: 3.8
+
Possible values are: TRUE, FALSE, and SCRIPT.
Set to TRUE to preselect the group in the installer
(this takes effect only on groups that have no visible child components)
@@ -224,15 +280,23 @@ The module defines the following commands:
the script as a value of the ``SCRIPT`` option).
``USER_INTERFACES``
+ .. versionadded:: 3.7
+
is a list of <file_path> ('.ui' files) representing pages to load.
``TRANSLATIONS``
+ .. versionadded:: 3.8
+
is a list of <file_path> ('.qm' files) representing translations to load.
``REPLACES``
+ .. versionadded:: 3.10
+
list of identifiers of component or component group to replace.
``CHECKABLE``
+ .. versionadded:: 3.10
+
Possible values are: TRUE, FALSE.
Set to FALSE if you want to hide the checkbox for an item.
This is useful when only a few subcomponents should be selected
@@ -272,6 +336,8 @@ The module defines the following commands:
.. command:: cpack_ifw_update_repository
+ .. versionadded:: 3.6
+
Update QtIFW specific repository from remote repository.
::
@@ -307,6 +373,8 @@ The module defines the following commands:
.. command:: cpack_ifw_add_package_resources
+ .. versionadded:: 3.7
+
Add additional resources in the installer binary.
::
diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake
index 8265bd26e..8f8ebb4b7 100644
--- a/Modules/CTest.cmake
+++ b/Modules/CTest.cmake
@@ -121,15 +121,6 @@ if(BUILD_TESTING)
string(APPEND SUBMIT_URL "${DROP_SITE}${DROP_LOCATION}")
endif()
- find_program(CVSCOMMAND cvs )
- set(CVS_UPDATE_OPTIONS "-d -A -P" CACHE STRING
- "Options passed to the cvs update command.")
- find_program(SVNCOMMAND svn)
- find_program(BZRCOMMAND bzr)
- find_program(HGCOMMAND hg)
- find_program(GITCOMMAND git)
- find_program(P4COMMAND p4)
-
if(NOT UPDATE_TYPE)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CVS")
set(UPDATE_TYPE cvs)
@@ -146,21 +137,29 @@ if(BUILD_TESTING)
string(TOLOWER "${UPDATE_TYPE}" _update_type)
if("${_update_type}" STREQUAL "cvs")
+ find_program(CVSCOMMAND cvs )
+ set(CVS_UPDATE_OPTIONS "-d -A -P" CACHE STRING
+ "Options passed to the cvs update command.")
set(UPDATE_COMMAND "${CVSCOMMAND}")
set(UPDATE_OPTIONS "${CVS_UPDATE_OPTIONS}")
elseif("${_update_type}" STREQUAL "svn")
+ find_program(SVNCOMMAND svn)
set(UPDATE_COMMAND "${SVNCOMMAND}")
set(UPDATE_OPTIONS "${SVN_UPDATE_OPTIONS}")
elseif("${_update_type}" STREQUAL "bzr")
+ find_program(BZRCOMMAND bzr)
set(UPDATE_COMMAND "${BZRCOMMAND}")
set(UPDATE_OPTIONS "${BZR_UPDATE_OPTIONS}")
elseif("${_update_type}" STREQUAL "hg")
+ find_program(HGCOMMAND hg)
set(UPDATE_COMMAND "${HGCOMMAND}")
set(UPDATE_OPTIONS "${HG_UPDATE_OPTIONS}")
elseif("${_update_type}" STREQUAL "git")
+ find_program(GITCOMMAND git)
set(UPDATE_COMMAND "${GITCOMMAND}")
set(UPDATE_OPTIONS "${GIT_UPDATE_OPTIONS}")
elseif("${_update_type}" STREQUAL "p4")
+ find_program(P4COMMAND p4)
set(UPDATE_COMMAND "${P4COMMAND}")
set(UPDATE_OPTIONS "${P4_UPDATE_OPTIONS}")
endif()
@@ -179,12 +178,6 @@ if(BUILD_TESTING)
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rational Software\\Purify\\Setup;InstallFolder]"
DOC "Path to the memory checking command, used for memory error detection."
)
- find_program(SLURM_SBATCH_COMMAND sbatch DOC
- "Path to the SLURM sbatch executable"
- )
- find_program(SLURM_SRUN_COMMAND srun DOC
- "Path to the SLURM srun executable"
- )
set(MEMORYCHECK_SUPPRESSIONS_FILE "" CACHE FILEPATH
"File that contains suppressions for the memory checker")
find_program(COVERAGE_COMMAND gcov DOC
@@ -194,7 +187,14 @@ if(BUILD_TESTING)
"Extra command line flags to pass to the coverage tool")
# set the site name
- site_name(SITE)
+ if(COMMAND cmake_host_system_information)
+ cmake_host_system_information(RESULT _ctest_hostname QUERY HOSTNAME)
+ set(SITE "${_ctest_hostname}" CACHE STRING "Name of the computer/site where compile is being run")
+ unset(_ctest_hostname)
+ else()
+ # This code path is needed for CMake itself during bootstrap.
+ site_name(SITE)
+ endif()
# set the build name
if(NOT BUILDNAME)
set(DART_COMPILER "${CMAKE_CXX_COMPILER}")
@@ -256,8 +256,6 @@ if(BUILD_TESTING)
MAKECOMMAND
MEMORYCHECK_COMMAND
MEMORYCHECK_SUPPRESSIONS_FILE
- SLURM_SBATCH_COMMAND
- SLURM_SRUN_COMMAND
SITE
SVNCOMMAND
)
diff --git a/Modules/CTestCoverageCollectGCOV.cmake b/Modules/CTestCoverageCollectGCOV.cmake
index a01a2fea2..a6fa3a4c6 100644
--- a/Modules/CTestCoverageCollectGCOV.cmake
+++ b/Modules/CTestCoverageCollectGCOV.cmake
@@ -39,7 +39,10 @@ After generating this tar file, it can be sent to CDash for display with the
upload to CDash. Relative paths will be interpreted with respect
to the top-level build directory.
- ``TARBALL_COMPRESSION <option>`` Specify a compression algorithm for the
+ ``TARBALL_COMPRESSION <option>``
+ .. versionadded:: 3.18
+
+ Specify a compression algorithm for the
``TARBALL`` data file. Using this option reduces the size of the data file
before it is submitted to CDash. ``<option>`` must be one of ``GZIP``,
``BZIP2``, ``XZ``, ``ZSTD``, ``FROM_EXT``, or an expression that CMake
@@ -68,15 +71,23 @@ After generating this tar file, it can be sent to CDash for display with the
If not specified, the default option is just ``-b -x``.
``GLOB``
+ .. versionadded:: 3.6
+
Recursively search for .gcda files in build_dir rather than
determining search locations by reading TargetDirectories.txt.
``DELETE``
+ .. versionadded:: 3.6
+
Delete coverage files after they've been packaged into the .tar.
``QUIET``
Suppress non-error messages that otherwise would have been
printed out by this function.
+
+ .. versionadded:: 3.3
+ Added support for the :variable:`CTEST_CUSTOM_COVERAGE_EXCLUDE` variable.
+
#]=======================================================================]
function(ctest_coverage_collect_gcov)
diff --git a/Modules/CTestUseLaunchers.cmake b/Modules/CTestUseLaunchers.cmake
index 3dff92605..23a206b2a 100644
--- a/Modules/CTestUseLaunchers.cmake
+++ b/Modules/CTestUseLaunchers.cmake
@@ -24,9 +24,12 @@ long as your CMakeLists uses include(CTest) or
include(CTestUseLaunchers), it will use the value of the ENV variable
to initialize a CTEST_USE_LAUNCHERS cache variable. This cache
variable initialization only occurs if CTEST_USE_LAUNCHERS is not
-already defined. If CTEST_USE_LAUNCHERS is on in a ctest -S script
-the ctest_configure command will add -DCTEST_USE_LAUNCHERS:BOOL=TRUE
-to the cmake command used to configure the project.
+already defined.
+
+.. versionadded:: 3.8
+ If CTEST_USE_LAUNCHERS is on in a ctest -S script
+ the ctest_configure command will add -DCTEST_USE_LAUNCHERS:BOOL=TRUE
+ to the cmake command used to configure the project.
#]=======================================================================]
if(NOT DEFINED CTEST_USE_LAUNCHERS AND DEFINED ENV{CTEST_USE_LAUNCHERS_DEFAULT})
diff --git a/Modules/CheckCSourceCompiles.cmake b/Modules/CheckCSourceCompiles.cmake
index 698a007eb..b24da49bc 100644
--- a/Modules/CheckCSourceCompiles.cmake
+++ b/Modules/CheckCSourceCompiles.cmake
@@ -44,6 +44,8 @@ Check if given C source compiles and links into an executable.
directory property will be ignored.
``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+
A :ref:`;-list <CMake Language Lists>` of options to add to the link
command (see :command:`try_compile` for further details).
@@ -54,6 +56,8 @@ Check if given C source compiles and links into an executable.
further details).
``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+
If this variable evaluates to a boolean true value, all status messages
associated with the check will be suppressed.
diff --git a/Modules/CheckCSourceRuns.cmake b/Modules/CheckCSourceRuns.cmake
index a99e47e83..a6081ff46 100644
--- a/Modules/CheckCSourceRuns.cmake
+++ b/Modules/CheckCSourceRuns.cmake
@@ -43,6 +43,8 @@ subsequently be run.
directory property will be ignored.
``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+
A :ref:`;-list <CMake Language Lists>` of options to add to the link
command (see :command:`try_run` for further details).
@@ -53,6 +55,8 @@ subsequently be run.
further details).
``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+
If this variable evaluates to a boolean true value, all status messages
associated with the check will be suppressed.
diff --git a/Modules/CheckCXXSourceCompiles.cmake b/Modules/CheckCXXSourceCompiles.cmake
index dc209b268..502bfa76e 100644
--- a/Modules/CheckCXXSourceCompiles.cmake
+++ b/Modules/CheckCXXSourceCompiles.cmake
@@ -44,6 +44,8 @@ Check if given C++ source compiles and links into an executable.
directory property will be ignored.
``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+
A :ref:`;-list <CMake Language Lists>` of options to add to the link
command (see :command:`try_compile` for further details).
@@ -54,6 +56,8 @@ Check if given C++ source compiles and links into an executable.
further details).
``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+
If this variable evaluates to a boolean true value, all status messages
associated with the check will be suppressed.
diff --git a/Modules/CheckCXXSourceRuns.cmake b/Modules/CheckCXXSourceRuns.cmake
index c8ff3d7bf..af03453d9 100644
--- a/Modules/CheckCXXSourceRuns.cmake
+++ b/Modules/CheckCXXSourceRuns.cmake
@@ -43,6 +43,8 @@ subsequently be run.
directory property will be ignored.
``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+
A :ref:`;-list <CMake Language Lists>` of options to add to the link
command (see :command:`try_run` for further details).
@@ -53,6 +55,8 @@ subsequently be run.
further details).
``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+
If this variable evaluates to a boolean true value, all status messages
associated with the check will be suppressed.
diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index 5c9079dbf..b4da4fac8 100644
--- a/Modules/CheckCXXSymbolExists.cmake
+++ b/Modules/CheckCXXSymbolExists.cmake
@@ -49,12 +49,14 @@ the way the check is run:
a :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler.
``CMAKE_REQUIRED_LINK_OPTIONS``
- a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
+ .. versionadded:: 3.14
+ a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
``CMAKE_REQUIRED_LIBRARIES``
a :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. See policy :policy:`CMP0075`.
``CMAKE_REQUIRED_QUIET``
- execute quietly without messages.
+ .. versionadded:: 3.1
+ execute quietly without messages.
For example:
diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake
index d06203fc2..ad72e2f09 100644
--- a/Modules/CheckFortranFunctionExists.cmake
+++ b/Modules/CheckFortranFunctionExists.cmake
@@ -24,8 +24,9 @@ The following variables may be set before calling this macro to modify
the way the check is run:
``CMAKE_REQUIRED_LINK_OPTIONS``
- A :ref:`;-list <CMake Language Lists>` of options to add to the link
- command (see :command:`try_compile` for further details).
+ .. versionadded:: 3.14
+ A :ref:`;-list <CMake Language Lists>` of options to add to the link
+ command (see :command:`try_compile` for further details).
``CMAKE_REQUIRED_LIBRARIES``
A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
diff --git a/Modules/CheckFortranSourceCompiles.cmake b/Modules/CheckFortranSourceCompiles.cmake
index 5ede28457..e1343293b 100644
--- a/Modules/CheckFortranSourceCompiles.cmake
+++ b/Modules/CheckFortranSourceCompiles.cmake
@@ -65,6 +65,8 @@ Check if given Fortran source compiles and links into an executable.
directory property will be ignored.
``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+
A :ref:`;-list <CMake Language Lists>` of options to add to the link
command (see :command:`try_compile` for further details).
diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake
index 136da89d9..9efa132b4 100644
--- a/Modules/CheckFunctionExists.cmake
+++ b/Modules/CheckFunctionExists.cmake
@@ -28,12 +28,14 @@ way the check is run:
a :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler.
``CMAKE_REQUIRED_LINK_OPTIONS``
- a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
+ .. versionadded:: 3.14
+ a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
``CMAKE_REQUIRED_LIBRARIES``
a :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. See policy :policy:`CMP0075`.
``CMAKE_REQUIRED_QUIET``
- execute quietly without messages.
+ .. versionadded:: 3.1
+ execute quietly without messages.
.. note::
diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake
index 1dd951d83..0bc3c9233 100644
--- a/Modules/CheckIPOSupported.cmake
+++ b/Modules/CheckIPOSupported.cmake
@@ -33,6 +33,9 @@ property.
It makes no sense to use this module when :policy:`CMP0069` is set to ``OLD`` so
module will return error in this case. See policy :policy:`CMP0069` for details.
+.. versionadded:: 3.13
+ Add support for Visual Studio generators.
+
Examples
^^^^^^^^
diff --git a/Modules/CheckIncludeFile.cmake b/Modules/CheckIncludeFile.cmake
index 3a104736c..71ddde7f2 100644
--- a/Modules/CheckIncludeFile.cmake
+++ b/Modules/CheckIncludeFile.cmake
@@ -29,12 +29,14 @@ the way the check is run:
a :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler.
``CMAKE_REQUIRED_LINK_OPTIONS``
- a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
+ .. versionadded:: 3.14
+ a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
``CMAKE_REQUIRED_LIBRARIES``
a :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. See policy :policy:`CMP0075`.
``CMAKE_REQUIRED_QUIET``
- execute quietly without messages.
+ .. versionadded:: 3.1
+ execute quietly without messages.
See the :module:`CheckIncludeFiles` module to check for multiple headers
at once. See the :module:`CheckIncludeFileCXX` module to check for headers
diff --git a/Modules/CheckIncludeFileCXX.cmake b/Modules/CheckIncludeFileCXX.cmake
index 496550fa8..953224e76 100644
--- a/Modules/CheckIncludeFileCXX.cmake
+++ b/Modules/CheckIncludeFileCXX.cmake
@@ -29,12 +29,14 @@ the way the check is run:
a :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler.
``CMAKE_REQUIRED_LINK_OPTIONS``
- a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
+ .. versionadded:: 3.14
+ a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
``CMAKE_REQUIRED_LIBRARIES``
a :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. See policy :policy:`CMP0075`.
``CMAKE_REQUIRED_QUIET``
- execute quietly without messages.
+ .. versionadded:: 3.1
+ execute quietly without messages.
See modules :module:`CheckIncludeFile` and :module:`CheckIncludeFiles`
to check for one or more ``C`` headers.
diff --git a/Modules/CheckIncludeFiles.cmake b/Modules/CheckIncludeFiles.cmake
index 8e10cd6ab..1800ca888 100644
--- a/Modules/CheckIncludeFiles.cmake
+++ b/Modules/CheckIncludeFiles.cmake
@@ -35,12 +35,14 @@ the way the check is run:
a :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler.
``CMAKE_REQUIRED_LINK_OPTIONS``
- a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
+ .. versionadded:: 3.14
+ a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
``CMAKE_REQUIRED_LIBRARIES``
a :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. See policy :policy:`CMP0075`.
``CMAKE_REQUIRED_QUIET``
- execute quietly without messages.
+ .. versionadded:: 3.1
+ execute quietly without messages.
See modules :module:`CheckIncludeFile` and :module:`CheckIncludeFileCXX`
to check for a single header file in ``C`` or ``CXX`` languages.
diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake
index 44387d4b4..928881cab 100644
--- a/Modules/CheckLanguage.cmake
+++ b/Modules/CheckLanguage.cmake
@@ -68,6 +68,11 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
else()
set(_D_CMAKE_MAKE_PROGRAM "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
endif()
+ if(CMAKE_TOOLCHAIN_FILE)
+ set(_D_CMAKE_TOOLCHAIN_FILE "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE}")
+ else()
+ set(_D_CMAKE_TOOLCHAIN_FILE "")
+ endif()
execute_process(
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
@@ -75,6 +80,7 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
-T "${CMAKE_GENERATOR_TOOLSET}"
${_D_CMAKE_GENERATOR_INSTANCE}
${_D_CMAKE_MAKE_PROGRAM}
+ ${_D_CMAKE_TOOLCHAIN_FILE}
OUTPUT_VARIABLE _cl_output
ERROR_VARIABLE _cl_output
RESULT_VARIABLE _cl_result
diff --git a/Modules/CheckLibraryExists.cmake b/Modules/CheckLibraryExists.cmake
index 6470dfd04..804e0cbba 100644
--- a/Modules/CheckLibraryExists.cmake
+++ b/Modules/CheckLibraryExists.cmake
@@ -26,13 +26,18 @@ Check if the function exists.
The following variables may be set before calling this macro to modify
the way the check is run:
-::
-
- CMAKE_REQUIRED_FLAGS = string of compile command line flags
- CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
- CMAKE_REQUIRED_LINK_OPTIONS = list of options to pass to link command
- CMAKE_REQUIRED_LIBRARIES = list of libraries to link
- CMAKE_REQUIRED_QUIET = execute quietly without messages
+``CMAKE_REQUIRED_FLAGS``
+ string of compile command line flags.
+``CMAKE_REQUIRED_DEFINITIONS``
+ list of macros to define (-DFOO=bar).
+``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+ list of options to pass to link command.
+``CMAKE_REQUIRED_LIBRARIES``
+ list of libraries to link.
+``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+ execute quietly without messages.
#]=======================================================================]
include_guard(GLOBAL)
diff --git a/Modules/CheckPrototypeDefinition.cmake b/Modules/CheckPrototypeDefinition.cmake
index 8b06403d7..d29c5e89f 100644
--- a/Modules/CheckPrototypeDefinition.cmake
+++ b/Modules/CheckPrototypeDefinition.cmake
@@ -35,14 +35,20 @@ Check if the prototype we expect is correct.
The following variables may be set before calling this function to modify
the way the check is run:
-::
-
- CMAKE_REQUIRED_FLAGS = string of compile command line flags
- CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
- CMAKE_REQUIRED_INCLUDES = list of include directories
- CMAKE_REQUIRED_LINK_OPTIONS = list of options to pass to link command
- CMAKE_REQUIRED_LIBRARIES = list of libraries to link
- CMAKE_REQUIRED_QUIET = execute quietly without messages
+``CMAKE_REQUIRED_FLAGS``
+ string of compile command line flags.
+``CMAKE_REQUIRED_DEFINITIONS``
+ list of macros to define (-DFOO=bar).
+``CMAKE_REQUIRED_INCLUDES``
+ list of include directories.
+``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+ list of options to pass to link command.
+``CMAKE_REQUIRED_LIBRARIES``
+ list of libraries to link.
+``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+ execute quietly without messages.
#]=======================================================================]
#
diff --git a/Modules/CheckStructHasMember.cmake b/Modules/CheckStructHasMember.cmake
index 842a8fdb7..8217c84c2 100644
--- a/Modules/CheckStructHasMember.cmake
+++ b/Modules/CheckStructHasMember.cmake
@@ -23,18 +23,23 @@ Check if the given struct or class has the specified member variable
<language> - the compiler to use (C or CXX)
-
The following variables may be set before calling this macro to modify
the way the check is run:
-::
-
- CMAKE_REQUIRED_FLAGS = string of compile command line flags
- CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
- CMAKE_REQUIRED_INCLUDES = list of include directories
- CMAKE_REQUIRED_LINK_OPTIONS = list of options to pass to link command
- CMAKE_REQUIRED_LIBRARIES = list of libraries to link
- CMAKE_REQUIRED_QUIET = execute quietly without messages
+``CMAKE_REQUIRED_FLAGS``
+ string of compile command line flags.
+``CMAKE_REQUIRED_DEFINITIONS``
+ list of macros to define (-DFOO=bar).
+``CMAKE_REQUIRED_INCLUDES``
+ list of include directories.
+``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+ list of options to pass to link command.
+``CMAKE_REQUIRED_LIBRARIES``
+ list of libraries to link.
+``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+ execute quietly without messages.
Example:
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index 4f202c41d..f8ca58402 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -39,12 +39,14 @@ the way the check is run:
a :ref:`;-list <CMake Language Lists>` of header search paths to pass to
the compiler.
``CMAKE_REQUIRED_LINK_OPTIONS``
- a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
+ .. versionadded:: 3.14
+ a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
``CMAKE_REQUIRED_LIBRARIES``
a :ref:`;-list <CMake Language Lists>` of libraries to add to the link
command. See policy :policy:`CMP0075`.
``CMAKE_REQUIRED_QUIET``
- execute quietly without messages.
+ .. versionadded:: 3.1
+ execute quietly without messages.
For example:
diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake
index 17beadcb1..69f68f9d4 100644
--- a/Modules/CheckTypeSize.cmake
+++ b/Modules/CheckTypeSize.cmake
@@ -57,19 +57,25 @@ member you can do something like this:
check_type_size("((struct something*)0)->member" SIZEOF_MEMBER)
-
The following variables may be set before calling this macro to modify
the way the check is run:
-::
-
- CMAKE_REQUIRED_FLAGS = string of compile command line flags
- CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
- CMAKE_REQUIRED_INCLUDES = list of include directories
- CMAKE_REQUIRED_LINK_OPTIONS = list of options to pass to link command
- CMAKE_REQUIRED_LIBRARIES = list of libraries to link
- CMAKE_REQUIRED_QUIET = execute quietly without messages
- CMAKE_EXTRA_INCLUDE_FILES = list of extra headers to include
+``CMAKE_REQUIRED_FLAGS``
+ string of compile command line flags.
+``CMAKE_REQUIRED_DEFINITIONS``
+ list of macros to define (-DFOO=bar).
+``CMAKE_REQUIRED_INCLUDES``
+ list of include directories.
+``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+ list of options to pass to link command.
+``CMAKE_REQUIRED_LIBRARIES``
+ list of libraries to link.
+``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+ execute quietly without messages.
+``CMAKE_EXTRA_INCLUDE_FILES``
+ list of extra headers to include.
#]=======================================================================]
include(CheckIncludeFile)
diff --git a/Modules/CheckVariableExists.cmake b/Modules/CheckVariableExists.cmake
index 8a9353524..7420124f4 100644
--- a/Modules/CheckVariableExists.cmake
+++ b/Modules/CheckVariableExists.cmake
@@ -26,13 +26,18 @@ Check if the variable exists.
The following variables may be set before calling this macro to modify
the way the check is run:
-::
-
- CMAKE_REQUIRED_FLAGS = string of compile command line flags
- CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
- CMAKE_REQUIRED_LINK_OPTIONS = list of options to pass to link command
- CMAKE_REQUIRED_LIBRARIES = list of libraries to link
- CMAKE_REQUIRED_QUIET = execute quietly without messages
+``CMAKE_REQUIRED_FLAGS``
+ string of compile command line flags.
+``CMAKE_REQUIRED_DEFINITIONS``
+ list of macros to define (-DFOO=bar).
+``CMAKE_REQUIRED_LINK_OPTIONS``
+ .. versionadded:: 3.14
+ list of options to pass to link command.
+``CMAKE_REQUIRED_LIBRARIES``
+ list of libraries to link.
+``CMAKE_REQUIRED_QUIET``
+ .. versionadded:: 3.1
+ execute quietly without messages.
#]=======================================================================]
include_guard(GLOBAL)
diff --git a/Modules/Compiler/ARMCC.cmake b/Modules/Compiler/ARMCC.cmake
index f94956821..f4f1854a1 100644
--- a/Modules/Compiler/ARMCC.cmake
+++ b/Modules/Compiler/ARMCC.cmake
@@ -33,7 +33,7 @@ macro(__compiler_armcc lang)
set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> -o <TARGET> --list <TARGET_BASE>.map")
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> --create -cr <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_DEPFILE_FLAGS_${lang} "--depend=<DEPFILE> --depend_single_line --no_depend_system_headers")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "--depend=<DEP_FILE> --depend_single_line --no_depend_system_headers")
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ")
endmacro()
diff --git a/Modules/Compiler/AppleClang-C.cmake b/Modules/Compiler/AppleClang-C.cmake
index 2794f52bb..bd9819350 100644
--- a/Modules/Compiler/AppleClang-C.cmake
+++ b/Modules/Compiler/AppleClang-C.cmake
@@ -1,6 +1,19 @@
include(Compiler/Clang)
__compiler_clang(C)
+
+if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_C_DEPFILE_FORMAT gcc)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+ endif()
+endif()
+
+set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c)
+
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0)
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
diff --git a/Modules/Compiler/AppleClang-CXX.cmake b/Modules/Compiler/AppleClang-CXX.cmake
index 15edc21e9..28be1dfd5 100644
--- a/Modules/Compiler/AppleClang-CXX.cmake
+++ b/Modules/Compiler/AppleClang-CXX.cmake
@@ -1,7 +1,17 @@
include(Compiler/Clang)
__compiler_clang(CXX)
+set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++)
+
if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_CXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+ endif()
+
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
endif()
diff --git a/Modules/Compiler/AppleClang-OBJC.cmake b/Modules/Compiler/AppleClang-OBJC.cmake
index d1f37062e..d4eab4f63 100644
--- a/Modules/Compiler/AppleClang-OBJC.cmake
+++ b/Modules/Compiler/AppleClang-OBJC.cmake
@@ -1,5 +1,14 @@
include(Compiler/Clang-OBJC)
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles"
+ AND CMAKE_DEPFILE_FLAGS_OBJC)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_OBJC_DEPFILE_FORMAT gcc)
+ set(CMAKE_OBJC_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+
if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.0)
set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
diff --git a/Modules/Compiler/AppleClang-OBJCXX.cmake b/Modules/Compiler/AppleClang-OBJCXX.cmake
index 409bd4a2e..172a3438c 100644
--- a/Modules/Compiler/AppleClang-OBJCXX.cmake
+++ b/Modules/Compiler/AppleClang-OBJCXX.cmake
@@ -1,5 +1,15 @@
include(Compiler/Clang-OBJCXX)
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles"
+ AND CMAKE_DEPFILE_FLAGS_OBJCXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_OBJCXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_OBJCXX_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+
set(CMAKE_OBJCXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.0)
diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
index 409b65a5f..cd897c527 100644
--- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake
+++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
@@ -93,21 +93,14 @@ endmacro()
# Define to allow compile features to be automatically determined
macro(cmake_record_cxx_compile_features)
set(_result 0)
+ if(_result EQUAL 0 AND DEFINED CMAKE_CXX23_STANDARD_COMPILE_OPTION)
+ _has_compiler_features_cxx(23)
+ endif()
if(_result EQUAL 0 AND DEFINED CMAKE_CXX20_STANDARD_COMPILE_OPTION)
- if(CMAKE_CXX20_STANDARD__HAS_FULL_SUPPORT)
- _has_compiler_features_cxx(20)
- else()
- _record_compiler_features_cxx(20)
- endif()
- unset(CMAKE_CXX20_STANDARD__HAS_FULL_SUPPORT)
+ _has_compiler_features_cxx(20)
endif()
if(_result EQUAL 0 AND DEFINED CMAKE_CXX17_STANDARD_COMPILE_OPTION)
- if(CMAKE_CXX17_STANDARD__HAS_FULL_SUPPORT)
- _has_compiler_features_cxx(17)
- else()
- _record_compiler_features_cxx(17)
- endif()
- unset(CMAKE_CXX17_STANDARD__HAS_FULL_SUPPORT)
+ _has_compiler_features_cxx(17)
endif()
if(_result EQUAL 0 AND DEFINED CMAKE_CXX14_STANDARD_COMPILE_OPTION)
if(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT)
@@ -137,21 +130,14 @@ endmacro()
macro(cmake_record_cuda_compile_features)
set(_result 0)
+ if(_result EQUAL 0 AND DEFINED CMAKE_CUDA23_STANDARD_COMPILE_OPTION)
+ _has_compiler_features_cuda(23)
+ endif()
if(_result EQUAL 0 AND DEFINED CMAKE_CUDA20_STANDARD_COMPILE_OPTION)
- if(CMAKE_CUDA20_STANDARD__HAS_FULL_SUPPORT)
- _has_compiler_features_cuda(20)
- else()
- _record_compiler_features_cuda(20)
- endif()
- unset(CMAKE_CUDA20_STANDARD__HAS_FULL_SUPPORT)
+ _has_compiler_features_cuda(20)
endif()
if(_result EQUAL 0 AND DEFINED CMAKE_CUDA17_STANDARD_COMPILE_OPTION)
- if(CMAKE_CUDA17_STANDARD__HAS_FULL_SUPPORT)
- _has_compiler_features_cuda(17)
- else()
- _record_compiler_features_cuda(17)
- endif()
- unset(CMAKE_CUDA17_STANDARD__HAS_FULL_SUPPORT)
+ _has_compiler_features_cuda(17)
endif()
if(_result EQUAL 0 AND DEFINED CMAKE_CUDA14_STANDARD_COMPILE_OPTION)
if(CMAKE_CUDA14_STANDARD__HAS_FULL_SUPPORT)
diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake
index 7c4a263f6..5609abf47 100644
--- a/Modules/Compiler/Clang-C.cmake
+++ b/Modules/Compiler/Clang-C.cmake
@@ -7,7 +7,22 @@ if(APPLE AND NOT appleClangPolicy STREQUAL NEW)
endif()
if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+ endif()
+elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c)
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_C_DEPFILE_FORMAT gcc)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+ endif()
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
diff --git a/Modules/Compiler/Clang-CUDA.cmake b/Modules/Compiler/Clang-CUDA.cmake
index fd8c2b7c9..cafc7ddd1 100644
--- a/Modules/Compiler/Clang-CUDA.cmake
+++ b/Modules/Compiler/Clang-CUDA.cmake
@@ -2,7 +2,13 @@ include(Compiler/Clang)
__compiler_clang(CUDA)
# Set explicitly, because __compiler_clang() doesn't set this if we're simulating MSVC.
-set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <OBJECT> -MF <DEPFILE>")
+set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
+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_CUDA_DEPFILE_FORMAT gcc)
+ set(CMAKE_CUDA_DEPENDS_USE_COMPILER TRUE)
+endif()
# C++03 isn't supported for CXX, but is for CUDA, so we need to set these manually.
# Do this before __compiler_clang_cxx_standards() since that adds the feature.
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake
index 789e99159..98828e011 100644
--- a/Modules/Compiler/Clang-CXX.cmake
+++ b/Modules/Compiler/Clang-CXX.cmake
@@ -3,6 +3,15 @@ __compiler_clang(CXX)
__compiler_clang_cxx_standards(CXX)
if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_CXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+ endif()
+
+ set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++)
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
endif()
@@ -13,4 +22,9 @@ endif()
if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+ endif()
endif()
diff --git a/Modules/Compiler/Clang-FindBinUtils.cmake b/Modules/Compiler/Clang-FindBinUtils.cmake
index b8526600e..e6c469a10 100644
--- a/Modules/Compiler/Clang-FindBinUtils.cmake
+++ b/Modules/Compiler/Clang-FindBinUtils.cmake
@@ -2,6 +2,12 @@ if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL
message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
endif()
+# Ubuntu:
+# * /usr/bin/llvm-ar-9
+# * /usr/bin/llvm-ranlib-9
+string(REGEX MATCH "^([0-9]+)" __version_x
+ "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}")
+
# Debian:
# * /usr/bin/llvm-ar-4.0
# * /usr/bin/llvm-ranlib-4.0
@@ -19,6 +25,7 @@ set(__clang_hints ${__clang_hint_1} ${__clang_hint_2})
# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ar.1.html
find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES
"${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x_y}"
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x}"
"${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar"
HINTS ${__clang_hints}
DOC "LLVM archiver"
@@ -28,6 +35,7 @@ mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR)
# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ranlib.1.html
find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES
"${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x_y}"
+ "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x}"
"${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib"
HINTS ${__clang_hints}
DOC "Generate index for LLVM archive"
diff --git a/Modules/Compiler/Clang-OBJC.cmake b/Modules/Compiler/Clang-OBJC.cmake
index c61c497fc..19179e36e 100644
--- a/Modules/Compiler/Clang-OBJC.cmake
+++ b/Modules/Compiler/Clang-OBJC.cmake
@@ -1,6 +1,15 @@
include(Compiler/Clang)
__compiler_clang(OBJC)
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_OBJC)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_OBJC_DEPFILE_FORMAT gcc)
+ set(CMAKE_OBJC_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+
if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 3.4)
set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
diff --git a/Modules/Compiler/Clang-OBJCXX.cmake b/Modules/Compiler/Clang-OBJCXX.cmake
index 453b5fd7b..9bdff663f 100644
--- a/Modules/Compiler/Clang-OBJCXX.cmake
+++ b/Modules/Compiler/Clang-OBJCXX.cmake
@@ -1,3 +1,11 @@
include(Compiler/Clang)
__compiler_clang(OBJCXX)
__compiler_clang_cxx_standards(OBJCXX)
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_OBJCXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_OBJCXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_OBJCXX_DEPENDS_USE_COMPILER TRUE)
+endif()
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index c43265d58..9f93d4188 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -77,7 +77,7 @@ else()
set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto")
endif()
- if(ANDROID)
+ if(ANDROID AND NOT CMAKE_ANDROID_NDK_VERSION VERSION_GREATER_EQUAL "22")
# https://github.com/android-ndk/ndk/issues/242
set(CMAKE_${lang}_LINK_OPTIONS_IPO "-fuse-ld=gold")
endif()
@@ -154,10 +154,6 @@ macro(__compiler_clang_cxx_standards lang)
set(CMAKE_${lang}17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
endif()
- if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 6.0)
- set(CMAKE_${lang}17_STANDARD__HAS_FULL_SUPPORT ON)
- endif()
-
if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 11.0)
set(CMAKE_${lang}20_STANDARD_COMPILE_OPTION "-std=c++20")
set(CMAKE_${lang}20_EXTENSION_COMPILE_OPTION "-std=gnu++20")
@@ -168,6 +164,11 @@ macro(__compiler_clang_cxx_standards lang)
unset(_clang_version_std17)
+ if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 12.0)
+ set(CMAKE_${lang}23_STANDARD_COMPILE_OPTION "-std=c++2b")
+ set(CMAKE_${lang}23_EXTENSION_COMPILE_OPTION "-std=gnu++2b")
+ endif()
+
if("x${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "xMSVC")
# The MSVC standard library requires C++14, and MSVC itself has no
# notion of operating in a mode not aware of at least that standard.
@@ -179,8 +180,6 @@ macro(__compiler_clang_cxx_standards lang)
# This clang++ is missing some features because of MSVC compatibility.
unset(CMAKE_${lang}11_STANDARD__HAS_FULL_SUPPORT)
unset(CMAKE_${lang}14_STANDARD__HAS_FULL_SUPPORT)
- unset(CMAKE_${lang}17_STANDARD__HAS_FULL_SUPPORT)
- unset(CMAKE_${lang}20_STANDARD__HAS_FULL_SUPPORT)
endif()
__compiler_check_default_language_standard(${lang} 2.1 98)
@@ -220,6 +219,8 @@ macro(__compiler_clang_cxx_standards lang)
set(CMAKE_${lang}17_EXTENSION_COMPILE_OPTION "")
set(CMAKE_${lang}20_STANDARD_COMPILE_OPTION "")
set(CMAKE_${lang}20_EXTENSION_COMPILE_OPTION "")
+ set(CMAKE_${lang}23_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_${lang}23_EXTENSION_COMPILE_OPTION "")
# There is no meaningful default for this
set(CMAKE_${lang}_STANDARD_DEFAULT "")
@@ -235,6 +236,7 @@ macro(__compiler_clang_cxx_standards lang)
cxx_std_14
cxx_std_17
cxx_std_20
+ cxx_std_23
)
_record_compiler_features(${lang} "" CMAKE_${lang}_COMPILE_FEATURES)
endmacro()
diff --git a/Modules/Compiler/Cray-Fortran.cmake b/Modules/Compiler/Cray-Fortran.cmake
index 696ae7607..0d5e1c767 100644
--- a/Modules/Compiler/Cray-Fortran.cmake
+++ b/Modules/Compiler/Cray-Fortran.cmake
@@ -19,3 +19,7 @@ else()
set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-eZ")
set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-dZ")
endif()
+
+if (NOT CMAKE_Fortran_COMPILER_VERSION VERSION_LESS 11.0)
+ set(CMAKE_Fortran_PREPROCESS_SOURCE "<CMAKE_Fortran_COMPILER> -o <PREPROCESSED_SOURCE> <DEFINES> <INCLUDES> <FLAGS> -eP <SOURCE>")
+endif()
diff --git a/Modules/Compiler/GNU-ASM.cmake b/Modules/Compiler/GNU-ASM.cmake
index 94af401da..a93541671 100644
--- a/Modules/Compiler/GNU-ASM.cmake
+++ b/Modules/Compiler/GNU-ASM.cmake
@@ -6,7 +6,7 @@ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;S;asm)
__compiler_gnu(ASM)
if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_MATCH STREQUAL "GNU assembler")
- set(CMAKE_DEPFILE_FLAGS_ASM${ASM_DIALECT} "--MD <DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_ASM${ASM_DIALECT} "--MD <DEP_FILE>")
set(CMAKE_ASM${ASM_DIALECT}_LINK_EXECUTABLE
"<CMAKE_LINKER> <FLAGS> <CMAKE_ASM${ASM_DIALECT}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_ASM_DEFINE_FLAG "--defsym ")
diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake
index ca286b397..86b4d83e5 100644
--- a/Modules/Compiler/GNU-C.cmake
+++ b/Modules/Compiler/GNU-C.cmake
@@ -1,6 +1,17 @@
include(Compiler/GNU)
__compiler_gnu(C)
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_C_DEPFILE_FORMAT gcc)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c)
+
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5)
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake
index fcaaeab43..758d3c783 100644
--- a/Modules/Compiler/GNU-CXX.cmake
+++ b/Modules/Compiler/GNU-CXX.cmake
@@ -1,6 +1,17 @@
include(Compiler/GNU)
__compiler_gnu(CXX)
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_CXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++)
+
if (WIN32)
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport")
diff --git a/Modules/Compiler/GNU-OBJC.cmake b/Modules/Compiler/GNU-OBJC.cmake
index fb9b0b2a5..7eeed833b 100644
--- a/Modules/Compiler/GNU-OBJC.cmake
+++ b/Modules/Compiler/GNU-OBJC.cmake
@@ -1,2 +1,11 @@
include(Compiler/GNU)
__compiler_gnu(OBJC)
+
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_OBJC)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_OBJC_DEPFILE_FORMAT gcc)
+ set(CMAKE_OBJC_DEPENDS_USE_COMPILER TRUE)
+endif()
diff --git a/Modules/Compiler/GNU-OBJCXX.cmake b/Modules/Compiler/GNU-OBJCXX.cmake
index 06f0244da..1047b5d33 100644
--- a/Modules/Compiler/GNU-OBJCXX.cmake
+++ b/Modules/Compiler/GNU-OBJCXX.cmake
@@ -1,6 +1,15 @@
include(Compiler/GNU)
__compiler_gnu(OBJCXX)
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_OBJCXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_OBJCXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_OBJCXX_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+
if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.2)
set(CMAKE_OBJCXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
endif()
diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index 81ab3a2f7..928e7263f 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -48,7 +48,7 @@ macro(__compiler_gnu lang)
# distcc does not transform -o to -MT when invoking the preprocessor
# internally, as it ought to. Work around this bug by setting -MT here
# even though it isn't strictly necessary.
- set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <OBJECT> -MF <DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
endif()
# Initial configuration flags.
diff --git a/Modules/Compiler/IAR-ASM.cmake b/Modules/Compiler/IAR-ASM.cmake
index 936d4ae30..e3ca16edc 100644
--- a/Modules/Compiler/IAR-ASM.cmake
+++ b/Modules/Compiler/IAR-ASM.cmake
@@ -47,6 +47,11 @@ elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051")
__compiler_iar_xlink(ASM)
set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s51;asm;msa)
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8")
+ set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
+ __compiler_iar_ilink(ASM)
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
+
else()
message(FATAL_ERROR "CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.")
endif()
diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake
index e27fdfcb8..054ee74c1 100644
--- a/Modules/Compiler/IAR-C.cmake
+++ b/Modules/Compiler/IAR-C.cmake
@@ -70,6 +70,10 @@ elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051")
__compiler_check_default_language_standard(C 6.10 90 8.10 99)
set(CMAKE_C_OUTPUT_EXTENSION ".r51")
+elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8")
+ __compiler_iar_ilink(C)
+ __compiler_check_default_language_standard(C 3.11 90 3.11 99)
+
else()
message(FATAL_ERROR "CMAKE_C_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.")
endif()
diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake
index eca89c541..d93b27289 100644
--- a/Modules/Compiler/IAR-CXX.cmake
+++ b/Modules/Compiler/IAR-CXX.cmake
@@ -78,6 +78,10 @@ elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051")
__compiler_check_default_language_standard(CXX 6.10 98)
set(CMAKE_C_OUTPUT_EXTENSION ".r51")
+elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8")
+ __compiler_iar_ilink(CXX)
+ __compiler_check_default_language_standard(CXX 3.11 98)
+
else()
message(FATAL_ERROR "CMAKE_CXX_COMPILER_ARCHITECTURE_ID not detected. This should be automatic." )
endif()
diff --git a/Modules/Compiler/IAR-DetermineCompiler.cmake b/Modules/Compiler/IAR-DetermineCompiler.cmake
index 0a026b2e8..443b09c32 100644
--- a/Modules/Compiler/IAR-DetermineCompiler.cmake
+++ b/Modules/Compiler/IAR-DetermineCompiler.cmake
@@ -31,7 +31,7 @@ set(_compiler_id_version_compute "
# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(((__VER__) / 1000) % 1000)
# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@((__VER__) % 1000)
# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__IAR_SYSTEMS_ICC__)
-# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__))
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@((__VER__) / 100)
# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@((__VER__) - (((__VER__) / 100)*100))
# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__SUBVERSION__)
diff --git a/Modules/Compiler/IAR-FindBinUtils.cmake b/Modules/Compiler/IAR-FindBinUtils.cmake
index 6ef3759ba..6c67d3479 100644
--- a/Modules/Compiler/IAR-FindBinUtils.cmake
+++ b/Modules/Compiler/IAR-FindBinUtils.cmake
@@ -14,7 +14,8 @@ if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "A
"${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX" OR
"${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850" OR
"${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78" OR
- "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV")
+ "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV" OR
+ "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8")
string(TOLOWER "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" _archid_lower)
diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake
index f3938a9a2..b8c077009 100644
--- a/Modules/Compiler/IAR.cmake
+++ b/Modules/Compiler/IAR.cmake
@@ -49,7 +49,7 @@ macro(__compiler_iar_ilink lang)
set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -lAH <ASSEMBLY_SOURCE> -o <OBJECT>.dummy")
set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-f ")
- set(CMAKE_DEPFILE_FLAGS_${lang} "--dependencies=ns <DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "--dependencies=ns <DEP_FILE>")
string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -r")
@@ -85,7 +85,7 @@ macro(__compiler_iar_xlink lang)
set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -lAH <ASSEMBLY_SOURCE> -o <OBJECT>.dummy")
set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-f ")
- set(CMAKE_DEPFILE_FLAGS_${lang} "--dependencies=ns <DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "--dependencies=ns <DEP_FILE>")
string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -r")
diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake
index ec3bfd88f..ead9069f3 100644
--- a/Modules/Compiler/Intel-C.cmake
+++ b/Modules/Compiler/Intel-C.cmake
@@ -5,10 +5,17 @@ string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
-set(CMAKE_DEPFILE_FLAGS_C "-MD -MT <OBJECT> -MF <DEPFILE>")
+set(CMAKE_DEPFILE_FLAGS_C "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
+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_C_DEPFILE_FORMAT gcc)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+endif()
if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
+ set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0)
@@ -28,6 +35,8 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
else()
+ set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c)
+
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0)
set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake
index b71b946e9..37f339a77 100644
--- a/Modules/Compiler/Intel-CXX.cmake
+++ b/Modules/Compiler/Intel-CXX.cmake
@@ -5,7 +5,13 @@ string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG")
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
-set(CMAKE_DEPFILE_FLAGS_CXX "-MD -MT <OBJECT> -MF <DEPFILE>")
+set(CMAKE_DEPFILE_FLAGS_CXX "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
+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_CXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+endif()
if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
@@ -42,6 +48,8 @@ if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
else()
+ set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++)
+
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.0)
set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++20")
set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20")
diff --git a/Modules/Compiler/Intel-ISPC.cmake b/Modules/Compiler/Intel-ISPC.cmake
index aa9ecea19..be64cf79f 100644
--- a/Modules/Compiler/Intel-ISPC.cmake
+++ b/Modules/Compiler/Intel-ISPC.cmake
@@ -3,7 +3,13 @@ include(Compiler/CMakeCommonCompilerMacros)
# Not aware of any verbose flag for ISPC
#set(CMAKE_ISPC_VERBOSE_FLAG )
-set(CMAKE_DEPFILE_FLAGS_ISPC "-M -MT <OBJECT> -MF <DEPFILE>")
+set(CMAKE_DEPFILE_FLAGS_ISPC "-M -MT <DEP_TARGET> -MF <DEP_FILE>")
+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_ISPC_DEPFILE_FORMAT gcc)
+ set(CMAKE_ISPC_DEPENDS_USE_COMPILER TRUE)
+endif()
string(APPEND CMAKE_ISPC_FLAGS_INIT " ")
string(APPEND CMAKE_ISPC_FLAGS_DEBUG_INIT "-O0 -g")
diff --git a/Modules/Compiler/IntelLLVM-ASM.cmake b/Modules/Compiler/IntelLLVM-ASM.cmake
new file mode 100644
index 000000000..c258a0a24
--- /dev/null
+++ b/Modules/Compiler/IntelLLVM-ASM.cmake
@@ -0,0 +1,12 @@
+include(Compiler/IntelLLVM)
+__compiler_intel_llvm(ASM)
+
+string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
+string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG")
+string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
+
+if(UNIX)
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;S)
+else()
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS asm)
+endif()
diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake
new file mode 100644
index 000000000..fce2971ca
--- /dev/null
+++ b/Modules/Compiler/IntelLLVM-C.cmake
@@ -0,0 +1,58 @@
+include(Compiler/IntelLLVM)
+__compiler_intel_llvm(C)
+
+if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
+ set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+ endif()
+else()
+ set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c)
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_C_DEPFILE_FORMAT gcc)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+ endif()
+
+ string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
+ string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
+ string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
+endif()
+
+set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
+set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
+set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
+
+if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
+ set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
+ set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
+
+ set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99")
+ set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+
+ set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
+ set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+else()
+ # clang-cl doesn't have any of these
+ 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_C11_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_C11_EXTENSION_COMPILE_OPTION "")
+endif()
+
+if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
+ # 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)
+else()
+ set(CMAKE_C_STANDARD_DEFAULT "")
+endif()
diff --git a/Modules/Compiler/IntelLLVM-CXX.cmake b/Modules/Compiler/IntelLLVM-CXX.cmake
new file mode 100644
index 000000000..4c0c26e2e
--- /dev/null
+++ b/Modules/Compiler/IntelLLVM-CXX.cmake
@@ -0,0 +1,69 @@
+include(Compiler/IntelLLVM)
+__compiler_intel_llvm(CXX)
+
+if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TP)
+ set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+ endif()
+else()
+ set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++)
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_CXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+ endif()
+
+ set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
+
+ string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
+ string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG")
+ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
+endif()
+
+set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON)
+set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON)
+set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON)
+
+if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
+ set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98")
+ set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
+
+ set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+ set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+
+ set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14")
+ set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
+
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
+
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++20")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20")
+else()
+ set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
+ set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
+
+ set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-Qstd=c++11")
+ set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-Qstd=c++11")
+
+ set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-Qstd=c++14")
+ set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-Qstd=c++14")
+
+ set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-Qstd=c++17")
+ set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-Qstd=c++17")
+
+ set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-Qstd=c++20")
+ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-Qstd=c++20")
+endif()
+
+if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
+ __compiler_check_default_language_standard(CXX 2020 14)
+else()
+ set(CMAKE_CXX_STANDARD_DEFAULT "")
+endif()
diff --git a/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake b/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake
new file mode 100644
index 000000000..124dafe69
--- /dev/null
+++ b/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake
@@ -0,0 +1,41 @@
+
+set(_compiler_id_pp_test "(defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_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.
+ */
+#if __INTEL_LLVM_COMPILER < 1000000L
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__INTEL_LLVM_COMPILER/100)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__INTEL_LLVM_COMPILER/10 % 10)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__INTEL_LLVM_COMPILER % 10)
+#else
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__INTEL_LLVM_COMPILER/10000)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__INTEL_LLVM_COMPILER/100 % 100)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__INTEL_LLVM_COMPILER % 100)
+#endif
+#if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define @PREFIX@SIMULATE_VERSION_MAJOR @MACRO_DEC@(_MSC_VER / 100)
+# define @PREFIX@SIMULATE_VERSION_MINOR @MACRO_DEC@(_MSC_VER % 100)
+#endif
+#if defined(__GNUC__)
+# define @PREFIX@SIMULATE_VERSION_MAJOR @MACRO_DEC@(__GNUC__)
+#elif defined(__GNUG__)
+# define @PREFIX@SIMULATE_VERSION_MAJOR @MACRO_DEC@(__GNUG__)
+#endif
+#if defined(__GNUC_MINOR__)
+# define @PREFIX@SIMULATE_VERSION_MINOR @MACRO_DEC@(__GNUC_MINOR__)
+#endif
+#if defined(__GNUC_PATCHLEVEL__)
+# define @PREFIX@SIMULATE_VERSION_PATCH @MACRO_DEC@(__GNUC_PATCHLEVEL__)
+#endif")
+
+set(_compiler_id_simulate "
+#if defined(_MSC_VER)
+# define @PREFIX@SIMULATE_ID \"MSVC\"
+#endif
+#if defined(__GNUC__)
+# define @PREFIX@SIMULATE_ID \"GNU\"
+#endif")
diff --git a/Modules/Compiler/IntelLLVM-Fortran.cmake b/Modules/Compiler/IntelLLVM-Fortran.cmake
new file mode 100644
index 000000000..710803f01
--- /dev/null
+++ b/Modules/Compiler/IntelLLVM-Fortran.cmake
@@ -0,0 +1,27 @@
+include(Compiler/IntelLLVM)
+__compiler_intel_llvm(Fortran)
+
+set(CMAKE_Fortran_SUBMODULE_SEP "@")
+set(CMAKE_Fortran_SUBMODULE_EXT ".smod")
+
+set(CMAKE_Fortran_MODDIR_FLAG "-module ")
+set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixed")
+set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free")
+
+set(CMAKE_Fortran_COMPILE_WITH_DEFINES 1)
+
+set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
+
+if(CMAKE_HOST_WIN32)
+ # MSVC-like
+ set(CMAKE_Fortran_PREPROCESS_SOURCE
+ "<CMAKE_Fortran_COMPILER> -fpp <DEFINES> <INCLUDES> <FLAGS> -P <SOURCE> -Fi<PREPROCESSED_SOURCE>")
+else()
+ # GNU-like
+ set(CMAKE_Fortran_PREPROCESS_SOURCE
+ "<CMAKE_Fortran_COMPILER> -fpp <DEFINES> <INCLUDES> <FLAGS> -P <SOURCE> -o <PREPROCESSED_SOURCE>")
+endif()
+
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-fpp")
+set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nofpp")
diff --git a/Modules/Compiler/IntelLLVM.cmake b/Modules/Compiler/IntelLLVM.cmake
new file mode 100644
index 000000000..14b7ad83c
--- /dev/null
+++ b/Modules/Compiler/IntelLLVM.cmake
@@ -0,0 +1,92 @@
+# 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_LLVM_INTEL)
+ return()
+endif()
+set(__COMPILER_LLVM_INTEL 1)
+
+include(Compiler/CMakeCommonCompilerMacros)
+
+set(__pch_header_C "c-header")
+set(__pch_header_CXX "c++-header")
+set(__pch_header_OBJC "objective-c-header")
+set(__pch_header_OBJCXX "objective-c++-header")
+
+if(CMAKE_HOST_WIN32)
+ # MSVC-like
+ macro(__compiler_intel_llvm lang)
+ if(NOT "x${lang}" STREQUAL "xFortran")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch)
+ endif()
+ endmacro()
+else()
+ # GNU-like
+ macro(__compiler_intel_llvm lang)
+ set(CMAKE_${lang}_VERBOSE_FLAG "-v")
+
+ string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
+ string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g")
+ string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os")
+ string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3")
+ string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
+
+ set(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER YES)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
+ set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-pie")
+ set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-no-pie")
+
+ set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
+ # distcc does not transform -o to -MT when invoking the preprocessor
+ # internally, as it ought to. Work around this bug by setting -MT here
+ # even though it isn't strictly necessary.
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
+
+ set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "--target=")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_SYSROOT "--sysroot=")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP)
+
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin")
+ set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>")
+
+ set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+ set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
+
+ set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}")
+ if(CMAKE_${lang}_COMPILER_ARG1)
+ separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}")
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS})
+ unset(_COMPILER_ARGS)
+ endif()
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
+ if(CMAKE_${lang}_COMPILER_TARGET)
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}")
+ endif()
+
+ if(NOT "x${lang}" STREQUAL "xFortran")
+ # Precompile Headers
+ set(CMAKE_PCH_EXTENSION .pch)
+ set(CMAKE_PCH_PROLOGUE "#pragma clang system_header")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_INSTANTIATE_TEMPLATES_PCH -fpch-instantiate-templates)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang <PCH_FILE> -Xclang -include -Xclang <PCH_HEADER>)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER> -x ${__pch_header_${lang}})
+ endif()
+ endmacro()
+endif()
diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake
index 31ae7fdec..9a5104bd9 100644
--- a/Modules/Compiler/MSVC-C.cmake
+++ b/Modules/Compiler/MSVC-C.cmake
@@ -27,6 +27,7 @@ else()
set(CMAKE_C_STANDARD_DEFAULT "")
endif()
+set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
# There are no C compiler modes so we hard-code the known compiler supported
diff --git a/Modules/Compiler/NAG-Fortran.cmake b/Modules/Compiler/NAG-Fortran.cmake
index ffce97ef7..a65fd2c5a 100644
--- a/Modules/Compiler/NAG-Fortran.cmake
+++ b/Modules/Compiler/NAG-Fortran.cmake
@@ -31,6 +31,7 @@ endif()
set(CMAKE_Fortran_SUBMODULE_SEP ".")
set(CMAKE_Fortran_SUBMODULE_EXT ".sub")
set(CMAKE_Fortran_MODDIR_FLAG "-mdir ")
+set(CMAKE_Fortran_MODDIR_INCLUDE_FLAG "-I") # -mdir does not affect search path
set(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "-PIC")
set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-fixed")
set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free")
diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake
new file mode 100644
index 000000000..d16c72b76
--- /dev/null
+++ b/Modules/Compiler/NVHPC-C.cmake
@@ -0,0 +1,3 @@
+include(Compiler/PGI-C)
+include(Compiler/NVHPC)
+__compiler_nvhpc(C)
diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake
new file mode 100644
index 000000000..18ace8bfe
--- /dev/null
+++ b/Modules/Compiler/NVHPC-CXX.cmake
@@ -0,0 +1,3 @@
+include(Compiler/PGI-CXX)
+include(Compiler/NVHPC)
+__compiler_nvhpc(CXX)
diff --git a/Modules/Compiler/NVHPC-DetermineCompiler.cmake b/Modules/Compiler/NVHPC-DetermineCompiler.cmake
new file mode 100644
index 000000000..45b69e18e
--- /dev/null
+++ b/Modules/Compiler/NVHPC-DetermineCompiler.cmake
@@ -0,0 +1,9 @@
+
+set(_compiler_id_pp_test "defined(__NVCOMPILER)")
+
+set(_compiler_id_version_compute "
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__NVCOMPILER_MAJOR__)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__NVCOMPILER_MINOR__)
+# if defined(__NVCOMPILER_PATCHLEVEL__)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__NVCOMPILER_PATCHLEVEL__)
+# endif")
diff --git a/Modules/Compiler/NVHPC-Fortran.cmake b/Modules/Compiler/NVHPC-Fortran.cmake
new file mode 100644
index 000000000..59755b3a7
--- /dev/null
+++ b/Modules/Compiler/NVHPC-Fortran.cmake
@@ -0,0 +1,3 @@
+include(Compiler/PGI-Fortran)
+include(Compiler/NVHPC)
+__compiler_nvhpc(Fortran)
diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake
new file mode 100644
index 000000000..70486705c
--- /dev/null
+++ b/Modules/Compiler/NVHPC.cmake
@@ -0,0 +1,15 @@
+# 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_NVHPC)
+ return()
+endif()
+set(__COMPILER_NVHPC 1)
+
+include(Compiler/PGI)
+
+macro(__compiler_nvhpc lang)
+ # Logic specific to NVHPC.
+endmacro()
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
index 95a51f66b..eb806758f 100644
--- a/Modules/Compiler/NVIDIA-CUDA.cmake
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -28,7 +28,14 @@ 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 <OBJECT> -MF <DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
+else()
+ 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)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
+ set(CMAKE_CUDA_DEPENDS_USE_COMPILER TRUE)
endif()
if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
diff --git a/Modules/Compiler/PGI-CXX.cmake b/Modules/Compiler/PGI-CXX.cmake
index 2d7a303c9..1279c1987 100644
--- a/Modules/Compiler/PGI-CXX.cmake
+++ b/Modules/Compiler/PGI-CXX.cmake
@@ -8,6 +8,8 @@ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.10)
set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION --gnu_extensions)
set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.10)
+ set(CMAKE_CXX98_STANDARD_COMPILE_OPTION --c++03)
+ set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION --c++03 --gnu_extensions)
set(CMAKE_CXX11_STANDARD_COMPILE_OPTION --c++11)
set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION --c++11 --gnu_extensions)
set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON)
@@ -18,7 +20,6 @@ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.10)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 17.1)
set(CMAKE_CXX17_STANDARD_COMPILE_OPTION --c++17)
set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION --c++17 --gnu_extensions)
- set(CMAKE_CXX17_STANDARD__HAS_FULL_SUPPORT ON)
endif()
endif()
endif()
diff --git a/Modules/Compiler/QCC.cmake b/Modules/Compiler/QCC.cmake
index 10e138918..7fbfd107e 100644
--- a/Modules/Compiler/QCC.cmake
+++ b/Modules/Compiler/QCC.cmake
@@ -14,7 +14,7 @@ macro(__compiler_qcc lang)
set(CMAKE_${lang}_COMPILE_OPTIONS_SYSROOT "-Wc,-isysroot,")
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-Wp,-isystem,")
- set(CMAKE_DEPFILE_FLAGS_${lang} "-Wp,-MD,<DEPFILE> -Wp,-MT,<OBJECT> -Wp,-MF,<DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-Wp,-MD,<DEP_FILE> -Wp,-MT,<DEP_TARGET> -Wp,-MF,<DEP_FILE>")
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
diff --git a/Modules/Compiler/SunPro-C.cmake b/Modules/Compiler/SunPro-C.cmake
index 7e962b8ee..c98656f58 100644
--- a/Modules/Compiler/SunPro-C.cmake
+++ b/Modules/Compiler/SunPro-C.cmake
@@ -22,7 +22,7 @@ string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -xO2 -xspace -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -xO3 -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -g -xO2 -DNDEBUG")
-set(CMAKE_DEPFILE_FLAGS_C "-xMD -xMF <DEPFILE>")
+set(CMAKE_DEPFILE_FLAGS_C "-xMD -xMF <DEP_FILE>")
# Initialize C link type selection flags. These flags are used when
# building a shared library, shared module, or executable that links
diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake
index c946c6436..aa8a9c549 100644
--- a/Modules/Compiler/SunPro-CXX.cmake
+++ b/Modules/Compiler/SunPro-CXX.cmake
@@ -22,7 +22,7 @@ string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -xO2 -xspace -DNDEBUG")
string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -xO3 -DNDEBUG")
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -g -xO2 -DNDEBUG")
-set(CMAKE_DEPFILE_FLAGS_CXX "-xMD -xMF <DEPFILE>")
+set(CMAKE_DEPFILE_FLAGS_CXX "-xMD -xMF <DEP_FILE>")
# Initialize C link type selection flags. These flags are used when
# building a shared library, shared module, or executable that links
diff --git a/Modules/Compiler/TI.cmake b/Modules/Compiler/TI.cmake
index f63168823..c8c163513 100644
--- a/Modules/Compiler/TI.cmake
+++ b/Modules/Compiler/TI.cmake
@@ -18,7 +18,7 @@ macro(__compiler_ti lang)
set(CMAKE_${lang}_RESPONSE_FILE_FLAG "--cmd_file=")
set(CMAKE_INCLUDE_FLAG_${lang} "--include_path=")
- set(CMAKE_DEPFILE_FLAGS_${lang} "--preproc_with_compile --preproc_dependency=<DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "--preproc_with_compile --preproc_dependency=<DEP_FILE>")
set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> --preproc_only ${__COMPILER_TI_SOURCE_FLAG_${lang}}=<SOURCE> <DEFINES> <INCLUDES> <FLAGS> --output_file=<PREPROCESSED_SOURCE>")
set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> --compile_only --skip_assembler ${__COMPILER_TI_SOURCE_FLAG_${lang}}=<SOURCE> <DEFINES> <INCLUDES> <FLAGS> --output_file=<ASSEMBLY_SOURCE>")
diff --git a/Modules/Compiler/XL.cmake b/Modules/Compiler/XL.cmake
index fc71ab489..8b9d4a9db 100644
--- a/Modules/Compiler/XL.cmake
+++ b/Modules/Compiler/XL.cmake
@@ -30,5 +30,5 @@ macro(__compiler_xl lang)
set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
- set(CMAKE_DEPFILE_FLAGS_${lang} "-MF <DEPFILE> -qmakedep=gcc")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-MF <DEP_FILE> -qmakedep=gcc")
endmacro()
diff --git a/Modules/Compiler/XLClang-C.cmake b/Modules/Compiler/XLClang-C.cmake
index 54c18a668..1668a4d0f 100644
--- a/Modules/Compiler/XLClang-C.cmake
+++ b/Modules/Compiler/XLClang-C.cmake
@@ -1,6 +1,8 @@
include(Compiler/XLClang)
__compiler_xlclang(C)
+set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c)
+
if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.1)
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89")
diff --git a/Modules/Compiler/XLClang-CXX.cmake b/Modules/Compiler/XLClang-CXX.cmake
index 9ea3d7cac..02638c791 100644
--- a/Modules/Compiler/XLClang-CXX.cmake
+++ b/Modules/Compiler/XLClang-CXX.cmake
@@ -1,6 +1,8 @@
include(Compiler/XLClang)
__compiler_xlclang(CXX)
+set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++)
+
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.1)
set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in
index 90a56e287..e5b1e5d78 100644
--- a/Modules/DartConfiguration.tcl.in
+++ b/Modules/DartConfiguration.tcl.in
@@ -83,10 +83,6 @@ MemoryCheckSuppressionFile: @MEMORYCHECK_SUPPRESSIONS_FILE@
CoverageCommand: @COVERAGE_COMMAND@
CoverageExtraFlags: @COVERAGE_EXTRA_FLAGS@
-# Cluster commands
-SlurmBatchCommand: @SLURM_SBATCH_COMMAND@
-SlurmRunCommand: @SLURM_SRUN_COMMAND@
-
# Testing options
# TimeOut is the amount of time in seconds to wait for processes
# to complete during testing. After TimeOut seconds, the
diff --git a/Modules/Documentation.cmake b/Modules/Documentation.cmake
index c297231e5..2430f85a0 100644
--- a/Modules/Documentation.cmake
+++ b/Modules/Documentation.cmake
@@ -5,6 +5,9 @@
Documentation
-------------
+.. deprecated:: 3.18
+ This module does nothing, unless policy :policy:`CMP0106` is set to ``OLD``.
+
This module provides support for the VTK documentation framework. It
relies on several tools (Doxygen, Perl, etc).
#]=======================================================================]
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 6fe8685ca..d6fbae9aa 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -78,7 +78,8 @@ Module Functions
manage local instances of data files stored externally::
ExternalData_Add_Target(
- <target> # Name of data management target
+ <target> # Name of data management target
+ [SHOW_PROGRESS <ON|OFF>] # Show progress during the download
)
It creates custom commands in the target as necessary to make data
@@ -89,6 +90,12 @@ Module Functions
in one of the paths specified in the ``ExternalData_OBJECT_STORES``
variable.
+ .. versionadded:: 3.20
+ The ``SHOW_PROGRESS`` argument may be passed to suppress progress information
+ during the download of objects. If not provided, it defaults to ``OFF`` for
+ :generator:`Ninja` and :generator:`Ninja Multi-Config` generators and ``ON``
+ otherwise.
+
Typically only one target is needed to manage all external data within
a project. Call this function once at the end of configuration after
all data references have been processed.
@@ -108,6 +115,8 @@ calling any of the functions provided by this module.
.. variable:: ExternalData_CUSTOM_SCRIPT_<key>
+ .. versionadded:: 3.2
+
Specify a full path to a ``.cmake`` custom fetch script identified by
``<key>`` in entries of the ``ExternalData_URL_TEMPLATES`` list.
See `Custom Fetch Scripts`_.
@@ -126,6 +135,8 @@ calling any of the functions provided by this module.
.. variable:: ExternalData_NO_SYMLINKS
+ .. versionadded:: 3.3
+
The real data files named by expanded ``DATA{}`` references may be made
available under ``ExternalData_BINARY_ROOT`` using symbolic links on
some platforms. The ``ExternalData_NO_SYMLINKS`` variable may be set
@@ -171,6 +182,8 @@ calling any of the functions provided by this module.
.. variable:: ExternalData_URL_ALGO_<algo>_<key>
+ .. versionadded:: 3.3
+
Specify a custom URL component to be substituted for URL template
placeholders of the form ``%(algo:<key>)``, where ``<key>`` is a
valid C identifier, when fetching an object referenced via hash
@@ -201,10 +214,11 @@ For example, the argument ``DATA{img.png}`` may be satisfied by either a
real ``img.png`` file in the current source directory or a ``img.png.md5``
file containing its MD5 sum.
-Multiple content links of the same name with different hash algorithms
-are supported (e.g. ``img.png.sha256`` and ``img.png.sha1``) so long as
-they all correspond to the same real file. This allows objects to be
-fetched from sources indexed by different hash algorithms.
+.. versionadded:: 3.8
+ Multiple content links of the same name with different hash algorithms
+ are supported (e.g. ``img.png.sha256`` and ``img.png.sha1``) so long as
+ they all correspond to the same real file. This allows objects to be
+ fetched from sources indexed by different hash algorithms.
Referencing File Series
"""""""""""""""""""""""
@@ -263,8 +277,11 @@ associated file options. For example, the argument
``DATA{MyDataDir/,REGEX:.*}`` will pass the full path to a ``MyDataDir``
directory on the command line and ensure that the directory contains
files corresponding to every file or content link in the ``MyDataDir``
-source directory. In order to match associated files in subdirectories,
-specify a ``RECURSE:`` option, e.g. ``DATA{MyDataDir/,RECURSE:,REGEX:.*}``.
+source directory.
+
+.. versionadded:: 3.3
+ In order to match associated files in subdirectories,
+ specify a ``RECURSE:`` option, e.g. ``DATA{MyDataDir/,RECURSE:,REGEX:.*}``.
Hash Algorithms
^^^^^^^^^^^^^^^
@@ -284,6 +301,9 @@ The following hash algorithms are supported::
SHA3_384 .sha3-384 Keccak SHA-3
SHA3_512 .sha3-512 Keccak SHA-3
+.. versionadded:: 3.8
+ Added the ``SHA3_*`` hash algorithms.
+
Note that the hashes are used only for unique data identification and
download verification.
@@ -292,6 +312,8 @@ download verification.
Custom Fetch Scripts
^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.2
+
When a data file must be fetched from one of the URL templates
specified in the ``ExternalData_URL_TEMPLATES`` variable, it is
normally downloaded using the :command:`file(DOWNLOAD)` command.
@@ -344,6 +366,30 @@ function(ExternalData_add_target target)
endif()
set(_ExternalData_CONFIG_CODE "")
+ cmake_parse_arguments(PARSE_ARGV 1 _ExternalData_add_target
+ ""
+ "SHOW_PROGRESS"
+ "")
+ if (_ExternalData_add_target_UNPARSED_ARGUMENTS)
+ message(AUTHOR_WARNING
+ "Ignoring unrecognized arguments passed to ExternalData_add_target: "
+ "`${_ExternalData_add_target_UNPARSED_ARGUMENTS}`")
+ endif ()
+
+ # Turn `SHOW_PROGRESS` into a boolean
+ if (NOT DEFINED _ExternalData_add_target_SHOW_PROGRESS)
+ # The default setting
+ if (CMAKE_GENERATOR MATCHES "Ninja")
+ set(_ExternalData_add_target_SHOW_PROGRESS OFF)
+ else ()
+ set(_ExternalData_add_target_SHOW_PROGRESS ON)
+ endif ()
+ elseif (_ExternalData_add_target_SHOW_PROGRESS)
+ set(_ExternalData_add_target_SHOW_PROGRESS ON)
+ else ()
+ set(_ExternalData_add_target_SHOW_PROGRESS OFF)
+ endif ()
+
# Store custom script configuration.
foreach(url_template IN LISTS ExternalData_URL_TEMPLATES)
if("${url_template}" MATCHES "^ExternalDataCustomScript://([^/]*)/(.*)$")
@@ -423,6 +469,7 @@ function(ExternalData_add_target target)
COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR}
-Dfile=${file} -Dname=${name}
-DExternalData_ACTION=local
+ -DExternalData_SHOW_PROGRESS=${_ExternalData_add_target_SHOW_PROGRESS}
-DExternalData_CONFIG=${config}
-P ${_ExternalData_SELF}
MAIN_DEPENDENCY "${name}"
@@ -459,6 +506,7 @@ function(ExternalData_add_target target)
COMMAND ${CMAKE_COMMAND} -Drelative_top=${CMAKE_BINARY_DIR}
-Dfile=${file} -Dname=${name} -Dexts=${exts}
-DExternalData_ACTION=fetch
+ -DExternalData_SHOW_PROGRESS=${_ExternalData_add_target_SHOW_PROGRESS}
-DExternalData_CONFIG=${config}
-P ${_ExternalData_SELF}
# Update whenever the object hash changes.
@@ -925,7 +973,11 @@ function(_ExternalData_download_file url file err_var msg_var)
else()
set(absolute_timeout "")
endif()
- file(DOWNLOAD "${url}" "${file}" STATUS status LOG log ${inactivity_timeout} ${absolute_timeout} SHOW_PROGRESS)
+ set(show_progress_args)
+ if (ExternalData_SHOW_PROGRESS)
+ list(APPEND show_progress_args SHOW_PROGRESS)
+ endif ()
+ file(DOWNLOAD "${url}" "${file}" STATUS status LOG log ${inactivity_timeout} ${absolute_timeout} ${show_progress_args})
list(GET status 0 err)
list(GET status 1 msg)
if(err)
diff --git a/Modules/ExternalProject-gitupdate.cmake.in b/Modules/ExternalProject-gitupdate.cmake.in
index eff39c130..703391805 100644
--- a/Modules/ExternalProject-gitupdate.cmake.in
+++ b/Modules/ExternalProject-gitupdate.cmake.in
@@ -3,214 +3,275 @@
cmake_minimum_required(VERSION 3.5)
-execute_process(
- COMMAND "@git_EXECUTABLE@" rev-list --max-count=1 HEAD
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- OUTPUT_VARIABLE head_sha
- OUTPUT_STRIP_TRAILING_WHITESPACE
+function(get_hash_for_ref ref out_var err_var)
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" rev-parse "${ref}"
+ WORKING_DIRECTORY "@work_dir@"
+ RESULT_VARIABLE error_code
+ OUTPUT_VARIABLE ref_hash
+ ERROR_VARIABLE error_msg
+ OUTPUT_STRIP_TRAILING_WHITESPACE
)
-if(error_code)
- message(FATAL_ERROR "Failed to get the hash for HEAD")
+ if(error_code)
+ set(${out_var} "" PARENT_SCOPE)
+ else()
+ set(${out_var} "${ref_hash}" PARENT_SCOPE)
+ endif()
+ set(${err_var} "${error_msg}" PARENT_SCOPE)
+endfunction()
+
+get_hash_for_ref(HEAD head_sha error_msg)
+if(head_sha STREQUAL "")
+ message(FATAL_ERROR "Failed to get the hash for HEAD:\n${error_msg}")
endif()
+
execute_process(
COMMAND "@git_EXECUTABLE@" show-ref "@git_tag@"
WORKING_DIRECTORY "@work_dir@"
OUTPUT_VARIABLE show_ref_output
- )
-# If a remote ref is asked for, which can possibly move around,
-# we must always do a fetch and checkout.
-if("${show_ref_output}" MATCHES "remotes")
- set(is_remote_ref 1)
-else()
- set(is_remote_ref 0)
-endif()
+)
+if(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/remotes/")
+ # Given a full remote/branch-name and we know about it already. Since
+ # branches can move around, we always have to fetch.
+ set(fetch_required YES)
+ set(checkout_name "@git_tag@")
+
+elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/tags/")
+ # Given a tag name that we already know about. We don't know if the tag we
+ # have matches the remote though (tags can move), so we should fetch.
+ set(fetch_required YES)
+ set(checkout_name "@git_tag@")
+
+ # Special case to preserve backward compatibility: if we are already at the
+ # same commit as the tag we hold locally, don't do a fetch and assume the tag
+ # hasn't moved on the remote.
+ # FIXME: We should provide an option to always fetch for this case
+ get_hash_for_ref("@git_tag@" tag_sha error_msg)
+ if(tag_sha STREQUAL head_sha)
+ message(VERBOSE "Already at requested tag: ${tag_sha}")
+ return()
+ endif()
+
+elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/heads/")
+ # Given a branch name without any remote and we already have a branch by that
+ # name. We might already have that branch checked out or it might be a
+ # different branch. It isn't safe to use a bare branch name without the
+ # remote, so do a fetch and replace the ref with one that includes the remote.
+ set(fetch_required YES)
+ set(checkout_name "@git_remote_name@/@git_tag@")
-# Tag is in the form <remote>/<tag> (i.e. origin/master) we must strip
-# the remote from the tag.
-if("${show_ref_output}" MATCHES "refs/remotes/@git_tag@")
- string(REGEX MATCH "^([^/]+)/(.+)$" _unused "@git_tag@")
- set(git_remote "${CMAKE_MATCH_1}")
- set(git_tag "${CMAKE_MATCH_2}")
else()
- set(git_remote "@git_remote_name@")
- set(git_tag "@git_tag@")
+ get_hash_for_ref("@git_tag@" tag_sha error_msg)
+ if(tag_sha STREQUAL head_sha)
+ # Have the right commit checked out already
+ message(VERBOSE "Already at requested ref: ${tag_sha}")
+ return()
+
+ elseif(tag_sha STREQUAL "")
+ # We don't know about this ref yet, so we have no choice but to fetch.
+ # We deliberately swallow any error message at the default log level
+ # because it can be confusing for users to see a failed git command.
+ # That failure is being handled here, so it isn't an error.
+ set(fetch_required YES)
+ set(checkout_name "@git_tag@")
+ if(NOT error_msg STREQUAL "")
+ message(VERBOSE "${error_msg}")
+ endif()
+
+ else()
+ # We have the commit, so we know we were asked to find a commit hash
+ # (otherwise it would have been handled further above), but we don't
+ # have that commit checked out yet
+ set(fetch_required NO)
+ set(checkout_name "@git_tag@")
+ if(NOT error_msg STREQUAL "")
+ message(WARNING "${error_msg}")
+ endif()
+
+ endif()
endif()
-# This will fail if the tag does not exist (it probably has not been fetched
-# yet).
-execute_process(
- COMMAND "@git_EXECUTABLE@" rev-list --max-count=1 "${git_tag}"
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- OUTPUT_VARIABLE tag_sha
- OUTPUT_STRIP_TRAILING_WHITESPACE
+if(fetch_required)
+ message(VERBOSE "Fetching latest from the remote @git_remote_name@")
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" fetch --tags --force "@git_remote_name@"
+ WORKING_DIRECTORY "@work_dir@"
+ COMMAND_ERROR_IS_FATAL ANY
)
+endif()
-# Is the hash checkout out that we want?
-if(error_code OR is_remote_ref OR NOT ("${tag_sha}" STREQUAL "${head_sha}"))
+set(git_update_strategy "@git_update_strategy@")
+if(git_update_strategy STREQUAL "")
+ # Backward compatibility requires REBASE as the default behavior
+ set(git_update_strategy REBASE)
+endif()
+
+if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$")
+ # Asked to potentially try to rebase first, maybe with fallback to checkout.
+ # We can't if we aren't already on a branch and we shouldn't if that local
+ # branch isn't tracking the one we want to checkout.
execute_process(
- COMMAND "@git_EXECUTABLE@" fetch
+ COMMAND "@git_EXECUTABLE@" symbolic-ref -q HEAD
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- message(FATAL_ERROR "Failed to fetch repository '@git_repository@'")
- endif()
+ OUTPUT_VARIABLE current_branch
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ # Don't test for an error. If this isn't a branch, we get a non-zero error
+ # code but empty output.
+ )
- if(is_remote_ref)
- # Check if stash is needed
+ if(current_branch STREQUAL "")
+ # Not on a branch, checkout is the only sensible option since any rebase
+ # would always fail (and backward compatibility requires us to checkout in
+ # this situation)
+ set(git_update_strategy CHECKOUT)
+
+ else()
execute_process(
- COMMAND "@git_EXECUTABLE@" status --porcelain
+ COMMAND "@git_EXECUTABLE@" for-each-ref "--format='%(upstream:short)'" "${current_branch}"
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- OUTPUT_VARIABLE repo_status
- )
- if(error_code)
- message(FATAL_ERROR "Failed to get the status")
+ OUTPUT_VARIABLE upstream_branch
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY # There is no error if no upstream is set
+ )
+ if(NOT upstream_branch STREQUAL checkout_name)
+ # Not safe to rebase when asked to checkout a different branch to the one
+ # we are tracking. If we did rebase, we could end up with arbitrary
+ # commits added to the ref we were asked to checkout if the current local
+ # branch happens to be able to rebase onto the target branch. There would
+ # be no error message and the user wouldn't know this was occurring.
+ set(git_update_strategy CHECKOUT)
endif()
- string(LENGTH "${repo_status}" need_stash)
- # If not in clean state, stash changes in order to be able to perform a
- # rebase or checkout without losing those changes permanently
- if(need_stash)
- execute_process(
- COMMAND "@git_EXECUTABLE@" stash save @git_stash_save_options@
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- message(FATAL_ERROR "Failed to stash changes")
- endif()
- endif()
+ endif()
+elseif(NOT git_update_strategy STREQUAL "CHECKOUT")
+ message(FATAL_ERROR "Unsupported git update strategy: ${git_update_strategy}")
+endif()
- if("@git_update_strategy@" STREQUAL "CHECKOUT")
- execute_process(
- COMMAND "@git_EXECUTABLE@" checkout "${git_remote}/${git_tag}"
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- message(FATAL_ERROR "Failed to checkout tag: '${git_remote}/${git_tag}'")
- endif()
- else()
- # Pull changes from the remote branch
- execute_process(
- COMMAND "@git_EXECUTABLE@" rebase "${git_remote}/${git_tag}"
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- OUTPUT_VARIABLE rebase_output
- ERROR_VARIABLE rebase_output
- )
- if(error_code)
- # Rebase failed, undo the rebase attempt before continuing
- execute_process(
- COMMAND "@git_EXECUTABLE@" rebase --abort
- WORKING_DIRECTORY "@work_dir@"
- )
-
- if(NOT "@git_update_strategy@" STREQUAL "REBASE_CHECKOUT")
- # Not allowed to do a checkout as a fallback, so cannot proceed
- if(need_stash)
- execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
- WORKING_DIRECTORY "@work_dir@"
- )
- endif()
- message(FATAL_ERROR "\nFailed to rebase in: '@work_dir@'."
- "\nOutput from the attempted rebase follows:"
- "\n${rebase_output}"
- "\n\nYou will have to resolve the conflicts manually")
- endif()
-
- # Fall back to checkout. We create an annotated tag so that the user
- # can manually inspect the situation and revert if required.
- # We can't log the failed rebase output because MSVC sees it and
- # intervenes, causing the build to fail even though it completes.
- # Write it to a file instead.
- string(TIMESTAMP tag_timestamp "%Y%m%dT%H%M%S" UTC)
- set(tag_name _cmake_ExternalProject_moved_from_here_${tag_timestamp}Z)
- set(error_log_file ${CMAKE_CURRENT_LIST_DIR}/rebase_error_${tag_timestamp}Z.log)
- file(WRITE ${error_log_file} "${rebase_output}")
- message(WARNING "Rebase failed, output has been saved to ${error_log_file}"
- "\nFalling back to checkout, previous commit tagged as ${tag_name}")
- execute_process(
- COMMAND "@git_EXECUTABLE@" tag -a
- -m "ExternalProject attempting to move from here to ${git_remote}/${git_tag}"
- ${tag_name}
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- message(FATAL_ERROR "Failed to add marker tag")
- endif()
- execute_process(
- COMMAND "@git_EXECUTABLE@" checkout "${git_remote}/${git_tag}"
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- message(FATAL_ERROR "Failed to checkout : '${git_remote}/${git_tag}'")
- endif()
+# Check if stash is needed
+execute_process(
+ COMMAND "@git_EXECUTABLE@" status --porcelain
+ WORKING_DIRECTORY "@work_dir@"
+ RESULT_VARIABLE error_code
+ OUTPUT_VARIABLE repo_status
+)
+if(error_code)
+ message(FATAL_ERROR "Failed to get the status")
+endif()
+string(LENGTH "${repo_status}" need_stash)
- endif()
- endif()
+# If not in clean state, stash changes in order to be able to perform a
+# rebase or checkout without losing those changes permanently
+if(need_stash)
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" stash save @git_stash_save_options@
+ WORKING_DIRECTORY "@work_dir@"
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+endif()
- if(need_stash)
- execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- # Stash pop --index failed: Try again dropping the index
- execute_process(
- COMMAND "@git_EXECUTABLE@" reset --hard --quiet
- WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
+if(git_update_strategy STREQUAL "CHECKOUT")
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}"
+ WORKING_DIRECTORY "@work_dir@"
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+else()
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" rebase "${checkout_name}"
+ WORKING_DIRECTORY "@work_dir@"
+ RESULT_VARIABLE error_code
+ OUTPUT_VARIABLE rebase_output
+ ERROR_VARIABLE rebase_output
+ )
+ if(error_code)
+ # Rebase failed, undo the rebase attempt before continuing
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" rebase --abort
+ WORKING_DIRECTORY "@work_dir@"
+ )
+
+ if(NOT git_update_strategy STREQUAL "REBASE_CHECKOUT")
+ # Not allowed to do a checkout as a fallback, so cannot proceed
+ if(need_stash)
execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --quiet
+ COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- # Stash pop failed: Restore previous state.
- execute_process(
- COMMAND "@git_EXECUTABLE@" reset --hard --quiet ${head_sha}
- WORKING_DIRECTORY "@work_dir@"
- )
- execute_process(
- COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
- WORKING_DIRECTORY "@work_dir@"
)
- message(FATAL_ERROR "\nFailed to unstash changes in: '@work_dir@'."
- "\nYou will have to resolve the conflicts manually")
- endif()
endif()
+ message(FATAL_ERROR "\nFailed to rebase in: '@work_dir@'."
+ "\nOutput from the attempted rebase follows:"
+ "\n${rebase_output}"
+ "\n\nYou will have to resolve the conflicts manually")
endif()
- else()
+
+ # Fall back to checkout. We create an annotated tag so that the user
+ # can manually inspect the situation and revert if required.
+ # We can't log the failed rebase output because MSVC sees it and
+ # intervenes, causing the build to fail even though it completes.
+ # Write it to a file instead.
+ string(TIMESTAMP tag_timestamp "%Y%m%dT%H%M%S" UTC)
+ set(tag_name _cmake_ExternalProject_moved_from_here_${tag_timestamp}Z)
+ set(error_log_file ${CMAKE_CURRENT_LIST_DIR}/rebase_error_${tag_timestamp}Z.log)
+ file(WRITE ${error_log_file} "${rebase_output}")
+ message(WARNING "Rebase failed, output has been saved to ${error_log_file}"
+ "\nFalling back to checkout, previous commit tagged as ${tag_name}")
execute_process(
- COMMAND "@git_EXECUTABLE@" checkout "${git_tag}"
+ COMMAND "@git_EXECUTABLE@" tag -a
+ -m "ExternalProject attempting to move from here to ${checkout_name}"
+ ${tag_name}
WORKING_DIRECTORY "@work_dir@"
- RESULT_VARIABLE error_code
- )
- if(error_code)
- message(FATAL_ERROR "Failed to checkout tag: '${git_tag}'")
- endif()
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}"
+ WORKING_DIRECTORY "@work_dir@"
+ COMMAND_ERROR_IS_FATAL ANY
+ )
endif()
+endif()
- set(init_submodules "@init_submodules@")
- if(init_submodules)
+if(need_stash)
+ # Put back the stashed changes
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
+ WORKING_DIRECTORY "@work_dir@"
+ RESULT_VARIABLE error_code
+ )
+ if(error_code)
+ # Stash pop --index failed: Try again dropping the index
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" reset --hard --quiet
+ WORKING_DIRECTORY "@work_dir@"
+ )
execute_process(
- COMMAND "@git_EXECUTABLE@" submodule update @git_submodules_recurse@ --init @git_submodules@
+ COMMAND "@git_EXECUTABLE@" stash pop --quiet
WORKING_DIRECTORY "@work_dir@"
RESULT_VARIABLE error_code
+ )
+ if(error_code)
+ # Stash pop failed: Restore previous state.
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" reset --hard --quiet ${head_sha}
+ WORKING_DIRECTORY "@work_dir@"
)
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" stash pop --index --quiet
+ WORKING_DIRECTORY "@work_dir@"
+ )
+ message(FATAL_ERROR "\nFailed to unstash changes in: '@work_dir@'."
+ "\nYou will have to resolve the conflicts manually")
+ endif()
endif()
- if(error_code)
- message(FATAL_ERROR "Failed to update submodules in: '@work_dir@'")
- endif()
+endif()
+
+set(init_submodules "@init_submodules@")
+if(init_submodules)
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" submodule update @git_submodules_recurse@ --init @git_submodules@
+ WORKING_DIRECTORY "@work_dir@"
+ COMMAND_ERROR_IS_FATAL ANY
+ )
endif()
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 8bbaf5a38..56525080c 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -1,6 +1,8 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+include_guard(GLOBAL)
+
#[=======================================================================[.rst:
ExternalProject
---------------
@@ -56,6 +58,8 @@ External Project Definition
(see *Logging Options* below).
``LOG_DIR <dir>``
+ .. versionadded:: 3.14
+
Directory in which to store the logs of each step.
``DOWNLOAD_DIR <dir>``
@@ -144,6 +148,9 @@ External Project Definition
is determined by inspecting the actual content rather than using logic
based on the file extension.
+ .. versionchanged:: 3.7
+ Multiple URLs are allowed.
+
``URL_HASH <algo>=<hashValue>``
Hash of the archive file to be downloaded. The argument should be of
the form ``<algo>=<hashValue>`` where ``algo`` can be any of the hashing
@@ -164,6 +171,8 @@ External Project Definition
of code internal to the ``ExternalProject`` module.
``DOWNLOAD_NO_EXTRACT <bool>``
+ .. versionadded:: 3.6
+
Allows the extraction part of the download step to be disabled by
passing a boolean true value for this option. If this option is not
given, the downloaded contents will be unpacked automatically if
@@ -180,15 +189,23 @@ External Project Definition
Maximum time allowed for file download operations.
``INACTIVITY_TIMEOUT <seconds>``
+ .. versionadded:: 3.19
+
Terminate the operation after a period of inactivity.
``HTTP_USERNAME <username>``
+ .. versionadded:: 3.7
+
Username for the download operation if authentication is required.
``HTTP_PASSWORD <password>``
+ .. versionadded:: 3.7
+
Password for the download operation if authentication is required.
``HTTP_HEADER <header1> [<header2>...]``
+ .. versionadded:: 3.7
+
Provides an arbitrary list of HTTP headers for the download operation.
This can be useful for accessing content in systems like AWS, etc.
@@ -201,6 +218,9 @@ External Project Definition
cannot be provided, this option can be an alternative verification
measure.
+ .. versionchanged:: 3.6
+ This option also applies to ``git clone`` invocations.
+
``TLS_CAINFO <file>``
Specify a custom certificate authority file to use if ``TLS_VERIFY``
is enabled. If this option is not specified, the value of the
@@ -208,6 +228,8 @@ External Project Definition
:command:`file(DOWNLOAD)`)
``NETRC <level>``
+ .. versionadded:: 3.11
+
Specify whether the ``.netrc`` file is to be used for operation.
If this option is not specified, the value of the ``CMAKE_NETRC``
variable will be used instead (see :command:`file(DOWNLOAD)`)
@@ -225,11 +247,16 @@ External Project Definition
is ignored.
``NETRC_FILE <file>``
+ .. versionadded:: 3.11
+
Specify an alternative ``.netrc`` file to the one in your home directory
if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will
be used instead (see :command:`file(DOWNLOAD)`)
+ .. versionadded:: 3.1
+ Added support for `tbz2`, `.tar.xz`, `.txz`, and `.7z` extensions.
+
*Git*
NOTE: A git version of 1.6.5 or later is required if this download method
is used.
@@ -267,22 +294,30 @@ External Project Definition
``GIT_SUBMODULES <module>...``
Specific git submodules that should also be updated. If this option is
- not provided, all git submodules will be updated. When :policy:`CMP0097`
- is set to ``NEW`` if this value is set to an empty string then no submodules
- are initialized or updated.
+ not provided, all git submodules will be updated.
+
+ .. versionchanged:: 3.16
+ When :policy:`CMP0097` is set to ``NEW``, if this value is set
+ to an empty string then no submodules are initialized or updated.
``GIT_SUBMODULES_RECURSE <bool>``
+ .. versionadded:: 3.17
+
Specify whether git submodules (if any) should update recursively by
passing the ``--recursive`` flag to ``git submodule update``.
If not specified, the default is on.
``GIT_SHALLOW <bool>``
+ .. versionadded:: 3.6
+
When this option is enabled, the ``git clone`` operation will be given
the ``--depth 1`` option. This performs a shallow clone, which avoids
downloading the whole history and instead retrieves just the commit
denoted by the ``GIT_TAG`` option.
``GIT_PROGRESS <bool>``
+ .. versionadded:: 3.8
+
When enabled, this option instructs the ``git clone`` operation to
report its progress by passing it the ``--progress`` option. Without
this option, the clone step for large projects may appear to make the
@@ -292,12 +327,16 @@ External Project Definition
overly noisy if lots of external projects are used.
``GIT_CONFIG <option1> [<option2>...]``
+ .. versionadded:: 3.8
+
Specify a list of config options to pass to ``git clone``. Each option
listed will be transformed into its own ``--config <option>`` on the
``git clone`` command line, with each option required to be in the
form ``key=value``.
``GIT_REMOTE_UPDATE_STRATEGY <strategy>``
+ .. versionadded:: 3.18
+
When ``GIT_TAG`` refers to a remote branch, this option can be used to
specify how the update step behaves. The ``<strategy>`` must be one of
the following:
@@ -379,6 +418,8 @@ External Project Definition
:manual:`generator expressions <cmake-generator-expressions(7)>`.
``UPDATE_DISCONNECTED <bool>``
+ .. versionadded:: 3.2
+
When enabled, this option causes the update step to be skipped. It does
not, however, prevent the download step. The update step can still be
added as a step target (see :command:`ExternalProject_Add_StepTargets`)
@@ -436,6 +477,8 @@ External Project Definition
``CONFIGURE_COMMAND`` option.
``CMAKE_GENERATOR_PLATFORM <platform>``
+ .. versionadded:: 3.1
+
Pass a generator-specific platform name to the CMake command (see
:variable:`CMAKE_GENERATOR_PLATFORM`). It is an error to provide this
option without the ``CMAKE_GENERATOR`` option.
@@ -446,6 +489,8 @@ External Project Definition
option without the ``CMAKE_GENERATOR`` option.
``CMAKE_GENERATOR_INSTANCE <instance>``
+ .. versionadded:: 3.11
+
Pass a generator-specific instance selection to the CMake command (see
:variable:`CMAKE_GENERATOR_INSTANCE`). It is an error to provide this
option without the ``CMAKE_GENERATOR`` option.
@@ -454,8 +499,10 @@ External Project Definition
The specified arguments are passed to the ``cmake`` command line. They
can be any argument the ``cmake`` command understands, not just cache
values defined by ``-D...`` arguments (see also
- :manual:`CMake Options <cmake(1)>`). In addition, arguments may use
- :manual:`generator expressions <cmake-generator-expressions(7)>`.
+ :manual:`CMake Options <cmake(1)>`).
+
+ .. versionadded:: 3.3
+ Arguments may use :manual:`generator expressions <cmake-generator-expressions(7)>`.
``CMAKE_CACHE_ARGS <arg>...``
This is an alternate way of specifying cache variables where command line
@@ -463,10 +510,14 @@ External Project Definition
the form ``-Dvar:STRING=value``, which are then transformed into
CMake :command:`set` commands with the ``FORCE`` option used. These
``set()`` commands are written to a pre-load script which is then applied
- using the :manual:`cmake -C <cmake(1)>` command line option. Arguments
- may use :manual:`generator expressions <cmake-generator-expressions(7)>`.
+ using the :manual:`cmake -C <cmake(1)>` command line option.
+
+ .. versionadded:: 3.3
+ Arguments may use :manual:`generator expressions <cmake-generator-expressions(7)>`.
``CMAKE_CACHE_DEFAULT_ARGS <arg>...``
+ .. versionadded:: 3.2
+
This is the same as the ``CMAKE_CACHE_ARGS`` option except the ``set()``
commands do not include the ``FORCE`` keyword. This means the values act
as initial defaults only and will not override any variables already set
@@ -474,20 +525,37 @@ External Project Definition
different behavior depending on whether the build starts from a fresh
build directory or re-uses previous build contents.
- If the CMake generator is the ``Green Hills MULTI`` and not overridden then
- the original project's settings for the GHS toolset and target system
- customization cache variables are propagated into the external project.
+ .. versionadded:: 3.15
+ If the CMake generator is the ``Green Hills MULTI`` and not overridden then
+ the original project's settings for the GHS toolset and target system
+ customization cache variables are propagated into the external project.
``SOURCE_SUBDIR <dir>``
+ .. versionadded:: 3.7
+
When no ``CONFIGURE_COMMAND`` option is specified, the configure step
assumes the external project has a ``CMakeLists.txt`` file at the top of
its source tree (i.e. in ``SOURCE_DIR``). The ``SOURCE_SUBDIR`` option
can be used to point to an alternative directory within the source tree
to use as the top of the CMake source tree instead. This must be a
relative path and it will be interpreted as being relative to
- ``SOURCE_DIR``. When ``BUILD_IN_SOURCE 1`` is specified, the
- ``BUILD_COMMAND`` is used to point to an alternative directory within the
- source tree.
+ ``SOURCE_DIR``.
+
+ .. versionadded:: 3.14
+ When ``BUILD_IN_SOURCE`` option is enabled, the ``BUILD_COMMAND``
+ is used to point to an alternative directory within the source tree.
+
+ ``CONFIGURE_HANDLED_BY_BUILD <bool>``
+ .. versionadded:: 3.20
+
+ Enabling this option relaxes the dependencies of the configure step on
+ other external projects to order-only. This means the configure step will
+ be executed after its external project dependencies are built but it will
+ not be marked dirty when one of its external project dependencies is
+ rebuilt. This option can be enabled when the build step is smart enough
+ to figure out if the configure step needs to be rerun. CMake and Meson are
+ examples of build systems whose build step is smart enough to know if the
+ configure step needs to be rerun.
**Build Step Options:**
If the configure step assumed the external project uses CMake as its build
@@ -524,6 +592,8 @@ External Project Definition
developers might modify the sources in ``SOURCE_DIR``).
``BUILD_BYPRODUCTS <file>...``
+ .. versionadded:: 3.2
+
Specifies files that will be generated by the build command but which
might or might not have their modification time updated by subsequent
builds. These ultimately get passed through as ``BYPRODUCTS`` to the
@@ -578,6 +648,8 @@ External Project Definition
``TEST_AFTER_INSTALL`` are enabled, the latter is silently ignored.
``TEST_EXCLUDE_FROM_MAIN <bool>``
+ .. versionadded:: 3.2
+
If enabled, the main build's default ALL target will not depend on the
test step. This can be a useful way of ensuring the test step is defined
but only gets invoked when manually requested.
@@ -597,6 +669,8 @@ External Project Definition
When enabled, the output of the update step is logged to files.
``LOG_PATCH <bool>``
+ .. versionadded:: 3.14
+
When enabled, the output of the patch step is logged to files.
``LOG_CONFIGURE <bool>``
@@ -612,10 +686,14 @@ External Project Definition
When enabled, the output of the test step is logged to files.
``LOG_MERGED_STDOUTERR <bool>``
+ .. versionadded:: 3.14
+
When enabled, stdout and stderr will be merged for any step whose
output is being logged to files.
``LOG_OUTPUT_ON_FAILURE <bool>``
+ .. versionadded:: 3.14
+
This option only has an effect if at least one of the other ``LOG_<step>``
options is enabled. If an error occurs for a step which has logging to
file enabled, that step's output will be printed to the console if
@@ -624,6 +702,8 @@ External Project Definition
console.
**Terminal Access Options:**
+ .. versionadded:: 3.4
+
Steps can be given direct access to the terminal in some cases. Giving a
step access to the terminal may allow it to receive terminal input if
required, such as for authentication details not provided by other options.
@@ -673,8 +753,9 @@ External Project Definition
discussion of the effects of this option.
``INDEPENDENT_STEP_TARGETS <step-target>...``
- Deprecated. This is allowed only if policy :policy:`CMP0114` is not set
- to ``NEW``.
+ .. deprecated:: 3.19
+ This is allowed only if policy :policy:`CMP0114` is not set to ``NEW``.
+
Generates custom targets for the specified steps and prevent these targets
from having the usual dependencies applied to them. If this option is not
specified, the default value is taken from the
@@ -780,6 +861,8 @@ control needed to implement such step-level capabilities.
Files on which this custom step depends.
``INDEPENDENT <bool>``
+ .. versionadded:: 3.19
+
Specifies whether this step is independent of the external dependencies
specified by the :command:`ExternalProject_Add`'s ``DEPENDS`` option.
The default is ``FALSE``. Steps marked as independent may depend only
@@ -795,6 +878,8 @@ control needed to implement such step-level capabilities.
on the external targets, but may depend on targets for other steps.
``BYPRODUCTS <file>...``
+ .. versionadded:: 3.2
+
Files that will be generated by this custom step but which might or might
not have their modification time updated by subsequent builds. This list of
files will ultimately be passed through as the ``BYPRODUCTS`` option to the
@@ -831,6 +916,12 @@ control needed to implement such step-level capabilities.
corresponding property values defined in the original call to
:command:`ExternalProject_Add`.
+ .. versionadded:: 3.3
+ Token replacement is extended to byproducts.
+
+ .. versionadded:: 3.11
+ The ``<DOWNLOAD_DIR>`` substitution token.
+
.. command:: ExternalProject_Add_StepTargets
The ``ExternalProject_Add_StepTargets()`` function generates targets for the
@@ -868,15 +959,16 @@ control needed to implement such step-level capabilities.
can save having to repeatedly specify the same set of step targets when
multiple external projects are being defined.
- If :policy:`CMP0114` is set to ``NEW``, step targets are fully responsible
- for holding the custom commands implementing their steps. The primary target
- created by ``ExternalProject_Add`` depends on the step targets, and the
- step targets depend on each other. The target-level dependencies match
- the file-level dependencies used by the custom commands for each step.
- The targets for steps created with :command:`ExternalProject_Add_Step`'s
- ``INDEPENDENT`` option do not depend on the external targets specified
- by :command:`ExternalProject_Add`'s ``DEPENDS`` option. The predefined
- steps ``mkdir``, ``download``, ``update``, and ``patch`` are independent.
+ .. versionadded:: 3.19
+ If :policy:`CMP0114` is set to ``NEW``, step targets are fully responsible
+ for holding the custom commands implementing their steps. The primary target
+ created by ``ExternalProject_Add`` depends on the step targets, and the
+ step targets depend on each other. The target-level dependencies match
+ the file-level dependencies used by the custom commands for each step.
+ The targets for steps created with :command:`ExternalProject_Add_Step`'s
+ ``INDEPENDENT`` option do not depend on the external targets specified
+ by :command:`ExternalProject_Add`'s ``DEPENDS`` option. The predefined
+ steps ``mkdir``, ``download``, ``update``, and ``patch`` are independent.
If :policy:`CMP0114` is not ``NEW``, the following deprecated behavior
is available:
@@ -901,6 +993,8 @@ control needed to implement such step-level capabilities.
.. command:: ExternalProject_Add_StepDependencies
+ .. versionadded:: 3.2
+
The ``ExternalProject_Add_StepDependencies()`` function can be used to add
dependencies to a step. The dependencies added must be targets CMake already
knows about (these can be ordinary executable or library targets, custom
@@ -1019,60 +1113,37 @@ cmake_policy(PUSH)
cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST
-# Pre-compute a regex to match documented keywords for each command.
-math(EXPR _ep_documentation_line_count "${CMAKE_CURRENT_LIST_LINE} - 4")
-file(STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines
- LIMIT_COUNT ${_ep_documentation_line_count}
- REGEX "^\\.\\. command:: [A-Za-z0-9_]+|^ +``[A-Z0-9_]+ [^`]*``$")
-foreach(line IN LISTS lines)
- if("${line}" MATCHES "^\\.\\. command:: ([A-Za-z0-9_]+)")
- if(_ep_func)
- string(APPEND _ep_keywords_${_ep_func} ")$")
- endif()
- set(_ep_func "${CMAKE_MATCH_1}")
- #message("function [${_ep_func}]")
- set(_ep_keywords_${_ep_func} "^(")
- set(_ep_keyword_sep)
- elseif("${line}" MATCHES "^ +``([A-Z0-9_]+) [^`]*``$")
- set(_ep_key "${CMAKE_MATCH_1}")
- # COMMAND should never be included as a keyword,
- # for ExternalProject_Add(), as it is treated as a
- # special case by argument parsing as an extension
- # of a previous ..._COMMAND
- if("x${_ep_key}x" STREQUAL "xCOMMANDx" AND
- "x${_ep_func}x" STREQUAL "xExternalProject_Addx")
- continue()
- endif()
- #message(" keyword [${_ep_key}]")
- string(APPEND _ep_keywords_${_ep_func}
- "${_ep_keyword_sep}${_ep_key}")
- set(_ep_keyword_sep "|")
- endif()
-endforeach()
-if(_ep_func)
- string(APPEND _ep_keywords_${_ep_func} ")$")
-endif()
-
-# Save regex matching supported hash algorithm names.
-set(_ep_hash_algos "MD5|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3_224|SHA3_256|SHA3_384|SHA3_512")
-set(_ep_hash_regex "^(${_ep_hash_algos})=([0-9A-Fa-f]+)$")
+macro(_ep_get_hash_algos out_var)
+ set(${out_var}
+ MD5
+ SHA1
+ SHA224
+ SHA256
+ SHA384
+ SHA512
+ SHA3_224
+ SHA3_256
+ SHA3_384
+ SHA3_512
+ )
+endmacro()
-set(_ExternalProject_SELF "${CMAKE_CURRENT_LIST_FILE}")
-get_filename_component(_ExternalProject_SELF_DIR "${_ExternalProject_SELF}" PATH)
+macro(_ep_get_hash_regex out_var)
+ _ep_get_hash_algos(${out_var})
+ list(JOIN ${out_var} "|" ${out_var})
+ set(${out_var} "^(${${out_var}})=([0-9A-Fa-f]+)$")
+endmacro()
-function(_ep_parse_arguments f name ns args)
+function(_ep_parse_arguments f keywords name ns args)
# Transfer the arguments to this function into target properties for the
# new custom target we just added so that we can set up all the build steps
# correctly based on target properties.
#
- # We loop through ARGN and consider the namespace starting with an
+ # Because some keywords can be repeated, we can't use cmake_parse_arguments().
+ # Instead, we loop through ARGN and consider the namespace starting with an
# upper-case letter followed by at least two more upper-case letters,
# numbers or underscores to be keywords.
- if(NOT DEFINED _ExternalProject_SELF)
- message(FATAL_ERROR "error: ExternalProject module must be explicitly included before using ${f} function")
- endif()
-
set(key)
foreach(arg IN LISTS args)
@@ -1081,7 +1152,7 @@ function(_ep_parse_arguments f name ns args)
if(arg MATCHES "^[A-Z][A-Z0-9_][A-Z0-9_]+$" AND
NOT (("x${arg}x" STREQUAL "x${key}x") AND ("x${key}x" STREQUAL "xCOMMANDx")) AND
NOT arg MATCHES "^(TRUE|FALSE)$")
- if(_ep_keywords_${f} AND arg MATCHES "${_ep_keywords_${f}}")
+ if(arg IN_LIST keywords)
set(is_value 0)
endif()
endif()
@@ -1106,9 +1177,6 @@ function(_ep_parse_arguments f name ns args)
endif()
else()
set(key "${arg}")
- if(key MATCHES GIT)
- get_property(have_key TARGET ${name} PROPERTY ${ns}${key} SET)
- endif()
endif()
endforeach()
endfunction()
@@ -1330,14 +1398,17 @@ function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_r
if("${git_tag}" STREQUAL "")
message(FATAL_ERROR "Tag for git checkout should not be empty.")
endif()
- if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.6)
- set(git_stash_save_options --all --quiet)
- else()
- set(git_stash_save_options --quiet)
+ set(git_stash_save_options --quiet)
+ if(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.7)
+ # This avoids stashing files covered by .gitignore
+ list(APPEND git_stash_save_options --include-untracked)
+ elseif(GIT_VERSION_STRING VERSION_GREATER_EQUAL 1.7.6)
+ # Untracked files, but also ignored files, so potentially slower
+ list(APPEND git_stash_save_options --all)
endif()
configure_file(
- "${_ExternalProject_SELF_DIR}/ExternalProject-gitupdate.cmake.in"
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-gitupdate.cmake.in"
"${script_filename}"
@ONLY
)
@@ -1366,6 +1437,7 @@ function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inac
set(SHOW_PROGRESS "SHOW_PROGRESS")
endif()
+ _ep_get_hash_regex(_ep_hash_regex)
if("${hash}" MATCHES "${_ep_hash_regex}")
set(ALGO "${CMAKE_MATCH_1}")
string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
@@ -1446,13 +1518,14 @@ function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout inac
# * USERPWD_ARGS
# * HTTP_HEADERS_ARGS
configure_file(
- "${_ExternalProject_SELF_DIR}/ExternalProject-download.cmake.in"
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-download.cmake.in"
"${script_filename}"
@ONLY
)
endfunction()
function(_ep_write_verifyfile_script script_filename LOCAL hash)
+ _ep_get_hash_regex(_ep_hash_regex)
if("${hash}" MATCHES "${_ep_hash_regex}")
set(ALGO "${CMAKE_MATCH_1}")
string(TOLOWER "${CMAKE_MATCH_2}" EXPECT_VALUE)
@@ -1466,7 +1539,7 @@ function(_ep_write_verifyfile_script script_filename LOCAL hash)
# * EXPECT_VALUE
# * LOCAL
configure_file(
- "${_ExternalProject_SELF_DIR}/ExternalProject-verify.cmake.in"
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject-verify.cmake.in"
"${script_filename}"
@ONLY
)
@@ -1984,8 +2057,10 @@ if(result)
message(FATAL_ERROR \"\${msg}\")
endif()
else()
- set(msg \"${name} ${step} command succeeded. See also ${logbase}-*.log\")
- message(STATUS \"\${msg}\")
+ if(NOT \"${CMAKE_GENERATOR}\" MATCHES \"Ninja\")
+ set(msg \"${name} ${step} command succeeded. See also ${logbase}-*.log\")
+ message(STATUS \"\${msg}\")
+ endif()
endif()
")
file(GENERATE OUTPUT "${script}" CONTENT "${code}")
@@ -2153,7 +2228,21 @@ function(ExternalProject_Add_Step name step)
_ep_get_complete_stampfile(${name} complete_stamp_file)
_ep_get_step_stampfile(${name} ${step} stamp_file)
- _ep_parse_arguments(ExternalProject_Add_Step
+ set(keywords
+ COMMAND
+ COMMENT
+ DEPENDEES
+ DEPENDERS
+ DEPENDS
+ INDEPENDENT
+ BYPRODUCTS
+ ALWAYS
+ EXCLUDE_FROM_MAIN
+ WORKING_DIRECTORY
+ LOG
+ USES_TERMINAL
+ )
+ _ep_parse_arguments(ExternalProject_Add_Step "${keywords}"
${name} _EP_${step}_ "${ARGN}")
get_property(independent TARGET ${name} PROPERTY _EP_${step}_INDEPENDENT)
@@ -2536,10 +2625,13 @@ function(_ep_add_download_command name)
--non-interactive ${svn_trust_cert_args} ${svn_user_pw_args} ${src_name})
list(APPEND depends ${stamp_dir}/${name}-svninfo.txt)
elseif(git_repository)
- unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
- find_package(Git QUIET)
- if(NOT GIT_EXECUTABLE)
- message(FATAL_ERROR "error: could not find git for clone of ${name}")
+ # FetchContent gives us these directly, so don't try to recompute them
+ if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
+ unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
+ find_package(Git QUIET)
+ if(NOT GIT_EXECUTABLE)
+ message(FATAL_ERROR "error: could not find git for clone of ${name}")
+ endif()
endif()
_ep_get_git_submodules_recurse(git_submodules_recurse)
@@ -2571,6 +2663,10 @@ function(_ep_add_download_command name)
get_property(git_progress TARGET ${name} PROPERTY _EP_GIT_PROGRESS)
get_property(git_config TARGET ${name} PROPERTY _EP_GIT_CONFIG)
+ # Make checkouts quiet when checking out a git hash (this avoids the
+ # very noisy detached head message)
+ list(PREPEND git_config advice.detachedHead=false)
+
# For the download step, and the git clone operation, only the repository
# should be recorded in a configured RepositoryInfo file. If the repo
# changes, the clone script should be run again. But if only the tag
@@ -2643,7 +2739,10 @@ function(_ep_add_download_command name)
elseif(url)
get_filename_component(work_dir "${source_dir}" PATH)
get_property(hash TARGET ${name} PROPERTY _EP_URL_HASH)
+ _ep_get_hash_regex(_ep_hash_regex)
if(hash AND NOT "${hash}" MATCHES "${_ep_hash_regex}")
+ _ep_get_hash_algos(_ep_hash_algos)
+ list(JOIN _ep_hash_algos "|" _ep_hash_algos)
message(FATAL_ERROR "URL_HASH is set to\n ${hash}\n"
"but must be ALGO=value where ALGO is\n ${_ep_hash_algos}\n"
"and value is a hex string.")
@@ -2857,10 +2956,13 @@ function(_ep_add_update_command name)
--non-interactive ${svn_trust_cert_args} ${svn_user_pw_args})
set(always 1)
elseif(git_repository)
- unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
- find_package(Git QUIET)
- if(NOT GIT_EXECUTABLE)
- message(FATAL_ERROR "error: could not find git for fetch of ${name}")
+ # FetchContent gives us these directly, so don't try to recompute them
+ if(NOT GIT_EXECUTABLE OR NOT GIT_VERSION_STRING)
+ unset(CMAKE_MODULE_PATH) # Use CMake builtin find module
+ find_package(Git QUIET)
+ if(NOT GIT_EXECUTABLE)
+ message(FATAL_ERROR "error: could not find git for fetch of ${name}")
+ endif()
endif()
set(work_dir ${source_dir})
set(comment "Performing update step for '${name}'")
@@ -3001,6 +3103,23 @@ function(_ep_add_patch_command name)
)
endfunction()
+function(_ep_get_file_deps var name)
+ set(file_deps)
+
+ get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
+ foreach(dep IN LISTS deps)
+ get_property(dep_type TARGET ${dep} PROPERTY TYPE)
+ if(dep_type STREQUAL "UTILITY")
+ get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
+ if(is_ep)
+ _ep_get_step_stampfile(${dep} "done" done_stamp_file)
+ list(APPEND file_deps ${done_stamp_file})
+ endif()
+ endif()
+ endforeach()
+
+ set("${var}" "${file_deps}" PARENT_SCOPE)
+endfunction()
function(_ep_extract_configure_command var name)
get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET)
@@ -3109,19 +3228,13 @@ endfunction()
function(_ep_add_configure_command name)
ExternalProject_Get_Property(${name} binary_dir tmp_dir)
- # Depend on other external projects (file-level).
set(file_deps)
- get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
- foreach(dep IN LISTS deps)
- get_property(dep_type TARGET ${dep} PROPERTY TYPE)
- if(dep_type STREQUAL "UTILITY")
- get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
- if(is_ep)
- _ep_get_step_stampfile(${dep} "done" done_stamp_file)
- list(APPEND file_deps ${done_stamp_file})
- endif()
- endif()
- endforeach()
+ get_property(configure_handled_by_build TARGET ${name}
+ PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD)
+ if(NOT configure_handled_by_build)
+ # Depend on other external projects (file-level)
+ _ep_get_file_deps(file_deps ${name})
+ endif()
_ep_extract_configure_command(cmd ${name})
@@ -3172,6 +3285,14 @@ endfunction()
function(_ep_add_build_command name)
ExternalProject_Get_Property(${name} binary_dir)
+ set(file_deps)
+ get_property(configure_handled_by_build TARGET ${name}
+ PROPERTY _EP_CONFIGURE_HANDLED_BY_BUILD)
+ if(configure_handled_by_build)
+ # Depend on other external projects (file-level)
+ _ep_get_file_deps(file_deps ${name})
+ endif()
+
get_property(cmd_set TARGET ${name} PROPERTY _EP_BUILD_COMMAND SET)
if(cmd_set)
get_property(cmd TARGET ${name} PROPERTY _EP_BUILD_COMMAND)
@@ -3214,6 +3335,7 @@ function(_ep_add_build_command name)
BYPRODUCTS \${build_byproducts}
WORKING_DIRECTORY \${binary_dir}
DEPENDEES configure
+ DEPENDS \${file_deps}
ALWAYS \${always}
${log}
${uses_terminal}
@@ -3378,7 +3500,136 @@ function(ExternalProject_Add name)
set_property(TARGET ${name} PROPERTY _EP_CMP0114 "${cmp0114}")
- _ep_parse_arguments(ExternalProject_Add ${name} _EP_ "${ARGN}")
+ set(keywords
+ #
+ # Directory options
+ #
+ PREFIX
+ TMP_DIR
+ STAMP_DIR
+ LOG_DIR
+ DOWNLOAD_DIR
+ SOURCE_DIR
+ BINARY_DIR
+ INSTALL_DIR
+ #
+ # Download step options
+ #
+ DOWNLOAD_COMMAND
+ #
+ URL
+ URL_HASH
+ URL_MD5
+ DOWNLOAD_NAME
+ DOWNLOAD_NO_EXTRACT
+ DOWNLOAD_NO_PROGRESS
+ TIMEOUT
+ INACTIVITY_TIMEOUT
+ HTTP_USERNAME
+ HTTP_PASSWORD
+ HTTP_HEADER
+ TLS_VERIFY # Also used for git clone operations
+ TLS_CAINFO
+ NETRC
+ NETRC_FILE
+ #
+ GIT_REPOSITORY
+ GIT_TAG
+ GIT_REMOTE_NAME
+ GIT_SUBMODULES
+ GIT_SUBMODULES_RECURSE
+ GIT_SHALLOW
+ GIT_PROGRESS
+ GIT_CONFIG
+ GIT_REMOTE_UPDATE_STRATEGY
+ #
+ SVN_REPOSITORY
+ SVN_REVISION
+ SVN_USERNAME
+ SVN_PASSWORD
+ SVN_TRUST_CERT
+ #
+ HG_REPOSITORY
+ HG_TAG
+ #
+ CVS_REPOSITORY
+ CVS_MODULE
+ CVS_TAG
+ #
+ # Update step options
+ #
+ UPDATE_COMMAND
+ UPDATE_DISCONNECTED
+ #
+ # Patch step options
+ #
+ PATCH_COMMAND
+ #
+ # Configure step options
+ #
+ CONFIGURE_COMMAND
+ CMAKE_COMMAND
+ CMAKE_GENERATOR
+ CMAKE_GENERATOR_PLATFORM
+ CMAKE_GENERATOR_TOOLSET
+ CMAKE_GENERATOR_INSTANCE
+ CMAKE_ARGS
+ CMAKE_CACHE_ARGS
+ CMAKE_CACHE_DEFAULT_ARGS
+ SOURCE_SUBDIR
+ CONFIGURE_HANDLED_BY_BUILD
+ #
+ # Build step options
+ #
+ BUILD_COMMAND
+ BUILD_IN_SOURCE
+ BUILD_ALWAYS
+ BUILD_BYPRODUCTS
+ #
+ # Install step options
+ #
+ INSTALL_COMMAND
+ #
+ # Test step options
+ #
+ TEST_COMMAND
+ TEST_BEFORE_INSTALL
+ TEST_AFTER_INSTALL
+ TEST_EXCLUDE_FROM_MAIN
+ #
+ # Logging options
+ #
+ LOG_DOWNLOAD
+ LOG_UPDATE
+ LOG_PATCH
+ LOG_CONFIGURE
+ LOG_BUILD
+ LOG_INSTALL
+ LOG_TEST
+ LOG_MERGED_STDOUTERR
+ LOG_OUTPUT_ON_FAILURE
+ #
+ # Terminal access options
+ #
+ USES_TERMINAL_DOWNLOAD
+ USES_TERMINAL_UPDATE
+ USES_TERMINAL_CONFIGURE
+ USES_TERMINAL_BUILD
+ USES_TERMINAL_INSTALL
+ USES_TERMINAL_TEST
+ #
+ # Target options
+ #
+ DEPENDS
+ EXCLUDE_FROM_ALL
+ STEP_TARGETS
+ INDEPENDENT_STEP_TARGETS
+ #
+ # Miscellaneous options
+ #
+ LIST_SEPARATOR
+ )
+ _ep_parse_arguments(ExternalProject_Add "${keywords}" ${name} _EP_ "${ARGN}")
_ep_set_directories(${name})
_ep_get_step_stampfile(${name} "done" done_stamp_file)
_ep_get_step_stampfile(${name} "install" install_stamp_file)
diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake
index 4a3e83af3..77c66d14a 100644
--- a/Modules/FeatureSummary.cmake
+++ b/Modules/FeatureSummary.cmake
@@ -66,6 +66,8 @@ The default value for this global property is ``OPTIONAL``.
.. variable:: FeatureSummary_<TYPE>_DESCRIPTION
+.. versionadded:: 3.9
+
The global property :variable:`FeatureSummary_<TYPE>_DESCRIPTION` can be defined
for each type to replace the type name with the specified string whenever the
package type is used in an output string.
@@ -242,12 +244,13 @@ endfunction()
``<TYPE>_PACKAGES_NOT_FOUND``
only those packages which have not been found which have the type <TYPE>
- With the exception of the ``ALL`` value, these values can be combined
- in order to customize the output. For example:
+ .. versionchanged:: 3.1
+ With the exception of the ``ALL`` value, these values can be combined
+ in order to customize the output. For example:
- .. code-block:: cmake
+ .. code-block:: cmake
- feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)
+ feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)
If a ``FILENAME`` is given, the information is printed into this file. If
``APPEND`` is used, it is appended to this file, otherwise the file is
@@ -268,14 +271,18 @@ endfunction()
The default value for the :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global
property is ``REQUIRED``.
+ .. versionadded:: 3.9
+ The ``DEFAULT_DESCRIPTION`` option.
+
The :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global property can be
modified to change the default package type assigned when not explicitly
assigned by the user.
- If the ``QUIET_ON_EMPTY`` option is used, if only one type of package was
- requested, and no packages belonging to that category were found, then no
- output (including the ``DESCRIPTION``) is printed or added to the ``VAR``
- variable.
+ .. versionadded:: 3.8
+ If the ``QUIET_ON_EMPTY`` option is used, if only one type of package was
+ requested, and no packages belonging to that category were found, then no
+ output (including the ``DESCRIPTION``) is printed or added to the ``VAR``
+ variable.
Example 1, append everything to a file:
@@ -617,6 +624,9 @@ endfunction()
be displayed using ``feature_summary()`` for ``ENABLED_FEATURES`` and
``DISABLED_FEATURES`` respectively.
+ .. versionchanged:: 3.8
+ ``<enabled>`` can be a list of conditions.
+
Example for setting the info for a feature:
.. code-block:: cmake
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index c81b3711a..8adef4777 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -77,6 +77,9 @@ operation and would not normally be the way the module is used, but it is
sometimes useful as part of implementing some higher level feature or to
populate some content in CMake's script mode.
+.. versionchanged:: 3.14
+ ``FetchContent`` commands can access the terminal. This is necessary
+ for password prompts and real-time progress displays to work.
Commands
^^^^^^^^
@@ -371,6 +374,8 @@ is simpler and provides additional features over the pattern above.
:variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately
on the command line invoking the script.
+ .. versionadded:: 3.18
+ Added support for ``DOWNLOAD_NO_EXTRACT`` and ``SOURCE_SUBDIR`` options.
.. command:: FetchContent_GetProperties
@@ -416,6 +421,8 @@ is simpler and provides additional features over the pattern above.
FetchContent_MakeAvailable( <name1> [<name2>...] )
+ .. versionadded:: 3.14
+
This command implements the common pattern typically needed for most
dependencies. It iterates over each of the named dependencies in turn
and for each one it loosely follows the
@@ -957,6 +964,22 @@ ExternalProject_Add_Step(${contentName}-populate copyfile
"-DCMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY=${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
endif()
+ # Avoid using if(... IN_LIST ...) so we don't have to alter policy settings
+ set(__FETCHCONTENT_CACHED_INFO "")
+ list(FIND ARG_UNPARSED_ARGUMENTS GIT_REPOSITORY indexResult)
+ if(indexResult GREATER_EQUAL 0)
+ find_package(Git QUIET)
+ set(__FETCHCONTENT_CACHED_INFO
+"# Pass through things we've already detected in the main project to avoid
+# paying the cost of redetecting them again in ExternalProject_Add()
+set(GIT_EXECUTABLE [==[${GIT_EXECUTABLE}]==])
+set(GIT_VERSION_STRING [==[${GIT_VERSION_STRING}]==])
+set_property(GLOBAL PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION
+ [==[${GIT_EXECUTABLE};${GIT_VERSION_STRING}]==]
+)
+")
+ endif()
+
# Create and build a separate CMake project to carry out the population.
# If we've already previously done these steps, they will not cause
# anything to be updated, so extra rebuilds of the project won't occur.
diff --git a/Modules/FetchContent/CMakeLists.cmake.in b/Modules/FetchContent/CMakeLists.cmake.in
index 45e4df03e..5ebb12f1a 100644
--- a/Modules/FetchContent/CMakeLists.cmake.in
+++ b/Modules/FetchContent/CMakeLists.cmake.in
@@ -9,6 +9,8 @@ cmake_minimum_required(VERSION ${CMAKE_VERSION})
project(${contentName}-populate NONE)
+@__FETCHCONTENT_CACHED_INFO@
+
include(ExternalProject)
ExternalProject_Add(${contentName}-populate
${ARG_EXTRA}
diff --git a/Modules/FindALSA.cmake b/Modules/FindALSA.cmake
index 88e2681eb..627866a4d 100644
--- a/Modules/FindALSA.cmake
+++ b/Modules/FindALSA.cmake
@@ -12,6 +12,8 @@ Find the alsa libraries (``asound``)
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.12
+
This module defines :prop_tgt:`IMPORTED` target ``ALSA::ALSA``, if
ALSA has been found.
diff --git a/Modules/FindArmadillo.cmake b/Modules/FindArmadillo.cmake
index c8a31a038..f959356b2 100644
--- a/Modules/FindArmadillo.cmake
+++ b/Modules/FindArmadillo.cmake
@@ -8,6 +8,9 @@ FindArmadillo
Find the Armadillo C++ library.
Armadillo is a library for linear algebra & scientific computing.
+.. versionadded:: 3.18
+ Support for linking wrapped libraries directly (``ARMA_DONT_USE_WRAPPER``).
+
Using Armadillo:
::
diff --git a/Modules/FindBISON.cmake b/Modules/FindBISON.cmake
index 1e1a5a3b4..3515bf0dd 100644
--- a/Modules/FindBISON.cmake
+++ b/Modules/FindBISON.cmake
@@ -35,21 +35,31 @@ the path to a yacc file. ``<CodeOutput>`` is the name of the source file
generated by bison. A header file is also be generated, and contains
the token list.
+.. versionchanged:: 3.14
+ When :policy:`CMP0088` is set to ``NEW``, ``bison`` runs in the
+ :variable:`CMAKE_CURRENT_BINARY_DIR` directory.
+
The options are:
``COMPILE_FLAGS <flags>``
Specify flags to be added to the ``bison`` command line.
``DEFINES_FILE <file>``
+ .. versionadded:: 3.4
+
Specify a non-default header ``<file>`` to be generated by ``bison``.
``VERBOSE [<file>]``
Tell ``bison`` to write a report file of the grammar and parser.
- If ``<file>`` is given, it specifies path the report file is copied to.
- ``[<file>]`` is left for backward compatibility of this module.
- Use ``VERBOSE REPORT_FILE <file>``.
+
+ .. deprecated:: 3.7
+ If ``<file>`` is given, it specifies path the report file is copied to.
+ ``[<file>]`` is left for backward compatibility of this module.
+ Use ``VERBOSE REPORT_FILE <file>``.
``REPORT_FILE <file>``
+ .. versionadded:: 3.7
+
Specify a non-default report ``<file>``, if generated.
The macro defines the following variables:
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index e4353dfaf..4cf812b7f 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -53,18 +53,46 @@ The following variables may be set to influence this module's behavior:
* ``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``).
+
``BLA_F95``
if ``ON`` tries to find the BLAS95 interfaces
``BLA_PREFER_PKGCONFIG``
+ .. versionadded:: 3.11
+
if set ``pkg-config`` will be used to search for a BLAS library first
and if one is found that is preferred
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.18
+
This module defines the following :prop_tgt:`IMPORTED` target:
``BLAS::BLAS``
@@ -104,10 +132,13 @@ This module defines the following variables:
Hints
^^^^^
-Set the ``MKLROOT`` 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``).
+``MKLROOT``
+ .. versionadded:: 3.15
+
+ 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``).
#]=======================================================================]
@@ -586,16 +617,22 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")
else()
find_package(Threads REQUIRED)
endif()
+ set(_threadlibs "${CMAKE_THREAD_LIBS_INIT}")
+ if(BLA_STATIC)
+ find_package(OpenMP COMPONENTS C)
+ list(PREPEND _threadlibs "${OpenMP_C_LIBRARIES}")
+ endif()
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
"openblas"
- "${CMAKE_THREAD_LIBS_INIT}"
+ "${_threadlibs}"
""
""
)
+ unset(_threadlibs)
endif()
endif()
@@ -805,6 +842,9 @@ if(BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All")
if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
set(_ACML_COMPILER32 "ifort32")
set(_ACML_COMPILER64 "ifort64")
+ elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM")
+ # 32-bit not supported
+ set(_ACML_COMPILER64 "ifx")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "SunPro")
set(_ACML_COMPILER32 "sun32")
set(_ACML_COMPILER64 "sun64")
@@ -951,6 +991,31 @@ if(BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All")
endif()
endif()
+# Elbrus Math Library?
+if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All")
+
+ set(BLAS_EML_LIB "eml")
+
+ # Check for OpenMP support, VIA BLA_VENDOR of eml_mt
+ if(BLA_VENDOR MATCHES "_mt")
+ set(BLAS_EML_LIB "${BLAS_EML_LIB}_mt")
+ endif()
+
+ if(NOT BLAS_LIBRARIES)
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "${BLAS_EML_LIB}"
+ ""
+ ""
+ ""
+ )
+ endif()
+
+endif()
+
# Generic BLAS library?
if(BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All")
if(NOT BLAS_LIBRARIES)
diff --git a/Modules/FindBZip2.cmake b/Modules/FindBZip2.cmake
index 5704d1d83..355c4bb96 100644
--- a/Modules/FindBZip2.cmake
+++ b/Modules/FindBZip2.cmake
@@ -10,6 +10,8 @@ Try to find BZip2
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.12
+
This module defines :prop_tgt:`IMPORTED` target ``BZip2::BZip2``, if
BZip2 has been found.
@@ -21,7 +23,8 @@ This module defines the following variables:
``BZIP2_FOUND``
system has BZip2
``BZIP2_INCLUDE_DIRS``
- the BZip2 include directories
+ .. versionadded:: 3.12
+ the BZip2 include directories
``BZIP2_LIBRARIES``
Link these to use BZip2
``BZIP2_NEED_PREFIX``
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index 54d9593ca..f8887ad2b 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -7,7 +7,9 @@ FindBoost
Find Boost include dirs and libraries
-Use this module by invoking find_package with the form::
+Use this module by invoking :command:`find_package` with the form:
+
+.. code-block:: cmake
find_package(Boost
[version] [EXACT] # Minimum or EXACT version e.g. 1.67.0
@@ -20,97 +22,134 @@ Use this module by invoking find_package with the form::
This module finds headers and requested component libraries OR a CMake
package configuration file provided by a "Boost CMake" build. For the
-latter case skip to the "Boost CMake" section below. For the former
-case results are reported in variables::
-
- Boost_FOUND - True if headers and requested libraries were found
- Boost_INCLUDE_DIRS - Boost include directories
- Boost_LIBRARY_DIRS - Link directories for Boost libraries
- Boost_LIBRARIES - Boost component libraries to be linked
- Boost_<C>_FOUND - True if component <C> was found (<C> is upper-case)
- Boost_<C>_LIBRARY - Libraries to link for component <C> (may include
- target_link_libraries debug/optimized keywords)
- Boost_VERSION_MACRO - BOOST_VERSION value from boost/version.hpp
- Boost_VERSION_STRING - Boost version number in x.y.z format
- Boost_VERSION - if CMP0093 NEW => same as Boost_VERSION_STRING
- if CMP0093 OLD or unset => same as Boost_VERSION_MACRO
- Boost_LIB_VERSION - Version string appended to library filenames
- Boost_VERSION_MAJOR - Boost major version number (X in X.y.z)
- alias: Boost_MAJOR_VERSION
- Boost_VERSION_MINOR - Boost minor version number (Y in x.Y.z)
- alias: Boost_MINOR_VERSION
- Boost_VERSION_PATCH - Boost subminor version number (Z in x.y.Z)
- alias: Boost_SUBMINOR_VERSION
- Boost_VERSION_COUNT - Amount of version components (3)
- Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows)
- - Pass to add_definitions() to have diagnostic
- information about Boost's automatic linking
- displayed during compilation
-
-Note that Boost Python components require a Python version suffix
-(Boost 1.67 and later), e.g. ``python36`` or ``python27`` for the
-versions built against Python 3.6 and 2.7, respectively. This also
-applies to additional components using Python including
-``mpi_python`` and ``numpy``. Earlier Boost releases may use
-distribution-specific suffixes such as ``2``, ``3`` or ``2.7``.
-These may also be used as suffixes, but note that they are not
-portable.
-
-This module reads hints about search locations from variables::
-
- BOOST_ROOT - Preferred installation prefix
- (or BOOSTROOT)
- BOOST_INCLUDEDIR - Preferred include directory e.g. <prefix>/include
- BOOST_LIBRARYDIR - Preferred library directory e.g. <prefix>/lib
- Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not
- specified by these hint variables. Default is OFF.
- Boost_ADDITIONAL_VERSIONS
- - List of Boost versions not known to this module
- (Boost install locations may contain the version)
-
-and saves search results persistently in CMake cache entries::
-
- Boost_INCLUDE_DIR - Directory containing Boost headers
- Boost_LIBRARY_DIR_RELEASE - Directory containing release Boost libraries
- Boost_LIBRARY_DIR_DEBUG - Directory containing debug Boost libraries
- Boost_<C>_LIBRARY_DEBUG - Component <C> library debug variant
- Boost_<C>_LIBRARY_RELEASE - Component <C> library release variant
-
-The following :prop_tgt:`IMPORTED` targets are also defined::
-
- Boost::headers - Target for header-only dependencies
- (Boost include directory)
- alias: Boost::boost
- Boost::<C> - Target for specific component dependency
- (shared or static library); <C> is lower-
- case
- Boost::diagnostic_definitions - interface target to enable diagnostic
- information about Boost's automatic linking
- during compilation (adds BOOST_LIB_DIAGNOSTIC)
- Boost::disable_autolinking - interface target to disable automatic
- linking with MSVC (adds BOOST_ALL_NO_LIB)
- Boost::dynamic_linking - interface target to enable dynamic linking
- linking with MSVC (adds BOOST_ALL_DYN_LINK)
+latter case skip to the :ref:`Boost CMake` section below.
-Implicit dependencies such as ``Boost::filesystem`` requiring
-``Boost::system`` will be automatically detected and satisfied, even
-if system is not specified when using :command:`find_package` and if
-``Boost::system`` is not added to :command:`target_link_libraries`. If using
-``Boost::thread``, then ``Threads::Threads`` will also be added automatically.
+.. versionadded:: 3.7
+ ``bzip2`` and ``zlib`` components (Windows only).
-It is important to note that the imported targets behave differently
-than variables created by this module: multiple calls to
-:command:`find_package(Boost)` in the same directory or sub-directories with
-different options (e.g. static or shared) will not override the
-values of the targets created by the first call.
+.. versionadded:: 3.11
+ The ``OPTIONAL_COMPONENTS`` option.
+
+.. versionadded:: 3.13
+ ``stacktrace_*`` components.
+
+.. versionadded:: 3.19
+ ``bzip2`` and ``zlib`` components on all platforms.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``Boost_FOUND``
+ True if headers and requested libraries were found.
+
+``Boost_INCLUDE_DIRS``
+ Boost include directories.
+
+``Boost_LIBRARY_DIRS``
+ Link directories for Boost libraries.
+
+``Boost_LIBRARIES``
+ Boost component libraries to be linked.
+
+``Boost_<COMPONENT>_FOUND``
+ True if component ``<COMPONENT>`` was found (``<COMPONENT>`` name is upper-case).
+
+``Boost_<COMPONENT>_LIBRARY``
+ Libraries to link for component ``<COMPONENT>`` (may include
+ :command:`target_link_libraries` debug/optimized keywords).
+
+``Boost_VERSION_MACRO``
+ ``BOOST_VERSION`` value from ``boost/version.hpp``.
+
+``Boost_VERSION_STRING``
+ Boost version number in ``X.Y.Z`` format.
+
+``Boost_VERSION``
+ Boost version number in ``X.Y.Z`` format (same as ``Boost_VERSION_STRING``).
+
+ .. versionchanged:: 3.15
+ In previous CMake versions, this variable used the raw version string
+ from the Boost header (same as ``Boost_VERSION_MACRO``).
+ See policy :policy:`CMP0093`.
+
+``Boost_LIB_VERSION``
+ Version string appended to library filenames.
+
+``Boost_VERSION_MAJOR``, ``Boost_MAJOR_VERSION``
+ Boost major version number (``X`` in ``X.Y.Z``).
+
+``Boost_VERSION_MINOR``, ``Boost_MINOR_VERSION``
+ Boost minor version number (``Y`` in ``X.Y.Z``).
+
+``Boost_VERSION_PATCH``, ``Boost_SUBMINOR_VERSION``
+ Boost subminor version number (``Z`` in ``X.Y.Z``).
+
+``Boost_VERSION_COUNT``
+ Amount of version components (3).
+
+``Boost_LIB_DIAGNOSTIC_DEFINITIONS`` (Windows-specific)
+ Pass to :command:`add_definitions` to have diagnostic
+ information about Boost's automatic linking
+ displayed during compilation
+
+.. versionadded:: 3.15
+ The ``Boost_VERSION_<PART>`` variables.
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+Search results are saved persistently in CMake cache entries:
+
+``Boost_INCLUDE_DIR``
+ Directory containing Boost headers.
+
+``Boost_LIBRARY_DIR_RELEASE``
+ Directory containing release Boost libraries.
+
+``Boost_LIBRARY_DIR_DEBUG``
+ Directory containing debug Boost libraries.
+
+``Boost_<COMPONENT>_LIBRARY_DEBUG``
+ Component ``<COMPONENT>`` library debug variant.
+
+``Boost_<COMPONENT>_LIBRARY_RELEASE``
+ Component ``<COMPONENT>`` library release variant.
+
+.. versionadded:: 3.3
+ Per-configuration variables ``Boost_LIBRARY_DIR_RELEASE`` and
+ ``Boost_LIBRARY_DIR_DEBUG``.
+
+Hints
+^^^^^
+
+This module reads hints about search locations from variables:
+
+``BOOST_ROOT``, ``BOOSTROOT``
+ Preferred installation prefix.
+
+``BOOST_INCLUDEDIR``
+ Preferred include directory e.g. ``<prefix>/include``.
+
+``BOOST_LIBRARYDIR``
+ Preferred library directory e.g. ``<prefix>/lib``.
+
+``Boost_NO_SYSTEM_PATHS``
+ Set to ``ON`` to disable searching in locations not
+ specified by these hint variables. Default is ``OFF``.
+
+``Boost_ADDITIONAL_VERSIONS``
+ List of Boost versions not known to this module.
+ (Boost install locations may contain the version).
Users may set these hints or results as ``CACHE`` entries. Projects
should not read these entries directly but instead use the above
result variables. Note that some hint names start in upper-case
-"BOOST". One may specify these as environment variables if they are
+``BOOST``. One may specify these as environment variables if they are
not specified as CMake variables or cache entries.
-This module first searches for the ``Boost`` header files using the above
+This module first searches for the Boost header files using the above
hint variables (excluding ``BOOST_LIBRARYDIR``) and saves the result in
``Boost_INCLUDE_DIR``. Then it searches for requested component libraries
using the above hints (excluding ``BOOST_INCLUDEDIR`` and
@@ -118,83 +157,170 @@ using the above hints (excluding ``BOOST_INCLUDEDIR`` and
and the library name configuration settings below. It saves the
library directories in ``Boost_LIBRARY_DIR_DEBUG`` and
``Boost_LIBRARY_DIR_RELEASE`` and individual library
-locations in ``Boost_<C>_LIBRARY_DEBUG`` and ``Boost_<C>_LIBRARY_RELEASE``.
+locations in ``Boost_<COMPONENT>_LIBRARY_DEBUG`` and ``Boost_<COMPONENT>_LIBRARY_RELEASE``.
When one changes settings used by previous searches in the same build
tree (excluding environment variables) this module discards previous
search results affected by the changes and searches again.
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.5
+
+This module defines the following :prop_tgt:`IMPORTED` targets:
+
+``Boost::boost``
+ Target for header-only dependencies. (Boost include directory).
+
+``Boost::headers``
+ .. versionadded:: 3.15
+ Alias for ``Boost::boost``.
+
+``Boost::<component>``
+ Target for specific component dependency (shared or static library);
+ ``<component>`` name is lower-case.
+
+``Boost::diagnostic_definitions``
+ Interface target to enable diagnostic information about Boost's automatic
+ linking during compilation (adds ``-DBOOST_LIB_DIAGNOSTIC``).
+
+``Boost::disable_autolinking``
+ Interface target to disable automatic linking with MSVC
+ (adds ``-DBOOST_ALL_NO_LIB``).
+
+``Boost::dynamic_linking``
+ Interface target to enable dynamic linking linking with MSVC
+ (adds ``-DBOOST_ALL_DYN_LINK``).
+
+Implicit dependencies such as ``Boost::filesystem`` requiring
+``Boost::system`` will be automatically detected and satisfied, even
+if system is not specified when using :command:`find_package` and if
+``Boost::system`` is not added to :command:`target_link_libraries`. If using
+``Boost::thread``, then ``Threads::Threads`` will also be added automatically.
+
+It is important to note that the imported targets behave differently
+than variables created by this module: multiple calls to
+:command:`find_package(Boost)` in the same directory or sub-directories with
+different options (e.g. static or shared) will not override the
+values of the targets created by the first call.
+
+Other Variables
+^^^^^^^^^^^^^^^
+
Boost libraries come in many variants encoded in their file name.
Users or projects may tell this module which variant to find by
-setting variables::
-
- Boost_USE_DEBUG_LIBS - Set to ON or OFF to specify whether to search
- and use the debug libraries. Default is ON.
- Boost_USE_RELEASE_LIBS - Set to ON or OFF to specify whether to search
- and use the release libraries. Default is ON.
- Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded
- libraries ('mt' tag). Default is ON.
- Boost_USE_STATIC_LIBS - Set to ON to force the use of the static
- libraries. Default is OFF.
- Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use
- libraries linked statically to the C++ runtime
- ('s' tag). Default is platform dependent.
- Boost_USE_DEBUG_RUNTIME - Set to ON or OFF to specify whether to use
- libraries linked to the MS debug C++ runtime
- ('g' tag). Default is ON.
- Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a
- debug Python build ('y' tag). Default is OFF.
- Boost_USE_STLPORT - Set to ON to use libraries compiled with
- STLPort ('p' tag). Default is OFF.
- Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS
- - Set to ON to use libraries compiled with
- STLPort deprecated "native iostreams"
- ('n' tag). Default is OFF.
- Boost_COMPILER - Set to the compiler-specific library suffix
- (e.g. "-gcc43"). Default is auto-computed
- for the C++ compiler in use. A list may be
- used if multiple compatible suffixes should
- be tested for, in decreasing order of
- preference.
- Boost_LIB_PREFIX - Set to the platform-specific library name
- prefix (e.g. "lib") used by Boost static libs.
- This is needed only on platforms where CMake
- does not know the prefix by default.
- Boost_ARCHITECTURE - Set to the architecture-specific library suffix
- (e.g. "-x64"). Default is auto-computed for the
- C++ compiler in use.
- Boost_THREADAPI - Suffix for "thread" component library name,
- such as "pthread" or "win32". Names with
- and without this suffix will both be tried.
- Boost_NAMESPACE - Alternate namespace used to build boost with
- e.g. if set to "myboost", will search for
- myboost_thread instead of boost_thread.
-
-Other variables one may set to control this module are::
-
- Boost_DEBUG - Set to ON to enable debug output from FindBoost.
- Please enable this before filing any bug report.
- Boost_REALPATH - Set to ON to resolve symlinks for discovered
- libraries to assist with packaging. For example,
- the "system" component library may be resolved to
- "/usr/lib/libboost_system.so.1.67.0" instead of
- "/usr/lib/libboost_system.so". This does not
- affect linking and should not be enabled unless
- the user needs this information.
- Boost_LIBRARY_DIR - Default value for Boost_LIBRARY_DIR_RELEASE and
- Boost_LIBRARY_DIR_DEBUG.
+setting variables:
+
+``Boost_USE_DEBUG_LIBS``
+ .. versionadded:: 3.10
+
+ Set to ``ON`` or ``OFF`` to specify whether to search and use the debug
+ libraries. Default is ``ON``.
+
+``Boost_USE_RELEASE_LIBS``
+ .. versionadded:: 3.10
+
+ Set to ``ON`` or ``OFF`` to specify whether to search and use the release
+ libraries. Default is ``ON``.
+
+``Boost_USE_MULTITHREADED``
+ Set to OFF to use the non-multithreaded libraries ("mt" tag). Default is
+ ``ON``.
+
+``Boost_USE_STATIC_LIBS``
+ Set to ON to force the use of the static libraries. Default is ``OFF``.
+
+``Boost_USE_STATIC_RUNTIME``
+ Set to ``ON`` or ``OFF`` to specify whether to use libraries linked
+ statically to the C++ runtime ("s" tag). Default is platform dependent.
+
+``Boost_USE_DEBUG_RUNTIME``
+ Set to ``ON`` or ``OFF`` to specify whether to use libraries linked to the
+ MS debug C++ runtime ("g" tag). Default is ``ON``.
+
+``Boost_USE_DEBUG_PYTHON``
+ Set to ``ON`` to use libraries compiled with a debug Python build ("y"
+ tag). Default is ``OFF``.
+
+``Boost_USE_STLPORT``
+ Set to ``ON`` to use libraries compiled with STLPort ("p" tag). Default is
+ ``OFF``.
+
+``Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS``
+ Set to ON to use libraries compiled with STLPort deprecated "native
+ iostreams" ("n" tag). Default is ``OFF``.
+
+``Boost_COMPILER``
+ Set to the compiler-specific library suffix (e.g. ``-gcc43``). Default is
+ auto-computed for the C++ compiler in use.
+
+ .. versionchanged:: 3.9
+ A list may be used if multiple compatible suffixes should be tested for,
+ in decreasing order of preference.
+
+``Boost_LIB_PREFIX``
+ .. versionadded:: 3.18
+
+ Set to the platform-specific library name prefix (e.g. ``lib``) used by
+ Boost static libs. This is needed only on platforms where CMake does not
+ know the prefix by default.
+
+``Boost_ARCHITECTURE``
+ .. versionadded:: 3.13
+
+ Set to the architecture-specific library suffix (e.g. ``-x64``).
+ Default is auto-computed for the C++ compiler in use.
+
+``Boost_THREADAPI``
+ Suffix for ``thread`` component library name, such as ``pthread`` or
+ ``win32``. Names with and without this suffix will both be tried.
+
+``Boost_NAMESPACE``
+ Alternate namespace used to build boost with e.g. if set to ``myboost``,
+ will search for ``myboost_thread`` instead of ``boost_thread``.
+
+Other variables one may set to control this module are:
+
+``Boost_DEBUG``
+ Set to ``ON`` to enable debug output from ``FindBoost``.
+ Please enable this before filing any bug report.
+
+``Boost_REALPATH``
+ Set to ``ON`` to resolve symlinks for discovered libraries to assist with
+ packaging. For example, the "system" component library may be resolved to
+ ``/usr/lib/libboost_system.so.1.67.0`` instead of
+ ``/usr/lib/libboost_system.so``. This does not affect linking and should
+ not be enabled unless the user needs this information.
+
+``Boost_LIBRARY_DIR``
+ Default value for ``Boost_LIBRARY_DIR_RELEASE`` and
+ ``Boost_LIBRARY_DIR_DEBUG``.
+
+``Boost_NO_WARN_NEW_VERSIONS``
+ .. versionadded:: 3.20
+
+ Set to ``ON`` to suppress the warning about unknown dependencies for new
+ Boost versions.
On Visual Studio and Borland compilers Boost headers request automatic
linking to corresponding libraries. This requires matching libraries
to be linked explicitly or available in the link library search path.
In this case setting ``Boost_USE_STATIC_LIBS`` to ``OFF`` may not achieve
dynamic linking. Boost automatic linking typically requests static
-libraries with a few exceptions (such as ``Boost.Python``). Use::
+libraries with a few exceptions (such as ``Boost.Python``). Use:
+
+.. code-block:: cmake
add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
to ask Boost to report information about automatic linking requests.
-Example to find Boost headers only::
+Examples
+^^^^^^^^
+
+Find Boost headers only:
+
+.. code-block:: cmake
find_package(Boost 1.36.0)
if(Boost_FOUND)
@@ -202,7 +328,9 @@ Example to find Boost headers only::
add_executable(foo foo.cc)
endif()
-Example to find Boost libraries and use imported targets::
+Find Boost libraries and use imported targets:
+
+.. code-block:: cmake
find_package(Boost 1.56 REQUIRED COMPONENTS
date_time filesystem iostreams)
@@ -210,17 +338,21 @@ Example to find Boost libraries and use imported targets::
target_link_libraries(foo Boost::date_time Boost::filesystem
Boost::iostreams)
-Example to find Boost Python 3.6 libraries and use imported targets::
+Find Boost Python 3.6 libraries and use imported targets:
+
+.. code-block:: cmake
find_package(Boost 1.67 REQUIRED COMPONENTS
python36 numpy36)
add_executable(foo foo.cc)
target_link_libraries(foo Boost::python36 Boost::numpy36)
-Example to find Boost headers and some *static* (release only) libraries::
+Find Boost headers and some *static* (release only) libraries:
+
+.. code-block:: cmake
set(Boost_USE_STATIC_LIBS ON) # only find static libs
- set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and
+ set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and
set(Boost_USE_RELEASE_LIBS ON) # only find release libs
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
@@ -231,6 +363,8 @@ Example to find Boost headers and some *static* (release only) libraries::
target_link_libraries(foo ${Boost_LIBRARIES})
endif()
+.. _`Boost CMake`:
+
Boost CMake
^^^^^^^^^^^
@@ -238,7 +372,7 @@ If Boost was built using the boost-cmake project or from Boost 1.70.0 on
it provides a package configuration file for use with find_package's config mode.
This module looks for the package configuration file called
``BoostConfig.cmake`` or ``boost-config.cmake`` and stores the result in
-``CACHE`` entry "Boost_DIR". If found, the package configuration file is loaded
+``CACHE`` entry ``Boost_DIR``. If found, the package configuration file is loaded
and this module returns with no further action. See documentation of
the Boost CMake package configuration for details on what it provides.
@@ -725,7 +859,8 @@ endfunction()
# Guesses Boost's compiler prefix used in built library names
# Returns the guess by setting the variable pointed to by _ret
function(_Boost_GUESS_COMPILER_PREFIX _ret)
- if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel")
+ if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel"
+ OR "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "xIntelLLVM")
if(WIN32)
set (_boost_COMPILER "-iw")
else()
@@ -1215,7 +1350,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_TIMER_DEPENDENCIES chrono)
set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
- if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.76.0)
+ if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.76.0 AND NOT Boost_NO_WARN_NEW_VERSIONS)
message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
endif()
endif()
@@ -1778,7 +1913,8 @@ endif()
if(WIN32 AND Boost_USE_DEBUG_RUNTIME)
if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC"
OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang"
- OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel")
+ OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel"
+ OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntelLLVM")
string(APPEND _boost_DEBUG_ABI_TAG "g")
endif()
endif()
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index f04f57127..620e32af5 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -4,12 +4,6 @@ FindCUDA
.. deprecated:: 3.10
- Superseded by first-class support for the CUDA language in CMake.
- Superseded by the :module:`FindCUDAToolkit` for CUDA toolkit libraries.
-
-Replacement
-^^^^^^^^^^^
-
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
@@ -17,9 +11,10 @@ in the top-level call to the :command:`project` command, or call the
Then one can add CUDA (``.cu``) sources to programs directly
in calls to :command:`add_library` and :command:`add_executable`.
-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.
+.. 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.
Documentation of Deprecated Usage
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -30,6 +25,9 @@ This script locates the NVIDIA CUDA C tools. It should work on Linux,
Windows, and macOS and should be reasonably up to date with CUDA C
releases.
+.. versionadded:: 3.19
+ QNX support.
+
This script makes use of the standard :command:`find_package` arguments of
``<VERSION>``, ``REQUIRED`` and ``QUIET``. ``CUDA_FOUND`` will report if an
acceptable version of CUDA was found.
@@ -50,342 +48,476 @@ location. In newer versions of the toolkit the CUDA library is
included with the graphics driver -- be sure that the driver version
matches what is needed by the CUDA runtime version.
+Input Variables
+"""""""""""""""
+
The following variables affect the behavior of the macros in the
script (in alphabetical order). Note that any of these flags can be
changed multiple times in the same directory before calling
-``CUDA_ADD_EXECUTABLE``, ``CUDA_ADD_LIBRARY``, ``CUDA_COMPILE``,
-``CUDA_COMPILE_PTX``, ``CUDA_COMPILE_FATBIN``, ``CUDA_COMPILE_CUBIN``
-or ``CUDA_WRAP_SRCS``::
-
- CUDA_64_BIT_DEVICE_CODE (Default matches host bit size)
- -- Set to ON to compile for 64 bit device code, OFF for 32 bit device code.
- Note that making this different from the host code when generating object
- or C files from CUDA code just won't work, because size_t gets defined by
- nvcc in the generated source. If you compile to PTX and then load the
- file yourself, you can mix bit sizes between device and host.
-
- CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE (Default ON)
- -- Set to ON if you want the custom build rule to be attached to the source
- file in Visual Studio. Turn OFF if you add the same cuda file to multiple
- targets.
-
- This allows the user to build the target from the CUDA file; however, bad
- things can happen if the CUDA source file is added to multiple targets.
- When performing parallel builds it is possible for the custom build
- command to be run more than once and in parallel causing cryptic build
- errors. VS runs the rules for every source file in the target, and a
- source can have only one rule no matter how many projects it is added to.
- When the rule is run from multiple targets race conditions can occur on
- the generated file. Eventually everything will get built, but if the user
- is unaware of this behavior, there may be confusion. It would be nice if
- this script could detect the reuse of source files across multiple targets
- and turn the option off for the user, but no good solution could be found.
-
- CUDA_BUILD_CUBIN (Default OFF)
- -- Set to ON to enable and extra compilation pass with the -cubin option in
- Device mode. The output is parsed and register, shared memory usage is
- printed during build.
-
- CUDA_BUILD_EMULATION (Default OFF for device mode)
- -- Set to ON for Emulation mode. -D_DEVICEEMU is defined for CUDA C files
- when CUDA_BUILD_EMULATION is TRUE.
-
- CUDA_LINK_LIBRARIES_KEYWORD (Default "")
- -- The <PRIVATE|PUBLIC|INTERFACE> keyword to use for internal
- target_link_libraries calls. The default is to use no keyword which
- uses the old "plain" form of target_link_libraries. Note that is matters
- because whatever is used inside the FindCUDA module must also be used
- outside - the two forms of target_link_libraries cannot be mixed.
-
- CUDA_GENERATED_OUTPUT_DIR (Default CMAKE_CURRENT_BINARY_DIR)
- -- Set to the path you wish to have the generated files placed. If it is
- blank output files will be placed in CMAKE_CURRENT_BINARY_DIR.
- Intermediate files will always be placed in
- CMAKE_CURRENT_BINARY_DIR/CMakeFiles.
-
- CUDA_HOST_COMPILATION_CPP (Default ON)
- -- Set to OFF for C compilation of host code.
-
- CUDA_HOST_COMPILER (Default CMAKE_C_COMPILER)
- -- Set the host compiler to be used by nvcc. Ignored if -ccbin or
- --compiler-bindir is already present in the CUDA_NVCC_FLAGS or
- CUDA_NVCC_FLAGS_<CONFIG> variables. For Visual Studio targets,
- the host compiler is constructed with one or more visual studio macros
- such as $(VCInstallDir), that expands out to the path when
- the command is run from within VS.
- If the CUDAHOSTCXX environment variable is set it will
- be used as the default.
+``cuda_add_executable()``, ``cuda_add_library()``, ``cuda_compile()``,
+``cuda_compile_ptx()``, ``cuda_compile_fatbin()``, ``cuda_compile_cubin()``
+or ``cuda_wrap_srcs()``:
+
+``CUDA_64_BIT_DEVICE_CODE`` (Default: host bit size)
+ Set to ``ON`` to compile for 64 bit device code, OFF for 32 bit device code.
+ Note that making this different from the host code when generating object
+ or C files from CUDA code just won't work, because size_t gets defined by
+ nvcc in the generated source. If you compile to PTX and then load the
+ file yourself, you can mix bit sizes between device and host.
+
+``CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE`` (Default: ``ON``)
+ Set to ``ON`` if you want the custom build rule to be attached to the source
+ file in Visual Studio. Turn OFF if you add the same cuda file to multiple
+ targets.
+
+ This allows the user to build the target from the CUDA file; however, bad
+ things can happen if the CUDA source file is added to multiple targets.
+ When performing parallel builds it is possible for the custom build
+ command to be run more than once and in parallel causing cryptic build
+ errors. VS runs the rules for every source file in the target, and a
+ source can have only one rule no matter how many projects it is added to.
+ When the rule is run from multiple targets race conditions can occur on
+ the generated file. Eventually everything will get built, but if the user
+ is unaware of this behavior, there may be confusion. It would be nice if
+ this script could detect the reuse of source files across multiple targets
+ and turn the option off for the user, but no good solution could be found.
+
+``CUDA_BUILD_CUBIN`` (Default: ``OFF``)
+ Set to ``ON`` to enable and extra compilation pass with the ``-cubin`` option in
+ Device mode. The output is parsed and register, shared memory usage is
+ printed during build.
+
+``CUDA_BUILD_EMULATION`` (Default: ``OFF`` for device mode)
+ Set to ``ON`` for Emulation mode. ``-D_DEVICEEMU`` is defined for CUDA C files
+ when ``CUDA_BUILD_EMULATION`` is ``TRUE``.
+
+``CUDA_LINK_LIBRARIES_KEYWORD`` (Default: ``""``)
+ .. versionadded:: 3.9
+
+ The ``<PRIVATE|PUBLIC|INTERFACE>`` keyword to use for internal
+ :command:`target_link_libraries` calls. The default is to use no keyword which
+ uses the old "plain" form of :command:`target_link_libraries`. Note that is matters
+ because whatever is used inside the ``FindCUDA`` module must also be used
+ outside - the two forms of :command:`target_link_libraries` cannot be mixed.
+
+``CUDA_GENERATED_OUTPUT_DIR`` (Default: :variable:`CMAKE_CURRENT_BINARY_DIR`)
+ Set to the path you wish to have the generated files placed. If it is
+ blank output files will be placed in :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ Intermediate files will always be placed in
+ ``CMAKE_CURRENT_BINARY_DIR/CMakeFiles``.
+
+``CUDA_HOST_COMPILATION_CPP`` (Default: ``ON``)
+ Set to ``OFF`` for C compilation of host code.
+
+``CUDA_HOST_COMPILER`` (Default: ``CMAKE_C_COMPILER``)
+ Set the host compiler to be used by nvcc. Ignored if ``-ccbin`` or
+ ``--compiler-bindir`` is already present in the ``CUDA_NVCC_FLAGS`` or
+ ``CUDA_NVCC_FLAGS_<CONFIG>`` variables. For Visual Studio targets,
+ the host compiler is constructed with one or more visual studio macros
+ such as ``$(VCInstallDir)``, that expands out to the path when
+ the command is run from within VS.
+
+ .. versionadded:: 3.13
+ If the :envvar:`CUDAHOSTCXX` environment variable is set it will
+ be used as the default.
+
+``CUDA_NVCC_FLAGS``, ``CUDA_NVCC_FLAGS_<CONFIG>``
+ Additional NVCC command line arguments. NOTE: multiple arguments must be
+ semi-colon delimited (e.g. ``--compiler-options;-Wall``)
+
+ .. versionadded:: 3.6
+ Contents of these variables may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+``CUDA_PROPAGATE_HOST_FLAGS`` (Default: ``ON``)
+ Set to ``ON`` to propagate :variable:`CMAKE_{C,CXX}_FLAGS <CMAKE_<LANG>_FLAGS>` and their configuration
+ dependent counterparts (e.g. ``CMAKE_C_FLAGS_DEBUG``) automatically to the
+ host compiler through nvcc's ``-Xcompiler`` flag. This helps make the
+ generated host code match the rest of the system better. Sometimes
+ certain flags give nvcc problems, and this will help you turn the flag
+ propagation off. This does not affect the flags supplied directly to nvcc
+ via ``CUDA_NVCC_FLAGS`` or through the ``OPTION`` flags specified through
+ ``cuda_add_library()``, ``cuda_add_executable()``, or ``cuda_wrap_srcs()``. Flags used for
+ shared library compilation are not affected by this flag.
- CUDA_NVCC_FLAGS
- CUDA_NVCC_FLAGS_<CONFIG>
- -- Additional NVCC command line arguments. NOTE: multiple arguments must be
- semi-colon delimited (e.g. --compiler-options;-Wall)
-
- CUDA_PROPAGATE_HOST_FLAGS (Default ON)
- -- Set to ON to propagate CMAKE_{C,CXX}_FLAGS and their configuration
- dependent counterparts (e.g. CMAKE_C_FLAGS_DEBUG) automatically to the
- host compiler through nvcc's -Xcompiler flag. This helps make the
- generated host code match the rest of the system better. Sometimes
- certain flags give nvcc problems, and this will help you turn the flag
- propagation off. This does not affect the flags supplied directly to nvcc
- via CUDA_NVCC_FLAGS or through the OPTION flags specified through
- CUDA_ADD_LIBRARY, CUDA_ADD_EXECUTABLE, or CUDA_WRAP_SRCS. Flags used for
- shared library compilation are not affected by this flag.
-
- CUDA_SEPARABLE_COMPILATION (Default OFF)
- -- If set this will enable separable compilation for all CUDA runtime object
- files. If used outside of CUDA_ADD_EXECUTABLE and CUDA_ADD_LIBRARY
- (e.g. calling CUDA_WRAP_SRCS directly),
- CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME and
- CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS should be called.
-
- CUDA_SOURCE_PROPERTY_FORMAT
- -- If this source file property is set, it can override the format specified
- to CUDA_WRAP_SRCS (OBJ, PTX, CUBIN, or FATBIN). If an input source file
- is not a .cu file, setting this file will cause it to be treated as a .cu
- file. See documentation for set_source_files_properties on how to set
- this property.
-
- CUDA_USE_STATIC_CUDA_RUNTIME (Default ON)
- -- When enabled the static version of the CUDA runtime library will be used
- in CUDA_LIBRARIES. If the version of CUDA configured doesn't support
- this option, then it will be silently disabled.
-
- CUDA_VERBOSE_BUILD (Default OFF)
- -- Set to ON to see all the commands used when building the CUDA file. When
- using a Makefile generator the value defaults to VERBOSE (run make
- VERBOSE=1 to see output), although setting CUDA_VERBOSE_BUILD to ON will
- always print the output.
-
-The script creates the following macros (in alphabetical order)::
-
- CUDA_ADD_CUFFT_TO_TARGET( cuda_target )
- -- Adds the cufft library to the target (can be any target). Handles whether
- you are in emulation mode or not.
-
- CUDA_ADD_CUBLAS_TO_TARGET( cuda_target )
- -- Adds the cublas library to the target (can be any target). Handles
- whether you are in emulation mode or not.
-
- CUDA_ADD_EXECUTABLE( cuda_target file0 file1 ...
- [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [OPTIONS ...] )
- -- Creates an executable "cuda_target" which is made up of the files
- specified. All of the non CUDA C files are compiled using the standard
- build rules specified by CMAKE and the cuda files are compiled to object
- files using nvcc and the host compiler. In addition CUDA_INCLUDE_DIRS is
- added automatically to include_directories(). Some standard CMake target
- calls can be used on the target after calling this macro
- (e.g. set_target_properties and target_link_libraries), but setting
- properties that adjust compilation flags will not affect code compiled by
- nvcc. Such flags should be modified before calling CUDA_ADD_EXECUTABLE,
- CUDA_ADD_LIBRARY or CUDA_WRAP_SRCS.
-
- CUDA_ADD_LIBRARY( cuda_target file0 file1 ...
- [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [OPTIONS ...] )
- -- Same as CUDA_ADD_EXECUTABLE except that a library is created.
-
- CUDA_BUILD_CLEAN_TARGET()
- -- Creates a convenience target that deletes all the dependency files
- generated. You should make clean after running this target to ensure the
- dependency files get regenerated.
-
- CUDA_COMPILE( generated_files file0 file1 ... [STATIC | SHARED | MODULE]
- [OPTIONS ...] )
- -- Returns a list of generated files from the input source files to be used
- with ADD_LIBRARY or ADD_EXECUTABLE.
-
- CUDA_COMPILE_PTX( generated_files file0 file1 ... [OPTIONS ...] )
- -- Returns a list of PTX files generated from the input source files.
-
- CUDA_COMPILE_FATBIN( generated_files file0 file1 ... [OPTIONS ...] )
- -- Returns a list of FATBIN files generated from the input source files.
-
- CUDA_COMPILE_CUBIN( generated_files file0 file1 ... [OPTIONS ...] )
- -- Returns a list of CUBIN files generated from the input source files.
-
- CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME( output_file_var
- cuda_target
- object_files )
- -- Compute the name of the intermediate link file used for separable
- compilation. This file name is typically passed into
- CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS. output_file_var is produced
- based on cuda_target the list of objects files that need separable
- compilation as specified by object_files. If the object_files list is
- empty, then output_file_var will be empty. This function is called
- automatically for CUDA_ADD_LIBRARY and CUDA_ADD_EXECUTABLE. Note that
- this is a function and not a macro.
-
- CUDA_INCLUDE_DIRECTORIES( path0 path1 ... )
- -- Sets the directories that should be passed to nvcc
- (e.g. nvcc -Ipath0 -Ipath1 ... ). These paths usually contain other .cu
- files.
-
-
- CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS( output_file_var cuda_target
- nvcc_flags object_files)
- -- Generates the link object required by separable compilation from the given
- object files. This is called automatically for CUDA_ADD_EXECUTABLE and
- CUDA_ADD_LIBRARY, but can be called manually when using CUDA_WRAP_SRCS
- directly. When called from CUDA_ADD_LIBRARY or CUDA_ADD_EXECUTABLE the
- nvcc_flags passed in are the same as the flags passed in via the OPTIONS
- argument. The only nvcc flag added automatically is the bitness flag as
- specified by CUDA_64_BIT_DEVICE_CODE. Note that this is a function
- instead of a macro.
-
- CUDA_SELECT_NVCC_ARCH_FLAGS(out_variable [target_CUDA_architectures])
- -- Selects GPU arch flags for nvcc based on target_CUDA_architectures
- target_CUDA_architectures : Auto | Common | All | LIST(ARCH_AND_PTX ...)
- - "Auto" detects local machine GPU compute arch at runtime.
- - "Common" and "All" cover common and entire subsets of architectures
- ARCH_AND_PTX : NAME | NUM.NUM | NUM.NUM(NUM.NUM) | NUM.NUM+PTX
- NAME: Fermi Kepler Maxwell Kepler+Tegra Kepler+Tesla Maxwell+Tegra Pascal
- NUM: Any number. Only those pairs are currently accepted by NVCC though:
- 2.0 2.1 3.0 3.2 3.5 3.7 5.0 5.2 5.3 6.0 6.2
- Returns LIST of flags to be added to CUDA_NVCC_FLAGS in ${out_variable}
- Additionally, sets ${out_variable}_readable to the resulting numeric list
- Example:
- CUDA_SELECT_NVCC_ARCH_FLAGS(ARCH_FLAGS 3.0 3.5+PTX 5.2(5.0) Maxwell)
- LIST(APPEND CUDA_NVCC_FLAGS ${ARCH_FLAGS})
-
- More info on CUDA architectures: https://en.wikipedia.org/wiki/CUDA
- Note that this is a function instead of a macro.
-
- CUDA_WRAP_SRCS ( cuda_target format generated_files file0 file1 ...
- [STATIC | SHARED | MODULE] [OPTIONS ...] )
- -- This is where all the magic happens. CUDA_ADD_EXECUTABLE,
- CUDA_ADD_LIBRARY, CUDA_COMPILE, and CUDA_COMPILE_PTX all call this
- function under the hood.
-
- Given the list of files (file0 file1 ... fileN) this macro generates
- custom commands that generate either PTX or linkable objects (use "PTX" or
- "OBJ" for the format argument to switch). Files that don't end with .cu
- or have the HEADER_FILE_ONLY property are ignored.
-
- The arguments passed in after OPTIONS are extra command line options to
- give to nvcc. You can also specify per configuration options by
- specifying the name of the configuration followed by the options. General
- options must precede configuration specific options. Not all
- configurations need to be specified, only the ones provided will be used.
-
- OPTIONS -DFLAG=2 "-DFLAG_OTHER=space in flag"
- DEBUG -g
- RELEASE --use_fast_math
- RELWITHDEBINFO --use_fast_math;-g
- MINSIZEREL --use_fast_math
-
- For certain configurations (namely VS generating object files with
- CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE set to ON), no generated file will
- be produced for the given cuda file. This is because when you add the
- cuda file to Visual Studio it knows that this file produces an object file
- and will link in the resulting object file automatically.
-
- This script will also generate a separate cmake script that is used at
- build time to invoke nvcc. This is for several reasons.
-
- 1. nvcc can return negative numbers as return values which confuses
- Visual Studio into thinking that the command succeeded. The script now
- checks the error codes and produces errors when there was a problem.
-
- 2. nvcc has been known to not delete incomplete results when it
- encounters problems. This confuses build systems into thinking the
- target was generated when in fact an unusable file exists. The script
- now deletes the output files if there was an error.
-
- 3. By putting all the options that affect the build into a file and then
- make the build rule dependent on the file, the output files will be
- regenerated when the options change.
-
- This script also looks at optional arguments STATIC, SHARED, or MODULE to
- determine when to target the object compilation for a shared library.
- BUILD_SHARED_LIBS is ignored in CUDA_WRAP_SRCS, but it is respected in
- CUDA_ADD_LIBRARY. On some systems special flags are added for building
- objects intended for shared libraries. A preprocessor macro,
- <target_name>_EXPORTS is defined when a shared library compilation is
- detected.
-
- Flags passed into add_definitions with -D or /D are passed along to nvcc.
-
-
-
-The script defines the following variables::
-
- CUDA_VERSION_MAJOR -- The major version of cuda as reported by nvcc.
- CUDA_VERSION_MINOR -- The minor version.
- CUDA_VERSION
- CUDA_VERSION_STRING -- CUDA_VERSION_MAJOR.CUDA_VERSION_MINOR
- CUDA_HAS_FP16 -- Whether a short float (float16,fp16) is supported.
-
- CUDA_TOOLKIT_ROOT_DIR -- Path to the CUDA Toolkit (defined if not set).
- CUDA_SDK_ROOT_DIR -- Path to the CUDA SDK. Use this to find files in the
- SDK. This script will not directly support finding
- specific libraries or headers, as that isn't
- supported by NVIDIA. If you want to change
- libraries when the path changes see the
- FindCUDA.cmake script for an example of how to clear
- these variables. There are also examples of how to
- use the CUDA_SDK_ROOT_DIR to locate headers or
- libraries, if you so choose (at your own risk).
- CUDA_INCLUDE_DIRS -- Include directory for cuda headers. Added automatically
- for CUDA_ADD_EXECUTABLE and CUDA_ADD_LIBRARY.
- CUDA_LIBRARIES -- Cuda RT library.
- CUDA_CUFFT_LIBRARIES -- Device or emulation library for the Cuda FFT
- implementation (alternative to:
- CUDA_ADD_CUFFT_TO_TARGET macro)
- CUDA_CUBLAS_LIBRARIES -- Device or emulation library for the Cuda BLAS
- implementation (alternative to:
- CUDA_ADD_CUBLAS_TO_TARGET macro).
- CUDA_cudart_static_LIBRARY -- Statically linkable cuda runtime library.
- Only available for CUDA version 5.5+
- CUDA_cudadevrt_LIBRARY -- Device runtime library.
- Required for separable compilation.
- CUDA_cupti_LIBRARY -- CUDA Profiling Tools Interface library.
- Only available for CUDA version 4.0+.
- CUDA_curand_LIBRARY -- CUDA Random Number Generation library.
- Only available for CUDA version 3.2+.
- CUDA_cusolver_LIBRARY -- CUDA Direct Solver library.
- Only available for CUDA version 7.0+.
- CUDA_cusparse_LIBRARY -- CUDA Sparse Matrix library.
- Only available for CUDA version 3.2+.
- CUDA_npp_LIBRARY -- NVIDIA Performance Primitives lib.
- Only available for CUDA version 4.0+.
- CUDA_nppc_LIBRARY -- NVIDIA Performance Primitives lib (core).
- Only available for CUDA version 5.5+.
- CUDA_nppi_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 5.5 - 8.0.
- CUDA_nppial_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppicc_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppicom_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0 - 10.2.
- Replaced by nvjpeg.
- CUDA_nppidei_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppif_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppig_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppim_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppist_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppisu_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_nppitc_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
- Only available for CUDA version 9.0.
- CUDA_npps_LIBRARY -- NVIDIA Performance Primitives lib (signal processing).
- Only available for CUDA version 5.5+.
- CUDA_nvcuvenc_LIBRARY -- CUDA Video Encoder library.
- Only available for CUDA version 3.2+.
- Windows only.
- CUDA_nvcuvid_LIBRARY -- CUDA Video Decoder library.
- Only available for CUDA version 3.2+.
- Windows only.
- CUDA_nvToolsExt_LIBRARY
- -- NVIDA CUDA Tools Extension library.
- Available for CUDA version 5+.
- CUDA_OpenCL_LIBRARY -- NVIDA CUDA OpenCL library.
- Available for CUDA version 5+.
+``CUDA_SEPARABLE_COMPILATION`` (Default: ``OFF``)
+ If set this will enable separable compilation for all CUDA runtime object
+ files. If used outside of ``cuda_add_executable()`` and ``cuda_add_library()``
+ (e.g. calling ``cuda_wrap_srcs()`` directly),
+ ``cuda_compute_separable_compilation_object_file_name()`` and
+ ``cuda_link_separable_compilation_objects()`` should be called.
+
+``CUDA_SOURCE_PROPERTY_FORMAT``
+ .. versionadded:: 3.3
+
+ If this source file property is set, it can override the format specified
+ to ``cuda_wrap_srcs()`` (``OBJ``, ``PTX``, ``CUBIN``, or ``FATBIN``). If an input source file
+ is not a ``.cu`` file, setting this file will cause it to be treated as a ``.cu``
+ file. See documentation for set_source_files_properties on how to set
+ this property.
+
+``CUDA_USE_STATIC_CUDA_RUNTIME`` (Default: ``ON``)
+ .. versionadded:: 3.3
+
+ When enabled the static version of the CUDA runtime library will be used
+ in ``CUDA_LIBRARIES``. If the version of CUDA configured doesn't support
+ this option, then it will be silently disabled.
+
+``CUDA_VERBOSE_BUILD`` (Default: ``OFF``)
+ Set to ``ON`` to see all the commands used when building the CUDA file. When
+ using a Makefile generator the value defaults to ``VERBOSE`` (run
+ ``make VERBOSE=1`` to see output), although setting ``CUDA_VERBOSE_BUILD`` to ``ON`` will
+ always print the output.
+
+Commands
+""""""""
+
+The script creates the following functions and macros (in alphabetical order):
+
+.. code-block:: cmake
+
+ cuda_add_cufft_to_target(<cuda_target>)
+
+Adds the cufft library to the target (can be any target). Handles whether
+you are in emulation mode or not.
+
+.. code-block:: cmake
+
+ cuda_add_cublas_to_target(<cuda_target>)
+
+Adds the cublas library to the target (can be any target). Handles
+whether you are in emulation mode or not.
+
+.. code-block:: cmake
+
+ cuda_add_executable(<cuda_target> <file>...
+ [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [OPTIONS ...])
+
+Creates an executable ``<cuda_target>`` which is made up of the files
+specified. All of the non CUDA C files are compiled using the standard
+build rules specified by CMake and the CUDA files are compiled to object
+files using nvcc and the host compiler. In addition ``CUDA_INCLUDE_DIRS`` is
+added automatically to :command:`include_directories`. Some standard CMake target
+calls can be used on the target after calling this macro
+(e.g. :command:`set_target_properties` and :command:`target_link_libraries`), but setting
+properties that adjust compilation flags will not affect code compiled by
+nvcc. Such flags should be modified before calling ``cuda_add_executable()``,
+``cuda_add_library()`` or ``cuda_wrap_srcs()``.
+
+.. code-block:: cmake
+
+ cuda_add_library(<cuda_target> <file>...
+ [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [OPTIONS ...])
+
+Same as ``cuda_add_executable()`` except that a library is created.
+
+.. code-block:: cmake
+
+ cuda_build_clean_target()
+
+Creates a convenience target that deletes all the dependency files
+generated. You should make clean after running this target to ensure the
+dependency files get regenerated.
+
+.. code-block:: cmake
+
+ cuda_compile(<generated_files> <file>... [STATIC | SHARED | MODULE]
+ [OPTIONS ...])
+
+Returns a list of generated files from the input source files to be used
+with :command:`add_library` or :command:`add_executable`.
+
+.. code-block:: cmake
+
+ cuda_compile_ptx(<generated_files> <file>... [OPTIONS ...])
+
+Returns a list of ``PTX`` files generated from the input source files.
+
+.. code-block:: cmake
+
+ cuda_compile_fatbin(<generated_files> <file>... [OPTIONS ...])
+
+.. versionadded:: 3.1
+
+Returns a list of ``FATBIN`` files generated from the input source files.
+
+.. code-block:: cmake
+
+ cuda_compile_cubin(<generated_files> <file>... [OPTIONS ...])
+
+.. versionadded:: 3.1
+
+Returns a list of ``CUBIN`` files generated from the input source files.
+
+.. code-block:: cmake
+
+ cuda_compute_separable_compilation_object_file_name(<output_file_var>
+ <cuda_target>
+ <object_files>)
+
+Compute the name of the intermediate link file used for separable
+compilation. This file name is typically passed into
+``CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS``. output_file_var is produced
+based on cuda_target the list of objects files that need separable
+compilation as specified by ``<object_files>``. If the ``<object_files>`` list is
+empty, then ``<output_file_var>`` will be empty. This function is called
+automatically for ``cuda_add_library()`` and ``cuda_add_executable()``. Note that
+this is a function and not a macro.
+
+.. code-block:: cmake
+
+ cuda_include_directories(path0 path1 ...)
+
+Sets the directories that should be passed to nvcc
+(e.g. ``nvcc -Ipath0 -Ipath1 ...``). These paths usually contain other ``.cu``
+files.
+
+.. code-block:: cmake
+
+ cuda_link_separable_compilation_objects(<output_file_var> <cuda_target>
+ <nvcc_flags> <object_files>)
+
+Generates the link object required by separable compilation from the given
+object files. This is called automatically for ``cuda_add_executable()`` and
+``cuda_add_library()``, but can be called manually when using ``cuda_wrap_srcs()``
+directly. When called from ``cuda_add_library()`` or ``cuda_add_executable()`` the
+``<nvcc_flags>`` passed in are the same as the flags passed in via the ``OPTIONS``
+argument. The only nvcc flag added automatically is the bitness flag as
+specified by ``CUDA_64_BIT_DEVICE_CODE``. Note that this is a function
+instead of a macro.
+
+.. code-block:: cmake
+
+ cuda_select_nvcc_arch_flags(<out_variable> [<target_CUDA_architecture> ...])
+
+Selects GPU arch flags for nvcc based on ``target_CUDA_architecture``.
+
+Values for ``target_CUDA_architecture``:
+
+* ``Auto``: detects local machine GPU compute arch at runtime.
+* ``Common`` and ``All``: cover common and entire subsets of architectures.
+* ``<name>``: one of ``Fermi``, ``Kepler``, ``Maxwell``, ``Kepler+Tegra``, ``Kepler+Tesla``, ``Maxwell+Tegra``, ``Pascal``.
+* ``<ver>``, ``<ver>(<ver>)``, ``<ver>+PTX``, where ``<ver>`` is one of
+ ``2.0``, ``2.1``, ``3.0``, ``3.2``, ``3.5``, ``3.7``, ``5.0``, ``5.2``, ``5.3``, ``6.0``, ``6.2``.
+
+Returns list of flags to be added to ``CUDA_NVCC_FLAGS`` in ``<out_variable>``.
+Additionally, sets ``<out_variable>_readable`` to the resulting numeric list.
+
+Example::
+
+ cuda_select_nvcc_arch_flags(ARCH_FLAGS 3.0 3.5+PTX 5.2(5.0) Maxwell)
+ list(APPEND CUDA_NVCC_FLAGS ${ARCH_FLAGS})
+
+More info on CUDA architectures: https://en.wikipedia.org/wiki/CUDA.
+Note that this is a function instead of a macro.
+
+.. code-block:: cmake
+
+ cuda_wrap_srcs(<cuda_target> <format> <generated_files> <file>...
+ [STATIC | SHARED | MODULE] [OPTIONS ...])
+
+This is where all the magic happens. ``cuda_add_executable()``,
+``cuda_add_library()``, ``cuda_compile()``, and ``cuda_compile_ptx()`` all call this
+function under the hood.
+
+Given the list of files ``<file>...`` this macro generates
+custom commands that generate either PTX or linkable objects (use ``PTX`` or
+``OBJ`` for the ``<format>`` argument to switch). Files that don't end with ``.cu``
+or have the ``HEADER_FILE_ONLY`` property are ignored.
+
+The arguments passed in after ``OPTIONS`` are extra command line options to
+give to nvcc. You can also specify per configuration options by
+specifying the name of the configuration followed by the options. General
+options must precede configuration specific options. Not all
+configurations need to be specified, only the ones provided will be used.
+For example:
+
+.. code-block:: cmake
+
+ cuda_add_executable(...
+ OPTIONS -DFLAG=2 "-DFLAG_OTHER=space in flag"
+ DEBUG -g
+ RELEASE --use_fast_math
+ RELWITHDEBINFO --use_fast_math;-g
+ MINSIZEREL --use_fast_math)
+
+For certain configurations (namely VS generating object files with
+``CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE`` set to ``ON``), no generated file will
+be produced for the given cuda file. This is because when you add the
+cuda file to Visual Studio it knows that this file produces an object file
+and will link in the resulting object file automatically.
+
+This script will also generate a separate cmake script that is used at
+build time to invoke nvcc. This is for several reasons:
+
+* nvcc can return negative numbers as return values which confuses
+ Visual Studio into thinking that the command succeeded. The script now
+ checks the error codes and produces errors when there was a problem.
+
+* nvcc has been known to not delete incomplete results when it
+ encounters problems. This confuses build systems into thinking the
+ target was generated when in fact an unusable file exists. The script
+ now deletes the output files if there was an error.
+
+* By putting all the options that affect the build into a file and then
+ make the build rule dependent on the file, the output files will be
+ regenerated when the options change.
+
+This script also looks at optional arguments ``STATIC``, ``SHARED``, or ``MODULE`` to
+determine when to target the object compilation for a shared library.
+:variable:`BUILD_SHARED_LIBS` is ignored in ``cuda_wrap_srcs()``, but it is respected in
+``cuda_add_library()``. On some systems special flags are added for building
+objects intended for shared libraries. A preprocessor macro,
+``<target_name>_EXPORTS`` is defined when a shared library compilation is
+detected.
+
+Flags passed into add_definitions with ``-D`` or ``/D`` are passed along to nvcc.
+
+Result Variables
+""""""""""""""""
+
+The script defines the following variables:
+
+``CUDA_VERSION_MAJOR``
+ The major version of cuda as reported by nvcc.
+
+``CUDA_VERSION_MINOR``
+ The minor version.
+
+``CUDA_VERSION``, ``CUDA_VERSION_STRING``
+ Full version in the ``X.Y`` format.
+
+``CUDA_HAS_FP16``
+ .. versionadded:: 3.6
+ Whether a short float (``float16``, ``fp16``) is supported.
+
+``CUDA_TOOLKIT_ROOT_DIR``
+ Path to the CUDA Toolkit (defined if not set).
+
+``CUDA_SDK_ROOT_DIR``
+ Path to the CUDA SDK. Use this to find files in the SDK. This script will
+ not directly support finding specific libraries or headers, as that isn't
+ supported by NVIDIA. If you want to change libraries when the path changes
+ see the ``FindCUDA.cmake`` script for an example of how to clear these
+ variables. There are also examples of how to use the ``CUDA_SDK_ROOT_DIR``
+ to locate headers or libraries, if you so choose (at your own risk).
+
+``CUDA_INCLUDE_DIRS``
+ Include directory for cuda headers. Added automatically
+ for ``cuda_add_executable()`` and ``cuda_add_library()``.
+
+``CUDA_LIBRARIES``
+ Cuda RT library.
+
+``CUDA_CUFFT_LIBRARIES``
+ Device or emulation library for the Cuda FFT implementation (alternative to
+ ``cuda_add_cufft_to_target()`` macro)
+
+``CUDA_CUBLAS_LIBRARIES``
+ Device or emulation library for the Cuda BLAS implementation (alternative to
+ ``cuda_add_cublas_to_target()`` macro).
+
+``CUDA_cudart_static_LIBRARY``
+ Statically linkable cuda runtime library.
+ Only available for CUDA version 5.5+.
+
+``CUDA_cudadevrt_LIBRARY``
+ .. versionadded:: 3.7
+ Device runtime library. Required for separable compilation.
+
+``CUDA_cupti_LIBRARY``
+ CUDA Profiling Tools Interface library.
+ Only available for CUDA version 4.0+.
+
+``CUDA_curand_LIBRARY``
+ CUDA Random Number Generation library.
+ Only available for CUDA version 3.2+.
+
+``CUDA_cusolver_LIBRARY``
+ .. versionadded:: 3.2
+ CUDA Direct Solver library.
+ Only available for CUDA version 7.0+.
+
+``CUDA_cusparse_LIBRARY``
+ CUDA Sparse Matrix library.
+ Only available for CUDA version 3.2+.
+
+``CUDA_npp_LIBRARY``
+ NVIDIA Performance Primitives lib.
+ Only available for CUDA version 4.0+.
+
+``CUDA_nppc_LIBRARY``
+ NVIDIA Performance Primitives lib (core).
+ Only available for CUDA version 5.5+.
+
+``CUDA_nppi_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 5.5 - 8.0.
+
+``CUDA_nppial_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppicc_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppicom_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0 - 10.2.
+ Replaced by nvjpeg.
+
+``CUDA_nppidei_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppif_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppig_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppim_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppist_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppisu_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_nppitc_LIBRARY``
+ NVIDIA Performance Primitives lib (image processing).
+ Only available for CUDA version 9.0.
+
+``CUDA_npps_LIBRARY``
+ NVIDIA Performance Primitives lib (signal processing).
+ Only available for CUDA version 5.5+.
+
+``CUDA_nvcuvenc_LIBRARY``
+ CUDA Video Encoder library.
+ Only available for CUDA version 3.2+.
+ Windows only.
+
+``CUDA_nvcuvid_LIBRARY``
+ CUDA Video Decoder library.
+ Only available for CUDA version 3.2+.
+ Windows only.
+
+``CUDA_nvToolsExt_LIBRARY``
+ .. versionadded:: 3.16
+ NVIDA CUDA Tools Extension library.
+ Available for CUDA version 5+.
+
+``CUDA_OpenCL_LIBRARY``
+ .. versionadded:: 3.16
+ NVIDA CUDA OpenCL library.
+ Available for CUDA version 5+.
#]=======================================================================]
@@ -702,8 +834,19 @@ if(NOT CUDA_TOOLKIT_ROOT_DIR AND NOT CMAKE_CROSSCOMPILING)
)
if (CUDA_TOOLKIT_ROOT_DIR_NVCC)
- get_filename_component(CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR "${CUDA_TOOLKIT_ROOT_DIR_NVCC}" DIRECTORY)
- get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR}" DIRECTORY CACHE)
+ # Given that NVCC can be provided by multiple different sources (NVIDIA HPC SDK, CUDA Toolkit, distro)
+ # each of which has a different layout, we need to extract the CUDA toolkit root from the compiler
+ # itself, allowing us to support numerous different scattered toolkit layouts
+ execute_process(COMMAND ${CUDA_TOOLKIT_ROOT_DIR_NVCC} "-v" "__cmake_determine_cuda"
+ OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT)
+ if(_CUDA_NVCC_OUT MATCHES "TOP=([^\r\n]*)")
+ get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CMAKE_MATCH_1}" ABSOLUTE CACHE)
+ else()
+ get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CUDA_TOOLKIT_ROOT_DIR_NVCC}" DIRECTORY)
+ get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CUDA_TOOLKIT_ROOT_DIR}" DIRECTORY CACHE)
+ endif()
+ unset(_CUDA_NVCC_OUT)
+
string(REGEX REPLACE "[/\\\\]?bin[64]*[/\\\\]?$" "" CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR})
# We need to force this back into the cache.
set(CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR} CACHE PATH "Toolkit location." FORCE)
diff --git a/Modules/FindCUDA/select_compute_arch.cmake b/Modules/FindCUDA/select_compute_arch.cmake
index 93512882d..a35b3f8ff 100644
--- a/Modules/FindCUDA/select_compute_arch.cmake
+++ b/Modules/FindCUDA/select_compute_arch.cmake
@@ -25,44 +25,26 @@ if(CMAKE_CUDA_COMPILER_LOADED) # CUDA as a language
endif()
# See: https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list
+# Additions, deprecations, and removals can be found in the release notes:
+# https://developer.nvidia.com/cuda-toolkit-archive
-# This list will be used for CUDA_ARCH_NAME = All option
-set(CUDA_KNOWN_GPU_ARCHITECTURES "Fermi" "Kepler" "Maxwell")
+# The initial status here is for CUDA 7.0
+set(CUDA_KNOWN_GPU_ARCHITECTURES "Fermi" "Kepler" "Maxwell" "Kepler+Tegra" "Kepler+Tesla" "Maxwell+Tegra")
+set(CUDA_COMMON_GPU_ARCHITECTURES "2.0" "2.1" "3.0" "3.5" "5.0" "5.3")
+set(CUDA_LIMIT_GPU_ARCHITECTURE "6.0")
+set(CUDA_ALL_GPU_ARCHITECTURES "2.0" "2.1" "3.0" "3.2" "3.5" "3.7" "5.0" "5.2" "5.3")
+set(_CUDA_MAX_COMMON_ARCHITECTURE "5.2+PTX")
-# This list will be used for CUDA_ARCH_NAME = Common option (enabled by default)
-set(CUDA_COMMON_GPU_ARCHITECTURES "3.5" "5.0")
-# 3.0 is removed in CUDA 11, see:
-# https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#deprecated-features
-if(CUDA_VERSION VERSION_LESS "11.0")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "3.0")
-endif()
-
-if(CUDA_VERSION VERSION_LESS "7.0")
- set(CUDA_LIMIT_GPU_ARCHITECTURE "5.2")
-endif()
-
-# This list is used to filter CUDA archs when autodetecting
-set(CUDA_ALL_GPU_ARCHITECTURES "3.0" "3.2" "3.5" "5.0")
-
-if(CUDA_VERSION VERSION_GREATER_EQUAL "7.0")
- list(APPEND CUDA_KNOWN_GPU_ARCHITECTURES "Kepler+Tegra" "Kepler+Tesla" "Maxwell+Tegra")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "5.2")
-
- if(CUDA_VERSION VERSION_LESS "8.0")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "5.2+PTX")
- set(CUDA_LIMIT_GPU_ARCHITECTURE "6.0")
- endif()
-endif()
if(CUDA_VERSION VERSION_GREATER_EQUAL "8.0")
list(APPEND CUDA_KNOWN_GPU_ARCHITECTURES "Pascal")
list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "6.0" "6.1")
list(APPEND CUDA_ALL_GPU_ARCHITECTURES "6.0" "6.1" "6.2")
- if(CUDA_VERSION VERSION_LESS "9.0")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "6.2+PTX")
- set(CUDA_LIMIT_GPU_ARCHITECTURE "7.0")
- endif()
+ set(_CUDA_MAX_COMMON_ARCHITECTURE "6.2+PTX")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "7.0")
+
+ list(REMOVE_ITEM CUDA_COMMON_GPU_ARCHITECTURES "2.0" "2.1")
endif ()
if(CUDA_VERSION VERSION_GREATER_EQUAL "9.0")
@@ -70,10 +52,11 @@ if(CUDA_VERSION VERSION_GREATER_EQUAL "9.0")
list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "7.0")
list(APPEND CUDA_ALL_GPU_ARCHITECTURES "7.0" "7.2")
- if(CUDA_VERSION VERSION_LESS "10.0")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "7.2+PTX")
- set(CUDA_LIMIT_GPU_ARCHITECTURE "8.0")
- endif()
+ set(_CUDA_MAX_COMMON_ARCHITECTURE "7.2+PTX")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "8.0")
+
+ list(REMOVE_ITEM CUDA_KNOWN_GPU_ARCHITECTURES "Fermi")
+ list(REMOVE_ITEM CUDA_ALL_GPU_ARCHITECTURES "2.0" "2.1")
endif()
if(CUDA_VERSION VERSION_GREATER_EQUAL "10.0")
@@ -81,32 +64,46 @@ if(CUDA_VERSION VERSION_GREATER_EQUAL "10.0")
list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "7.5")
list(APPEND CUDA_ALL_GPU_ARCHITECTURES "7.5")
- if(CUDA_VERSION VERSION_LESS "11.0")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "7.5+PTX")
- set(CUDA_LIMIT_GPU_ARCHITECTURE "8.0")
- endif()
+ set(_CUDA_MAX_COMMON_ARCHITECTURE "7.5+PTX")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "8.0")
+
+ list(REMOVE_ITEM CUDA_COMMON_GPU_ARCHITECTURES "3.0")
endif()
+# https://docs.nvidia.com/cuda/archive/11.0/cuda-toolkit-release-notes/index.html#cuda-general-new-features
+# https://docs.nvidia.com/cuda/archive/11.0/cuda-toolkit-release-notes/index.html#deprecated-features
if(CUDA_VERSION VERSION_GREATER_EQUAL "11.0")
list(APPEND CUDA_KNOWN_GPU_ARCHITECTURES "Ampere")
list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "8.0")
list(APPEND CUDA_ALL_GPU_ARCHITECTURES "8.0")
- if(CUDA_VERSION VERSION_LESS "11.1")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "8.0+PTX")
- set(CUDA_LIMIT_GPU_ARCHITECTURE "8.6")
- endif()
+ set(_CUDA_MAX_COMMON_ARCHITECTURE "8.0+PTX")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "8.6")
+
+ list(REMOVE_ITEM CUDA_COMMON_GPU_ARCHITECTURES "3.5" "5.0")
+ list(REMOVE_ITEM CUDA_ALL_GPU_ARCHITECTURES "3.0" "3.2")
endif()
if(CUDA_VERSION VERSION_GREATER_EQUAL "11.1")
- list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "8.6" "8.6+PTX")
+ list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "8.6")
list(APPEND CUDA_ALL_GPU_ARCHITECTURES "8.6")
- if(CUDA_VERSION VERSION_LESS "12.0")
- set(CUDA_LIMIT_GPU_ARCHITECTURE "9.0")
- endif()
+ set(_CUDA_MAX_COMMON_ARCHITECTURE "8.6+PTX")
+ set(CUDA_LIMIT_GPU_ARCHITECTURE "9.0")
endif()
+list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "${_CUDA_MAX_COMMON_ARCHITECTURE}")
+
+# Check with: cmake -DCUDA_VERSION=7.0 -P select_compute_arch.cmake
+if(DEFINED CMAKE_SCRIPT_MODE_FILE)
+ include(CMakePrintHelpers)
+ cmake_print_variables(CUDA_KNOWN_GPU_ARCHITECTURES)
+ cmake_print_variables(CUDA_COMMON_GPU_ARCHITECTURES)
+ cmake_print_variables(CUDA_LIMIT_GPU_ARCHITECTURE)
+ cmake_print_variables(CUDA_ALL_GPU_ARCHITECTURES)
+endif()
+
+
################################################################################################
# A function for automatic detection of GPUs installed (if autodetection is enabled)
# Usage:
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index d4cd338d3..de2b06883 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -11,6 +11,9 @@ This script locates the NVIDIA CUDA toolkit and the associated libraries, but
does not require the ``CUDA`` language be enabled for a given project. This
module does not search for the NVIDIA CUDA Samples.
+.. versionadded:: 3.19
+ QNX support.
+
Search Behavior
^^^^^^^^^^^^^^^
@@ -426,6 +429,8 @@ Result variables
Runtime library ``cudart``.
``CUDAToolkit_LIBRARY_ROOT``
+ .. versionadded:: 3.18
+
The path to the CUDA Toolkit directory containing the nvvm directory and
version.txt.
@@ -513,12 +518,24 @@ else()
)
endif()
- if(CUDAToolkit_NVCC_EXECUTABLE)
- get_filename_component(CUDAToolkit_BIN_DIR "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY)
+ if(EXISTS "${CUDAToolkit_NVCC_EXECUTABLE}")
+ # If NVCC exists then invoke it to find the toolkit location.
+ # This allows us to support wrapper scripts (e.g. ccache or colornvcc), CUDA Toolkit,
+ # NVIDIA HPC SDK, and distro's splayed layouts
+ execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda"
+ OUTPUT_VARIABLE _CUDA_NVCC_OUT ERROR_VARIABLE _CUDA_NVCC_OUT)
+ if(_CUDA_NVCC_OUT MATCHES "TOP=([^\r\n]*)")
+ get_filename_component(CUDAToolkit_BIN_DIR "${CMAKE_MATCH_1}/bin" ABSOLUTE)
+ else()
+ get_filename_component(CUDAToolkit_BIN_DIR "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY)
+ endif()
+ unset(_CUDA_NVCC_OUT)
- set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "" FORCE)
mark_as_advanced(CUDAToolkit_BIN_DIR)
- elseif(CUDAToolkit_SENTINEL_FILE)
+ set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "" FORCE)
+ endif()
+
+ if(CUDAToolkit_SENTINEL_FILE)
get_filename_component(CUDAToolkit_BIN_DIR ${CUDAToolkit_SENTINEL_FILE} DIRECTORY ABSOLUTE)
set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}/bin")
@@ -721,6 +738,7 @@ elseif(NOT CUDAToolkit_FIND_QUIETLY)
endif()
if(CUDAToolkit_NVCC_EXECUTABLE AND
+ CMAKE_CUDA_COMPILER_VERSION AND
CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER)
# Need to set these based off the already computed CMAKE_CUDA_COMPILER_VERSION value
# This if statement will always match, but is used to provide variables for MATCH 1,2,3...
diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake
index 74b36c6f7..e37d22591 100644
--- a/Modules/FindCURL.cmake
+++ b/Modules/FindCURL.cmake
@@ -7,8 +7,11 @@ FindCURL
Find the native CURL headers and libraries.
-This module accept optional COMPONENTS to check supported features and
-protocols::
+.. versionadded:: 3.14
+ This module accept optional COMPONENTS to check supported features and
+ protocols:
+
+::
PROTOCOLS: ICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3
POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP
@@ -18,6 +21,8 @@ protocols::
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.12
+
This module defines :prop_tgt:`IMPORTED` target ``CURL::libcurl``, if
curl has been found.
@@ -38,9 +43,14 @@ This module defines the following variables:
``CURL_VERSION_STRING``
The version of ``curl`` found.
+.. versionadded:: 3.13
+ Debug and Release variants are found separately.
+
CURL CMake
^^^^^^^^^^
+.. versionadded:: 3.17
+
If CURL was built using the CMake buildsystem then it provides its own
``CURLConfig.cmake`` file for use with the :command:`find_package` command's
config mode. This module looks for this file and, if found,
diff --git a/Modules/FindCups.cmake b/Modules/FindCups.cmake
index 4e8232d07..cf0d3416a 100644
--- a/Modules/FindCups.cmake
+++ b/Modules/FindCups.cmake
@@ -13,6 +13,8 @@ features this function (i.e. at least ``1.1.19``)
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.15
+
This module defines :prop_tgt:`IMPORTED` target ``Cups::Cups``, if Cups has
been found.
diff --git a/Modules/FindCurses.cmake b/Modules/FindCurses.cmake
index cde3a4d2d..5e25deb68 100644
--- a/Modules/FindCurses.cmake
+++ b/Modules/FindCurses.cmake
@@ -19,6 +19,8 @@ This module defines the following variables:
``CURSES_LIBRARIES``
The libraries needed to use Curses.
``CURSES_CFLAGS``
+ .. versionadded:: 3.16
+
Parameters which ought be given to C/C++ compilers when using Curses.
``CURSES_HAVE_CURSES_H``
True if curses.h is available.
@@ -31,8 +33,10 @@ This module defines the following variables:
Set ``CURSES_NEED_NCURSES`` to ``TRUE`` before the
``find_package(Curses)`` call if NCurses functionality is required.
-Set ``CURSES_NEED_WIDE`` to ``TRUE`` before the
-``find_package(Curses)`` call if unicode functionality is required.
+
+.. versionadded:: 3.10
+ Set ``CURSES_NEED_WIDE`` to ``TRUE`` before the
+ ``find_package(Curses)`` call if unicode functionality is required.
Backward Compatibility
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake
index 81fbbb758..bbf941efb 100644
--- a/Modules/FindDoxygen.cmake
+++ b/Modules/FindDoxygen.cmake
@@ -6,8 +6,7 @@ FindDoxygen
-----------
Doxygen is a documentation generation tool (see http://www.doxygen.org).
-This module looks for Doxygen and some optional tools it supports. These
-tools are enabled as components in the :command:`find_package` command:
+This module looks for Doxygen and some optional tools it supports:
``dot``
`Graphviz <http://graphviz.org>`_ ``dot`` utility used to render various
@@ -19,7 +18,9 @@ tools are enabled as components in the :command:`find_package` command:
`Dia <https://wiki.gnome.org/Apps/Dia>`_ the diagram editor used by Doxygen's
``\diafile`` command.
-Examples:
+.. versionadded:: 3.9
+ These tools are available as components in the :command:`find_package` command.
+ For example:
.. code-block:: cmake
@@ -38,12 +39,13 @@ The following variables are defined by this module:
The version reported by ``doxygen --version``.
-The module defines ``IMPORTED`` targets for Doxygen and each component found.
-These can be used as part of custom commands, etc. and should be preferred over
-old-style (and now deprecated) variables like ``DOXYGEN_EXECUTABLE``. The
-following import targets are defined if their corresponding executable could be
-found (the component import targets will only be defined if that component was
-requested):
+.. versionadded:: 3.9
+ The module defines ``IMPORTED`` targets for Doxygen and each component found.
+ These can be used as part of custom commands, etc. and should be preferred over
+ old-style (and now deprecated) variables like ``DOXYGEN_EXECUTABLE``. The
+ following import targets are defined if their corresponding executable could be
+ found (the component import targets will only be defined if that component was
+ requested):
::
@@ -58,6 +60,8 @@ Functions
.. command:: doxygen_add_docs
+ .. versionadded:: 3.9
+
This function is intended as a convenience for adding a target for generating
documentation with Doxygen. It aims to provide sensible defaults so that
projects can generally just provide the input files and directories and that
@@ -93,19 +97,21 @@ Functions
the :command:`add_custom_target` command used to create the custom target
internally.
- If ``ALL`` is set, the target will be added to the default build target.
-
- If ``USE_STAMP_FILE`` is set, the custom command defined by this function will
- create a stamp file with the name ``<targetName>.stamp`` in the current
- binary directory whenever doxygen is re-run. With this option present, all
- items in ``<filesOrDirs>`` must be files (i.e. no directories, symlinks or
- wildcards) and each of the files must exist at the time
- ``doxygen_add_docs()`` is called. An error will be raised if any of the
- items listed is missing or is not a file when ``USE_STAMP_FILE`` is given.
- A dependency will be created on each of the files so that doxygen will only
- be re-run if one of the files is updated. Without the ``USE_STAMP_FILE``
- option, doxygen will always be re-run if the ``<targetName>`` target is built
- regardless of whether anything listed in ``<filesOrDirs>`` has changed.
+ .. versionadded:: 3.12
+ If ``ALL`` is set, the target will be added to the default build target.
+
+ .. versionadded:: 3.16
+ If ``USE_STAMP_FILE`` is set, the custom command defined by this function will
+ create a stamp file with the name ``<targetName>.stamp`` in the current
+ binary directory whenever doxygen is re-run. With this option present, all
+ items in ``<filesOrDirs>`` must be files (i.e. no directories, symlinks or
+ wildcards) and each of the files must exist at the time
+ ``doxygen_add_docs()`` is called. An error will be raised if any of the
+ items listed is missing or is not a file when ``USE_STAMP_FILE`` is given.
+ A dependency will be created on each of the files so that doxygen will only
+ be re-run if one of the files is updated. Without the ``USE_STAMP_FILE``
+ option, doxygen will always be re-run if the ``<targetName>`` target is built
+ regardless of whether anything listed in ``<filesOrDirs>`` has changed.
The contents of the generated ``Doxyfile`` can be customized by setting CMake
variables before calling ``doxygen_add_docs()``. Any variable with a name of
@@ -308,18 +314,19 @@ if they contain at least one space:
WARN_LOGFILE
XML_OUTPUT
-There are situations where it may be undesirable for a particular config option
-to be automatically quoted by ``doxygen_add_docs()``, such as ``ALIASES`` which
-may need to include its own embedded quoting. The ``DOXYGEN_VERBATIM_VARS``
-variable can be used to specify a list of Doxygen variables (including the
-leading ``DOXYGEN_`` prefix) which should not be quoted. The project is then
-responsible for ensuring that those variables' values make sense when placed
-directly in the Doxygen input file. In the case of list variables, list items
-are still separated by spaces, it is only the automatic quoting that is
-skipped. For example, the following allows ``doxygen_add_docs()`` to apply
-quoting to ``DOXYGEN_PROJECT_BRIEF``, but not each item in the
-``DOXYGEN_ALIASES`` list (:ref:`bracket syntax <Bracket Argument>` can also
-be used to make working with embedded quotes easier):
+.. versionadded:: 3.11
+ There are situations where it may be undesirable for a particular config option
+ to be automatically quoted by ``doxygen_add_docs()``, such as ``ALIASES`` which
+ may need to include its own embedded quoting. The ``DOXYGEN_VERBATIM_VARS``
+ variable can be used to specify a list of Doxygen variables (including the
+ leading ``DOXYGEN_`` prefix) which should not be quoted. The project is then
+ responsible for ensuring that those variables' values make sense when placed
+ directly in the Doxygen input file. In the case of list variables, list items
+ are still separated by spaces, it is only the automatic quoting that is
+ skipped. For example, the following allows ``doxygen_add_docs()`` to apply
+ quoting to ``DOXYGEN_PROJECT_BRIEF``, but not each item in the
+ ``DOXYGEN_ALIASES`` list (:ref:`bracket syntax <Bracket Argument>` can also
+ be used to make working with embedded quotes easier):
.. code-block:: cmake
@@ -341,6 +348,8 @@ The resultant ``Doxyfile`` will contain the following lines:
Deprecated Result Variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. deprecated:: 3.9
+
For compatibility with previous versions of CMake, the following variables
are also defined but they are deprecated and should no longer be used:
@@ -375,6 +384,8 @@ are also defined but they are deprecated and should no longer be used:
Deprecated Hint Variables
^^^^^^^^^^^^^^^^^^^^^^^^^
+.. deprecated:: 3.9
+
.. variable:: DOXYGEN_SKIP_DOT
This variable has no effect for the component form of ``find_package``.
diff --git a/Modules/FindEXPAT.cmake b/Modules/FindEXPAT.cmake
index b0bb02a56..f9cb43207 100644
--- a/Modules/FindEXPAT.cmake
+++ b/Modules/FindEXPAT.cmake
@@ -11,6 +11,8 @@ Expat is a stream-oriented XML parser library written in C.
Imported Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.10
+
This module defines the following :prop_tgt:`IMPORTED` targets:
``EXPAT::EXPAT``
diff --git a/Modules/FindFLEX.cmake b/Modules/FindFLEX.cmake
index 13847367d..e67e93112 100644
--- a/Modules/FindFLEX.cmake
+++ b/Modules/FindFLEX.cmake
@@ -37,11 +37,20 @@ If flex is found on the system, the module provides the macro:
)
which creates a custom command to generate the ``FlexOutput`` file from
-the ``FlexInput`` file. If ``COMPILE_FLAGS`` option is specified, the next
-parameter is added to the flex command line. If flex is configured to
-output a header file, the ``DEFINES_FILE`` option may be used to specify its
-name. Name is an alias used to get details of this custom command.
-Indeed the macro defines the following variables:
+the ``FlexInput`` file. Name is an alias used to get details of this custom
+command. If ``COMPILE_FLAGS`` option is specified, the next
+parameter is added to the flex command line.
+
+.. versionadded:: 3.5
+ If flex is configured to
+ output a header file, the ``DEFINES_FILE`` option may be used to specify its
+ name.
+
+.. versionchanged:: 3.17
+ When :policy:`CMP0098` is set to ``NEW``, ``flex`` runs in the
+ :variable:`CMAKE_CURRENT_BINARY_DIR` directory.
+
+The macro defines the following variables:
::
diff --git a/Modules/FindFLTK.cmake b/Modules/FindFLTK.cmake
index e273642b5..e1e239a66 100644
--- a/Modules/FindFLTK.cmake
+++ b/Modules/FindFLTK.cmake
@@ -77,6 +77,10 @@ The following cache variables are also available to set or use:
``FLTK_IMAGES_LIBRARY_DEBUG``
The FLTK Images library (debug)
+
+.. versionadded:: 3.11
+ Debug and Release variants are found separately and use per-configuration
+ variables.
#]=======================================================================]
if(NOT FLTK_SKIP_OPENGL)
diff --git a/Modules/FindFreetype.cmake b/Modules/FindFreetype.cmake
index 3e6a177dc..82885cb2f 100644
--- a/Modules/FindFreetype.cmake
+++ b/Modules/FindFreetype.cmake
@@ -10,6 +10,8 @@ Find the FreeType font renderer includes and library.
Imported Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.10
+
This module defines the following :prop_tgt:`IMPORTED` target:
``Freetype::Freetype``
@@ -33,7 +35,10 @@ This module will set the following variables in your project:
``FREETYPE_LIBRARIES``
the library to link against
``FREETYPE_VERSION_STRING``
- the version of freetype found (since CMake 2.8.8)
+ the version of freetype found
+
+.. versionadded:: 3.7
+ Debug and Release variants are found separately.
Hints
^^^^^
diff --git a/Modules/FindGDAL.cmake b/Modules/FindGDAL.cmake
index fde84d488..5237e1513 100644
--- a/Modules/FindGDAL.cmake
+++ b/Modules/FindGDAL.cmake
@@ -10,6 +10,8 @@ Find Geospatial Data Abstraction Library (GDAL).
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.14
+
This module defines :prop_tgt:`IMPORTED` target ``GDAL::GDAL``
if GDAL has been found.
@@ -25,7 +27,8 @@ This module will set the following variables in your project:
``GDAL_LIBRARIES``
Libraries to link to GDAL.
``GDAL_VERSION``
- The version of GDAL found.
+ .. versionadded:: 3.14
+ The version of GDAL found.
Cache variables
^^^^^^^^^^^^^^^
@@ -42,6 +45,15 @@ Hints
Set ``GDAL_DIR`` or ``GDAL_ROOT`` in the environment to specify the
GDAL installation prefix.
+
+The following variables may be set to modify the search strategy:
+
+``FindGDAL_SKIP_GDAL_CONFIG``
+ If set, ``gdal-config`` will not be used. This can be useful if there are
+ GDAL libraries built with autotools (which provide the tool) and CMake (which
+ do not) in the same environment.
+``GDAL_ADDITIONAL_LIBRARY_VERSIONS``
+ Extra versions of library names to search for.
#]=======================================================================]
# $GDALDIR is an environment variable that would
@@ -65,12 +77,14 @@ find_path(GDAL_INCLUDE_DIR gdal.h
ENV GDAL_DIR
ENV GDAL_ROOT
PATH_SUFFIXES
- include/gdal
- include/GDAL
- include
+ include/gdal
+ include/GDAL
+ include
+ DOC "Path to the GDAL include directory"
)
+mark_as_advanced(GDAL_INCLUDE_DIR)
-if(UNIX)
+if(UNIX AND NOT FindGDAL_SKIP_GDAL_CONFIG)
# Use gdal-config to obtain the library version (this should hopefully
# allow us to -lgdal1.x.y where x.y are correct version)
# For some reason, libgdal development packages do not contain
@@ -80,10 +94,12 @@ if(UNIX)
ENV GDAL_DIR
ENV GDAL_ROOT
PATH_SUFFIXES bin
+ DOC "Path to the gdal-config tool"
)
+ mark_as_advanced(GDAL_CONFIG)
if(GDAL_CONFIG)
- exec_program(${GDAL_CONFIG} ARGS --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS)
+ execute_process(COMMAND ${GDAL_CONFIG} --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS)
if(GDAL_CONFIG_LIBS)
# treat the output as a command line and split it up
@@ -131,14 +147,30 @@ if(UNIX)
endif()
endif()
+# GDAL name its library when built with CMake as `gdal${major}${minor}`.
+set(_gdal_versions
+ ${GDAL_ADDITIONAL_LIBRARY_VERSIONS} 3.0 2.4 2.3 2.2 2.1 2.0 1.11 1.10 1.9 1.8 1.7 1.6 1.5 1.4 1.3 1.2)
+
+set(_gdal_libnames)
+foreach (_gdal_version IN LISTS _gdal_versions)
+ string(REPLACE "." "" _gdal_version "${_gdal_version}")
+ list(APPEND _gdal_libnames "gdal${_gdal_version}" "GDAL${_gdal_version}")
+endforeach ()
+unset(_gdal_version)
+unset(_gdal_versions)
+
find_library(GDAL_LIBRARY
- NAMES ${_gdal_lib} gdal gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL
+ NAMES ${_gdal_lib} ${_gdal_libnames} gdal gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL
HINTS
ENV GDAL_DIR
ENV GDAL_ROOT
${_gdal_libpath}
PATH_SUFFIXES lib
+ DOC "Path to the GDAL library"
)
+mark_as_advanced(GDAL_LIBRARY)
+unset(_gdal_libnames)
+unset(_gdal_lib)
if (EXISTS "${GDAL_INCLUDE_DIR}/gdal_version.h")
file(STRINGS "${GDAL_INCLUDE_DIR}/gdal_version.h" _gdal_version
@@ -154,12 +186,14 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GDAL
VERSION_VAR GDAL_VERSION
REQUIRED_VARS GDAL_LIBRARY GDAL_INCLUDE_DIR)
-if (GDAL_FOUND AND NOT TARGET GDAL::GDAL)
- add_library(GDAL::GDAL UNKNOWN IMPORTED)
- set_target_properties(GDAL::GDAL PROPERTIES
- IMPORTED_LOCATION "${GDAL_LIBRARY}"
- INTERFACE_INCLUDE_DIRECTORIES "${GDAL_INCLUDE_DIR}")
-endif ()
+if (GDAL_FOUND)
+ set(GDAL_LIBRARIES ${GDAL_LIBRARY})
+ set(GDAL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR})
-set(GDAL_LIBRARIES ${GDAL_LIBRARY})
-set(GDAL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR})
+ if (NOT TARGET GDAL::GDAL)
+ add_library(GDAL::GDAL UNKNOWN IMPORTED)
+ set_target_properties(GDAL::GDAL PROPERTIES
+ IMPORTED_LOCATION "${GDAL_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${GDAL_INCLUDE_DIR}")
+ endif ()
+endif ()
diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake
index 187b6a8d2..b9ebe08bd 100644
--- a/Modules/FindGLEW.cmake
+++ b/Modules/FindGLEW.cmake
@@ -21,6 +21,8 @@ The following variables may be set to influence this module's behavior:
Imported Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.1
+
This module defines the following :ref:`Imported Targets <Imported Targets>`:
@@ -55,6 +57,9 @@ This module defines the following variables:
``GLEW_VERSION_MICRO``
GLEW micro version
+.. versionadded:: 3.7
+ Debug and Release variants are found separately.
+
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake
index 15561d6b0..2770c604d 100644
--- a/Modules/FindGLUT.cmake
+++ b/Modules/FindGLUT.cmake
@@ -10,6 +10,8 @@ Find OpenGL Utility Toolkit (GLUT) library and include files.
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.1
+
This module defines the :prop_tgt:`IMPORTED` targets:
``GLUT::GLUT``
@@ -33,6 +35,9 @@ Also defined, but not for general use are:
GLUT_glut_LIBRARY = the full path to the glut library.
GLUT_Xmu_LIBRARY = the full path to the Xmu library.
GLUT_Xi_LIBRARY = the full path to the Xi Library.
+
+.. versionadded:: 3.13
+ Debug and Release variants are found separately.
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake
index 62f1614f8..00bfc29c8 100644
--- a/Modules/FindGTK2.cmake
+++ b/Modules/FindGTK2.cmake
@@ -16,6 +16,23 @@ module. See example below.
* ``glade``
* ``glademm``
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :prop_tgt:`IMPORTED` targets (subject to
+component selection):
+
+``GTK2::atk``, ``GTK2::atkmm``, ``GTK2::cairo``, ``GTK2::cairomm``,
+``GTK2::gdk_pixbuf``, ``GTK2::gdk``, ``GTK2::gdkmm``, ``GTK2::gio``,
+``GTK2::giomm``, ``GTK2::glade``, ``GTK2::glademm``, ``GTK2::glib``,
+``GTK2::glibmm``, ``GTK2::gmodule``, ``GTK2::gobject``, ``GTK2::gthread``,
+``GTK2::gtk``, ``GTK2::gtkmm``, ``GTK2::harfbuzz``, ``GTK2::pango``,
+``GTK2::pangocairo``, ``GTK2::pangoft2``, ``GTK2::pangomm``,
+``GTK2::pangoxft``, ``GTK2::sigc``.
+
+.. versionadded:: 3.16.7
+ Added the ``GTK2::harfbuzz`` target.
+
Result Variables
^^^^^^^^^^^^^^^^
@@ -28,7 +45,8 @@ The following variables will be defined for your use
``GTK2_LIBRARIES``
All libraries
``GTK2_TARGETS``
- All imported targets
+ .. versionadded:: 3.5
+ All imported targets
``GTK2_DEFINITIONS``
Additional compiler flags
``GTK2_VERSION``
@@ -40,6 +58,10 @@ The following variables will be defined for your use
``GTK2_PATCH_VERSION``
The patch version of GTK2
+.. versionadded:: 3.5
+ When ``GTK2_USE_IMPORTED_TARGETS`` is set to ``TRUE``, ``GTK2_LIBRARIES``
+ will list imported targets instead of library paths.
+
Input Variables
^^^^^^^^^^^^^^^
@@ -783,6 +805,7 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
_GTK2_ADD_TARGET (GIOMM GTK2_DEPENDS gio glibmm gobject sigc++ glib)
_GTK2_FIND_INCLUDE_DIR(ATKMM atkmm.h)
+ _GTK2_FIND_INCLUDE_DIR(ATKMMCONFIG atkmmconfig.h)
_GTK2_FIND_LIBRARY (ATKMM atkmm true true)
_GTK2_ADD_TARGET (ATKMM GTK2_DEPENDS atk glibmm gobject sigc++ glib)
diff --git a/Modules/FindGTest.cmake b/Modules/FindGTest.cmake
index 53cab1a76..8e22f7919 100644
--- a/Modules/FindGTest.cmake
+++ b/Modules/FindGTest.cmake
@@ -7,10 +7,24 @@ FindGTest
Locate the Google C++ Testing Framework.
+.. versionadded:: 3.20
+ Upstream ``GTestConfig.cmake`` is used if possible.
+
Imported targets
^^^^^^^^^^^^^^^^
-This module defines the following :prop_tgt:`IMPORTED` targets:
+.. versionadded:: 3.20
+ This module defines the following :prop_tgt:`IMPORTED` targets:
+
+``GTest::gtest``
+ The Google Test ``gtest`` library, if found; adds Thread::Thread
+ automatically
+``GTest::gtest_main``
+ The Google Test ``gtest_main`` library, if found
+
+.. deprecated:: 3.20
+ For backwards compatibility, this module defines additionally the
+ following deprecated :prop_tgt:`IMPORTED` targets (available since 3.5):
``GTest::GTest``
The Google Test ``gtest`` library, if found; adds Thread::Thread
@@ -24,7 +38,7 @@ Result variables
This module will set the following variables in your project:
-``GTEST_FOUND``
+``GTest_FOUND``
Found the Google Testing framework
``GTEST_INCLUDE_DIRS``
the directory containing the Google Test headers
@@ -62,7 +76,7 @@ Example usage
find_package(GTest REQUIRED)
add_executable(foo foo.cc)
- target_link_libraries(foo GTest::GTest GTest::Main)
+ target_link_libraries(foo GTest::gtest GTest::gtest_main)
add_test(AllTestsInFoo foo)
@@ -72,6 +86,10 @@ Deeper integration with CTest
See :module:`GoogleTest` for information on the :command:`gtest_add_tests`
and :command:`gtest_discover_tests` commands.
+
+.. versionchanged:: 3.9
+ Previous CMake versions defined :command:`gtest_add_tests` macro in this
+ module.
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/GoogleTest.cmake)
@@ -146,8 +164,41 @@ function(__gtest_import_library _target _var _config)
endif()
endfunction()
+function(__gtest_define_backwards_compatible_library_targets)
+ set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} PARENT_SCOPE)
+
+ # Add targets mapping the same library names as defined in
+ # older versions of CMake's FindGTest
+ if(NOT TARGET GTest::GTest)
+ add_library(GTest::GTest INTERFACE IMPORTED)
+ target_link_libraries(GTest::GTest INTERFACE GTest::gtest)
+ endif()
+ if(NOT TARGET GTest::Main)
+ add_library(GTest::Main INTERFACE IMPORTED)
+ target_link_libraries(GTest::Main INTERFACE GTest::gtest_main)
+ endif()
+endfunction()
+
#
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+
+# first specifically look for the CMake version of GTest
+find_package(GTest QUIET NO_MODULE)
+
+# if we found the GTest cmake package then we are done, and
+# can print what we found and return.
+if(GTest_FOUND)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTest HANDLE_COMPONENTS CONFIG_MODE)
+
+ set(GTEST_LIBRARIES GTest::gtest)
+ set(GTEST_MAIN_LIBRARIES GTest::gtest_main)
+
+ __gtest_define_backwards_compatible_library_targets()
+
+ return()
+endif()
+
if(NOT DEFINED GTEST_MSVC_SEARCH)
set(GTEST_MSVC_SEARCH MD)
endif()
@@ -201,54 +252,43 @@ else()
__gtest_find_library(GTEST_MAIN_LIBRARY_DEBUG gtest_maind)
endif()
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTest DEFAULT_MSG GTEST_LIBRARY GTEST_INCLUDE_DIR GTEST_MAIN_LIBRARY)
-if(GTEST_FOUND)
+if(GTest_FOUND)
set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIR})
__gtest_append_debugs(GTEST_LIBRARIES GTEST_LIBRARY)
__gtest_append_debugs(GTEST_MAIN_LIBRARIES GTEST_MAIN_LIBRARY)
- set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
find_package(Threads QUIET)
- if(NOT TARGET GTest::GTest)
+ if(NOT TARGET GTest::gtest)
__gtest_determine_library_type(GTEST_LIBRARY)
- add_library(GTest::GTest ${GTEST_LIBRARY_TYPE} IMPORTED)
+ add_library(GTest::gtest ${GTEST_LIBRARY_TYPE} IMPORTED)
if(TARGET Threads::Threads)
- set_target_properties(GTest::GTest PROPERTIES
+ set_target_properties(GTest::gtest PROPERTIES
INTERFACE_LINK_LIBRARIES Threads::Threads)
endif()
if(GTEST_LIBRARY_TYPE STREQUAL "SHARED")
- set_target_properties(GTest::GTest PROPERTIES
+ set_target_properties(GTest::gtest PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
endif()
if(GTEST_INCLUDE_DIRS)
- set_target_properties(GTest::GTest PROPERTIES
+ set_target_properties(GTest::gtest PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIRS}")
endif()
- __gtest_import_library(GTest::GTest GTEST_LIBRARY "")
- __gtest_import_library(GTest::GTest GTEST_LIBRARY "RELEASE")
- __gtest_import_library(GTest::GTest GTEST_LIBRARY "DEBUG")
+ __gtest_import_library(GTest::gtest GTEST_LIBRARY "")
+ __gtest_import_library(GTest::gtest GTEST_LIBRARY "RELEASE")
+ __gtest_import_library(GTest::gtest GTEST_LIBRARY "DEBUG")
endif()
- if(NOT TARGET GTest::Main)
+ if(NOT TARGET GTest::gtest_main)
__gtest_determine_library_type(GTEST_MAIN_LIBRARY)
- add_library(GTest::Main ${GTEST_MAIN_LIBRARY_TYPE} IMPORTED)
- set_target_properties(GTest::Main PROPERTIES
- INTERFACE_LINK_LIBRARIES "GTest::GTest")
- __gtest_import_library(GTest::Main GTEST_MAIN_LIBRARY "")
- __gtest_import_library(GTest::Main GTEST_MAIN_LIBRARY "RELEASE")
- __gtest_import_library(GTest::Main GTEST_MAIN_LIBRARY "DEBUG")
+ add_library(GTest::gtest_main ${GTEST_MAIN_LIBRARY_TYPE} IMPORTED)
+ set_target_properties(GTest::gtest_main PROPERTIES
+ INTERFACE_LINK_LIBRARIES "GTest::gtest")
+ __gtest_import_library(GTest::gtest_main GTEST_MAIN_LIBRARY "")
+ __gtest_import_library(GTest::gtest_main GTEST_MAIN_LIBRARY "RELEASE")
+ __gtest_import_library(GTest::gtest_main GTEST_MAIN_LIBRARY "DEBUG")
endif()
- # Add targets mapping the same library names as defined in
- # GTest's CMake package config.
- if(NOT TARGET GTest::gtest)
- add_library(GTest::gtest INTERFACE IMPORTED)
- target_link_libraries(GTest::gtest INTERFACE GTest::GTest)
- endif()
- if(NOT TARGET GTest::gtest_main)
- add_library(GTest::gtest_main INTERFACE IMPORTED)
- target_link_libraries(GTest::gtest_main INTERFACE GTest::Main)
- endif()
+ __gtest_define_backwards_compatible_library_targets()
endif()
diff --git a/Modules/FindGettext.cmake b/Modules/FindGettext.cmake
index 213ad13de..252f2aea2 100644
--- a/Modules/FindGettext.cmake
+++ b/Modules/FindGettext.cmake
@@ -54,7 +54,7 @@ PO_FILES <po1> <po2> ... )
If ALL is specified, the po files are processed when building the all traget.
It creates a custom target "pofiles".
-.. note::
+.. versionadded:: 3.2
If you wish to use the Gettext library (libintl), use :module:`FindIntl`.
#]=======================================================================]
diff --git a/Modules/FindGit.cmake b/Modules/FindGit.cmake
index 3491cdcc2..99850b4f1 100644
--- a/Modules/FindGit.cmake
+++ b/Modules/FindGit.cmake
@@ -5,12 +5,6 @@
FindGit
-------
-The module defines the following ``IMPORTED`` targets (when
-:prop_gbl:`CMAKE_ROLE` is ``PROJECT``):
-
-``Git::Git``
- Executable of the Git command-line client.
-
The module defines the following variables:
``GIT_EXECUTABLE``
@@ -20,6 +14,13 @@ The module defines the following variables:
``GIT_VERSION_STRING``
The version of Git found.
+.. versionadded:: 3.14
+ The module defines the following ``IMPORTED`` targets (when
+ :prop_gbl:`CMAKE_ROLE` is ``PROJECT``):
+
+``Git::Git``
+ Executable of the Git command-line client.
+
Example usage:
.. code-block:: cmake
@@ -76,20 +77,51 @@ unset(git_names)
unset(_git_sourcetree_path)
if(GIT_EXECUTABLE)
- execute_process(COMMAND ${GIT_EXECUTABLE} --version
- OUTPUT_VARIABLE git_version
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (git_version MATCHES "^git version [0-9]")
- string(REPLACE "git version " "" GIT_VERSION_STRING "${git_version}")
+ # Avoid querying the version if we've already done that this run. For
+ # projects that use things like ExternalProject or FetchContent heavily,
+ # this saving can be measurable on some platforms.
+ #
+ # This is an internal property, projects must not try to use it.
+ # We don't want this stored in the cache because it might still change
+ # between CMake runs, but it shouldn't change during a run for a given
+ # git executable location.
+ set(__doGitVersionCheck TRUE)
+ get_property(__gitVersionProp GLOBAL
+ PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION
+ )
+ if(__gitVersionProp)
+ list(GET __gitVersionProp 0 __gitExe)
+ list(GET __gitVersionProp 1 __gitVersion)
+ if(__gitExe STREQUAL GIT_EXECUTABLE AND NOT __gitVersion STREQUAL "")
+ set(GIT_VERSION_STRING "${__gitVersion}")
+ set(__doGitVersionCheck FALSE)
+ endif()
+ unset(__gitExe)
+ unset(__gitVersion)
+ endif()
+ unset(__gitVersionProp)
+
+ if(__doGitVersionCheck)
+ execute_process(COMMAND ${GIT_EXECUTABLE} --version
+ OUTPUT_VARIABLE git_version
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (git_version MATCHES "^git version [0-9]")
+ string(REPLACE "git version " "" GIT_VERSION_STRING "${git_version}")
+ set_property(GLOBAL PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION
+ "${GIT_EXECUTABLE};${GIT_VERSION_STRING}"
+ )
+ endif()
+ unset(git_version)
endif()
- unset(git_version)
+ unset(__doGitVersionCheck)
get_property(_findgit_role GLOBAL PROPERTY CMAKE_ROLE)
if(_findgit_role STREQUAL "PROJECT" AND NOT TARGET Git::Git)
add_executable(Git::Git IMPORTED)
set_property(TARGET Git::Git PROPERTY IMPORTED_LOCATION "${GIT_EXECUTABLE}")
endif()
+ unset(_findgit_role)
endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
diff --git a/Modules/FindGnuTLS.cmake b/Modules/FindGnuTLS.cmake
index 819f00012..782a72b2f 100644
--- a/Modules/FindGnuTLS.cmake
+++ b/Modules/FindGnuTLS.cmake
@@ -10,6 +10,8 @@ Find the GNU Transport Layer Security library (gnutls)
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.16
+
This module defines :prop_tgt:`IMPORTED` target ``GnuTLS::GnuTLS``, if
gnutls has been found.
diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index 38388d998..16bf2794c 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -32,6 +32,9 @@ static link to a dynamic link for ``HDF5`` and all of it's dependencies.
To use this feature, make sure that the ``HDF5_USE_STATIC_LIBRARIES``
variable is set before the call to find_package.
+.. versionadded:: 3.10
+ Support for ``HDF5_USE_STATIC_LIBRARIES`` on Windows.
+
Both the serial and parallel ``HDF5`` wrappers are considered and the first
directory to contain either one will be used. In the event that both appear
in the same directory the serial version is preferentially selected. This
@@ -51,7 +54,8 @@ This module will set the following variables in your project:
``HDF5_FOUND``
HDF5 was found on the system
``HDF5_VERSION``
- HDF5 library version
+ .. versionadded:: 3.3
+ HDF5 library version
``HDF5_INCLUDE_DIRS``
Location of the HDF5 header files
``HDF5_DEFINITIONS``
@@ -112,15 +116,22 @@ also be defined. With all components enabled, the following variables will be d
With all components enabled, the following targets will be defined:
-::
-
- ``hdf5::hdf5``
- ``hdf5::hdf5_hl_cpp``
- ``hdf5::hdf5_fortran``
- ``hdf5::hdf5_hl``
- ``hdf5::hdf5_hl_cpp``
- ``hdf5::hdf5_hl_fortran``
- ``hdf5::h5diff``
+``HDF5::HDF5``
+ All detected ``HDF5_LIBRARIES``.
+``hdf5::hdf5``
+ C library.
+``hdf5::hdf5_cpp``
+ C++ library.
+``hdf5::hdf5_fortran``
+ Fortran library.
+``hdf5::hdf5_hl``
+ High-level C library.
+``hdf5::hdf5_hl_cpp``
+ High-level C++ library.
+``hdf5::hdf5_hl_fortran``
+ High-level Fortran library.
+``hdf5::h5diff``
+ ``h5diff`` executable.
Hints
^^^^^
@@ -128,12 +139,18 @@ Hints
The following variables can be set to guide the search for HDF5 libraries and includes:
``HDF5_PREFER_PARALLEL``
+ .. versionadded:: 3.4
+
set ``true`` to prefer parallel HDF5 (by default, serial is preferred)
``HDF5_FIND_DEBUG``
+ .. versionadded:: 3.9
+
Set ``true`` to get extra debugging output.
``HDF5_NO_FIND_PACKAGE_CONFIG_FILE``
+ .. versionadded:: 3.8
+
Set ``true`` to skip trying to find ``hdf5-config.cmake``.
#]=======================================================================]
@@ -196,22 +213,6 @@ else()
set(HDF5_Fortran_COMPILER_NAMES h5fc h5pfc)
endif()
-# We may have picked up some duplicates in various lists during the above
-# process for the language bindings (both the C and C++ bindings depend on
-# libz for example). Remove the duplicates. It appears that the default
-# CMake behavior is to remove duplicates from the end of a list. However,
-# for link lines, this is incorrect since unresolved symbols are searched
-# for down the link line. Therefore, we reverse the list, remove the
-# duplicates, and then reverse it again to get the duplicates removed from
-# the beginning.
-macro(_HDF5_remove_duplicates_from_beginning _list_name)
- if(${_list_name})
- list(REVERSE ${_list_name})
- list(REMOVE_DUPLICATES ${_list_name})
- list(REVERSE ${_list_name})
- endif()
-endmacro()
-
# Test first if the current compilers automatically wrap HDF5
function(_HDF5_test_regular_compiler_C success version is_parallel)
set(scratch_directory
@@ -716,10 +717,8 @@ if(NOT HDF5_FOUND)
endif()
set(HDF5_${_lang}_FOUND TRUE)
- _HDF5_remove_duplicates_from_beginning(HDF5_${_lang}_DEFINITIONS)
- _HDF5_remove_duplicates_from_beginning(HDF5_${_lang}_INCLUDE_DIRS)
- _HDF5_remove_duplicates_from_beginning(HDF5_${_lang}_LIBRARIES)
- _HDF5_remove_duplicates_from_beginning(HDF5_${_lang}_HL_LIBRARIES)
+ list(REMOVE_DUPLICATES HDF5_${_lang}_DEFINITIONS)
+ list(REMOVE_DUPLICATES HDF5_${_lang}_INCLUDE_DIRS)
else()
set(_HDF5_NEED_TO_SEARCH TRUE)
endif()
@@ -772,10 +771,8 @@ elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH)
endif()
endif()
endforeach()
- _HDF5_remove_duplicates_from_beginning(HDF5_DEFINITIONS)
- _HDF5_remove_duplicates_from_beginning(HDF5_INCLUDE_DIRS)
- _HDF5_remove_duplicates_from_beginning(HDF5_LIBRARIES)
- _HDF5_remove_duplicates_from_beginning(HDF5_HL_LIBRARIES)
+ list(REMOVE_DUPLICATES HDF5_DEFINITIONS)
+ list(REMOVE_DUPLICATES HDF5_INCLUDE_DIRS)
set(HDF5_FOUND TRUE)
set(HDF5_REQUIRED_VARS HDF5_LIBRARIES)
if(HDF5_FIND_HL)
@@ -915,10 +912,8 @@ if( NOT HDF5_FOUND )
set(HDF5_HL_FOUND TRUE)
endif()
- _HDF5_remove_duplicates_from_beginning(HDF5_DEFINITIONS)
- _HDF5_remove_duplicates_from_beginning(HDF5_INCLUDE_DIRS)
- _HDF5_remove_duplicates_from_beginning(HDF5_LIBRARIES)
- _HDF5_remove_duplicates_from_beginning(HDF5_HL_LIBRARIES)
+ list(REMOVE_DUPLICATES HDF5_DEFINITIONS)
+ list(REMOVE_DUPLICATES HDF5_INCLUDE_DIRS)
# If the HDF5 include directory was found, open H5pubconf.h to determine if
# HDF5 was compiled with parallel IO support
@@ -1139,6 +1134,21 @@ if (HDF5_FIND_DEBUG)
message(STATUS "HDF5_${_lang}_HL_LIBRARY: ${HDF5_${_lang}_HL_LIBRARY}")
message(STATUS "HDF5_${_lang}_HL_LIBRARIES: ${HDF5_${_lang}_HL_LIBRARIES}")
endforeach()
+ message(STATUS "Defined targets (if any):")
+ foreach(_lang IN ITEMS "" "_cpp" "_fortran")
+ foreach(_hl IN ITEMS "" "_hl")
+ foreach(_prefix IN ITEMS "hdf5::" "")
+ foreach(_suffix IN ITEMS "-static" "-shared" "")
+ set (_target ${_prefix}hdf5${_hl}${_lang}${_suffix})
+ if (TARGET ${_target})
+ message(STATUS "... ${_target}")
+ else()
+ #message(STATUS "... ${_target} does not exist")
+ endif()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
endif()
unset(_lang)
unset(_HDF5_NEED_TO_SEARCH)
diff --git a/Modules/FindHg.cmake b/Modules/FindHg.cmake
index 1358363d2..e9f2c8277 100644
--- a/Modules/FindHg.cmake
+++ b/Modules/FindHg.cmake
@@ -15,7 +15,8 @@ The module defines the following variables:
HG_FOUND - true if the command line client was found
HG_VERSION_STRING - the version of mercurial found
-If the command line client executable is found the following macro is defined:
+.. versionadded:: 3.1
+ If the command line client executable is found the following macro is defined:
::
diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake
index c8b3e1fb7..2bb49adec 100644
--- a/Modules/FindICU.cmake
+++ b/Modules/FindICU.cmake
@@ -18,6 +18,9 @@ Note that on Windows ``data`` is named ``dt`` and ``i18n`` is named
``in``; any of the names may be used, and the appropriate
platform-specific library name will be automatically selected.
+.. versionadded:: 3.11
+ Added support for static libraries on Windows.
+
This module reports information about the ICU installation in
several variables. General variables::
@@ -31,7 +34,7 @@ Imported targets::
ICU::<C>
Where ``<C>`` is the name of an ICU component, for example
-``ICU::i18n``.
+``ICU::i18n``; ``<C>`` is lower-case.
ICU programs are reported in::
@@ -54,16 +57,14 @@ ICU programs are reported in::
ICU component libraries are reported in::
- ICU_<C>_FOUND - ON if component was found
- ICU_<C>_LIBRARIES - libraries for component
+ ICU_<C>_FOUND - ON if component was found; ``<C>`` is upper-case.
+ ICU_<C>_LIBRARIES - libraries for component; ``<C>`` is upper-case.
ICU datafiles are reported in::
ICU_MAKEFILE_INC - Makefile.inc
ICU_PKGDATA_INC - pkgdata.inc
-Note that ``<C>`` is the uppercased name of the component.
-
This module reads hints about search results from::
ICU_ROOT - the root of the ICU installation
@@ -73,9 +74,9 @@ ICU_ROOT variable takes precedence.
The following cache variables may also be set::
- ICU_<P>_EXECUTABLE - the path to executable <P>
+ ICU_<P>_EXECUTABLE - the path to executable <P>; ``<P>`` is upper-case.
ICU_INCLUDE_DIR - the directory containing the ICU headers
- ICU_<C>_LIBRARY - the library for component <C>
+ ICU_<C>_LIBRARY - the library for component <C>; ``<C>`` is upper-case.
.. note::
@@ -188,7 +189,8 @@ function(_ICU_FIND)
set(component_cache "ICU_${component_upcase}_LIBRARY")
set(component_cache_release "${component_cache}_RELEASE")
set(component_cache_debug "${component_cache}_DEBUG")
- set(component_found "${component_upcase}_FOUND")
+ set(component_found "ICU_${component_upcase}_FOUND")
+ set(component_found_compat "${component_upcase}_FOUND")
set(component_libnames "icu${component}")
set(component_debug_libnames "icu${component}d")
@@ -250,12 +252,15 @@ function(_ICU_FIND)
mark_as_advanced("${component_cache_release}" "${component_cache_debug}")
if(${component_cache})
set("${component_found}" ON)
+ set("${component_found_compat}" ON)
list(APPEND ICU_LIBRARY "${${component_cache}}")
endif()
mark_as_advanced("${component_found}")
+ mark_as_advanced("${component_found_compat}")
set("${component_cache}" "${${component_cache}}" PARENT_SCOPE)
set("${component_found}" "${${component_found}}" PARENT_SCOPE)
- if(${component_found})
+ set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE)
+ if(component_found OR component_found_compat)
if (ICU_FIND_REQUIRED_${component})
list(APPEND ICU_LIBS_FOUND "${component} (required)")
else()
@@ -346,7 +351,7 @@ if(ICU_FOUND)
set(_ICU_component_cache_release "ICU_${_ICU_component_upcase}_LIBRARY_RELEASE")
set(_ICU_component_cache_debug "ICU_${_ICU_component_upcase}_LIBRARY_DEBUG")
set(_ICU_component_lib "ICU_${_ICU_component_upcase}_LIBRARIES")
- set(_ICU_component_found "${_ICU_component_upcase}_FOUND")
+ set(_ICU_component_found "ICU_${_ICU_component_upcase}_FOUND")
set(_ICU_imported_target "ICU::${_ICU_component}")
if(${_ICU_component_found})
set("${_ICU_component_lib}" "${${_ICU_component_cache}}")
@@ -400,7 +405,7 @@ if(ICU_DEBUG)
foreach(program IN LISTS icu_programs)
string(TOUPPER "${program}" program_upcase)
set(program_lib "ICU_${program_upcase}_EXECUTABLE")
- message(STATUS "${program} program: ${${program_lib}}")
+ message(STATUS "${program} program: ${program_lib}=${${program_lib}}")
unset(program_upcase)
unset(program_lib)
endforeach()
@@ -409,7 +414,7 @@ if(ICU_DEBUG)
string(TOUPPER "${data}" data_upcase)
string(REPLACE "." "_" data_upcase "${data_upcase}")
set(data_lib "ICU_${data_upcase}")
- message(STATUS "${data} data: ${${data_lib}}")
+ message(STATUS "${data} data: ${data_lib}=${${data_lib}}")
unset(data_upcase)
unset(data_lib)
endforeach()
@@ -417,12 +422,15 @@ if(ICU_DEBUG)
foreach(component IN LISTS ICU_FIND_COMPONENTS)
string(TOUPPER "${component}" component_upcase)
set(component_lib "ICU_${component_upcase}_LIBRARIES")
- set(component_found "${component_upcase}_FOUND")
- message(STATUS "${component} library found: ${${component_found}}")
- message(STATUS "${component} library: ${${component_lib}}")
+ set(component_found "ICU_${component_upcase}_FOUND")
+ set(component_found_compat "${component_upcase}_FOUND")
+ message(STATUS "${component} library found: ${component_found}=${${component_found}}")
+ message(STATUS "${component} library found (compat name): ${component_found_compat}=${${component_found_compat}}")
+ message(STATUS "${component} library: ${component_lib}=${${component_lib}}")
unset(component_upcase)
unset(component_lib)
unset(component_found)
+ unset(component_found_compat)
endforeach()
message(STATUS "----------------")
endif()
diff --git a/Modules/FindIce.cmake b/Modules/FindIce.cmake
index 0f821e886..543e10c38 100644
--- a/Modules/FindIce.cmake
+++ b/Modules/FindIce.cmake
@@ -23,6 +23,15 @@ Ice 3.7 and later also include C++11-specific components:
Note that the set of supported components is Ice version-specific.
+.. versionadded:: 3.4
+ Imported targets for components and most ``EXECUTABLE`` variables.
+
+.. versionadded:: 3.7
+ Debug and Release variants are found separately.
+
+.. versionadded:: 3.10
+ Ice 3.7 support, including new components, programs and the Nuget package.
+
This module reports information about the Ice installation in
several variables. General variables::
@@ -56,6 +65,9 @@ Ice slice programs are reported in::
Ice_SLICE2PY_EXECUTABLE - path to slice2py executable
Ice_SLICE2RB_EXECUTABLE - path to slice2rb executable
+.. versionadded:: 3.14
+ Variables for ``slice2confluence`` and ``slice2matlab``.
+
Ice programs are reported in::
Ice_GLACIER2ROUTER_EXECUTABLE - path to glacier2router executable
diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake
index 8bf5123b7..d7de0ddcc 100644
--- a/Modules/FindImageMagick.cmake
+++ b/Modules/FindImageMagick.cmake
@@ -7,6 +7,9 @@ FindImageMagick
Find ImageMagick binary suite.
+.. versionadded:: 3.9
+ Added support for ImageMagick 7.
+
This module will search for a set of ImageMagick tools specified as
components in the :command:`find_package` call. Typical components include,
but are not limited to (future versions of ImageMagick might have
diff --git a/Modules/FindIntl.cmake b/Modules/FindIntl.cmake
index 1a09a6097..686c81801 100644
--- a/Modules/FindIntl.cmake
+++ b/Modules/FindIntl.cmake
@@ -16,10 +16,21 @@ installation in several variables. General variables::
Intl_INCLUDE_DIRS - the directory containing the libintl headers
Intl_LIBRARIES - libintl libraries to be linked
+.. versionadded:: 3.20
+ This module defines :prop_tgt:`IMPORTED` target ``Intl::Intl``.
+
The following cache variables may also be set::
Intl_INCLUDE_DIR - the directory containing the libintl headers
Intl_LIBRARY - the libintl library (if any)
+ Intl_HAVE_GETTEXT_BUILTIN - check if gettext is in the C library
+ Intl_HAVE_DCGETTEXT_BUILTIN - check if dcgettext is in the C library
+ Intl_IS_BUILTIN - whether intl is a part of the C library determined
+ from the result of Intl_HAVE_GETTEXT_BUILTIN and Intl_HAVE_DCGETTEXT_BUILTIN
+
+.. versionadded:: 3.20
+ Added the ``Intl_HAVE_GETTEXT_BUILTIN``, ``Intl_HAVE_DCGETTEXT_BUILTIN`` and
+ ``Intl_IS_BUILTIN`` variables.
.. note::
On some platforms, such as Linux with GNU libc, the gettext
@@ -35,6 +46,22 @@ The following cache variables may also be set::
# Written by Roger Leigh <rleigh@codelibre.net>
+include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/CheckSymbolExists.cmake)
+
+# Check if we have libintl is a part of libc
+cmake_push_check_state(RESET)
+set(CMAKE_REQUIRED_QUIET TRUE)
+check_symbol_exists(gettext libintl.h Intl_HAVE_GETTEXT_BUILTIN)
+check_symbol_exists(dcgettext libintl.h Intl_HAVE_DCGETTEXT_BUILTIN) # redundant check
+cmake_pop_check_state()
+
+if(Intl_HAVE_GETTEXT_BUILTIN AND Intl_HAVE_DCGETTEXT_BUILTIN)
+ set(Intl_IS_BUILTIN TRUE)
+else()
+ set(Intl_IS_BUILTIN FALSE)
+endif()
+
# Find include directory
find_path(Intl_INCLUDE_DIR
NAMES "libintl.h"
@@ -42,21 +69,28 @@ find_path(Intl_INCLUDE_DIR
mark_as_advanced(Intl_INCLUDE_DIR)
# Find all Intl libraries
-find_library(Intl_LIBRARY "intl" NAMES_PER_DIR
- DOC "libintl libraries (if not in the C library)")
-mark_as_advanced(Intl_LIBRARY)
+set(Intl_REQUIRED_VARS)
+if(NOT Intl_IS_BUILTIN)
+ find_library(Intl_LIBRARY "intl" "libintl" NAMES_PER_DIR
+ DOC "libintl libraries (if not in the C library)")
+ mark_as_advanced(Intl_LIBRARY)
+ list(APPEND Intl_REQUIRED_VARS Intl_LIBRARY)
+endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl
FOUND_VAR Intl_FOUND
- REQUIRED_VARS Intl_INCLUDE_DIR
+ REQUIRED_VARS Intl_INCLUDE_DIR ${Intl_REQUIRED_VARS}
FAIL_MESSAGE "Failed to find Gettext libintl")
+unset(Intl_REQUIRED_VARS)
if(Intl_FOUND)
set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}")
- if(Intl_LIBRARY)
- set(Intl_LIBRARIES "${Intl_LIBRARY}")
- else()
- unset(Intl_LIBRARIES)
+ set(Intl_LIBRARIES "${Intl_LIBRARY}")
+ if(NOT TARGET Intl::Intl)
+ add_library(Intl::Intl INTERFACE IMPORTED)
+ set_target_properties(Intl::Intl PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${Intl_INCLUDE_DIRS}"
+ INTERFACE_LINK_LIBRARIES "${Intl_LIBRARIES}")
endif()
endif()
diff --git a/Modules/FindJPEG.cmake b/Modules/FindJPEG.cmake
index 632fc9aa0..add2486c3 100644
--- a/Modules/FindJPEG.cmake
+++ b/Modules/FindJPEG.cmake
@@ -10,6 +10,8 @@ Find the Joint Photographic Experts Group (JPEG) library (``libjpeg``)
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.12
+
This module defines the following :prop_tgt:`IMPORTED` targets:
``JPEG::JPEG``
@@ -27,7 +29,8 @@ This module will set the following variables in your project:
``JPEG_LIBRARIES``
the libraries needed to use JPEG.
``JPEG_VERSION``
- the version of the JPEG library found
+ .. versionadded:: 3.12
+ the version of the JPEG library found
Cache variables
^^^^^^^^^^^^^^^
@@ -41,6 +44,9 @@ The following cache variables may also be set:
``JPEG_LIBRARY_DEBUG``
where to find the JPEG library (debug).
+.. versionadded:: 3.12
+ Debug and Release variand are found separately.
+
Obsolete variables
^^^^^^^^^^^^^^^^^^
@@ -52,7 +58,7 @@ Obsolete variables
find_path(JPEG_INCLUDE_DIR jpeglib.h)
-set(jpeg_names ${JPEG_NAMES} jpeg jpeg-static libjpeg libjpeg-static)
+set(jpeg_names ${JPEG_NAMES} jpeg jpeg-static libjpeg libjpeg-static turbojpeg turbojpeg-static)
foreach(name ${jpeg_names})
list(APPEND jpeg_names_debug "${name}d")
endforeach()
diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake
index 9db740b4f..4f0e0feaf 100644
--- a/Modules/FindJava.cmake
+++ b/Modules/FindJava.cmake
@@ -13,6 +13,9 @@ to specify a Java installation prefix explicitly.
See also the :module:`FindJNI` module to find Java Native Interface (JNI).
+.. versionadded:: 3.10
+ Added support for Java 9+ version parsing.
+
Specify one or more of the following components as you call this find module. See example below.
::
@@ -41,7 +44,9 @@ This module sets the following result variables:
Java_VERSION_TWEAK = The tweak version of the package found (after '_')
Java_VERSION = This is set to: $major[.$minor[.$patch[.$tweak]]]
-
+.. versionadded:: 3.4
+ Added the ``Java_IDLJ_EXECUTABLE`` and ``Java_JARSIGNER_EXECUTABLE``
+ variables.
The minimum required version of Java can be specified using the
:command:`find_package` syntax, e.g.
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index 4b71cee59..45e4be72f 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -43,14 +43,46 @@ The following variables may be set to influence this module's behavior:
* ``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``).
+
``BLA_F95``
if ``ON`` tries to find the BLAS95/LAPACK95 interfaces
+``BLA_PREFER_PKGCONFIG``
+ .. versionadded:: 3.20
+
+ if set ``pkg-config`` will be used to search for a LAPACK library first
+ and if one is found that is preferred
+
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.18
+
This module defines the following :prop_tgt:`IMPORTED` target:
``LAPACK::LAPACK``
@@ -95,6 +127,26 @@ 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)
+ 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}")
+ 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)
+ endif()
+endfunction()
+
macro(_lapack_find_library_setup)
cmake_push_check_state()
set(CMAKE_REQUIRED_QUIET ${LAPACK_FIND_QUIETLY})
@@ -239,6 +291,21 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
_lapack_find_dependency(BLAS)
endif()
+# Search with pkg-config if specified
+if(BLA_PREFER_PKGCONFIG)
+ find_package(PkgConfig)
+ pkg_check_modules(PKGC_LAPACK lapack)
+ if(PKGC_LAPACK_FOUND)
+ set(LAPACK_FOUND TRUE)
+ set(LAPACK_LIBRARIES "${PKGC_LAPACK_LINK_LIBRARIES}")
+ if (BLAS_LIBRARIES)
+ list(APPEND LAPACK_LIBRARIES "${BLAS_LIBRARIES}")
+ endif()
+ _add_lapack_target()
+ return()
+ endif()
+endif()
+
# Search for different LAPACK distributions if BLAS is found
if(NOT LAPACK_NOT_FOUND_MESSAGE)
set(LAPACK_LINKER_FLAGS ${BLAS_LINKER_FLAGS})
@@ -494,6 +561,30 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
)
endif()
+ # Elbrus Math Library?
+ if(NOT LAPACK_LIBRARIES
+ AND (BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All"))
+
+ set(LAPACK_EML_LIB "eml")
+
+ # Check for OpenMP support, VIA BLA_VENDOR of eml_mt
+ if(BLA_VENDOR MATCHES "_mt")
+ set(LAPACK_EML_LIB "${LAPACK_EML_LIB}_mt")
+ endif()
+
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "${LAPACK_EML_LIB}"
+ ""
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ endif()
+
# Generic LAPACK library?
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR STREQUAL "Generic"
@@ -535,21 +626,6 @@ if(LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
set(LAPACK_LIBRARIES "")
endif()
-if(LAPACK_FOUND AND NOT TARGET LAPACK::LAPACK)
- add_library(LAPACK::LAPACK INTERFACE IMPORTED)
- 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}")
- endif()
-
- if(_lapack_libs)
- set_target_properties(LAPACK::LAPACK PROPERTIES
- INTERFACE_LINK_LIBRARIES "${_lapack_libs}"
- )
- endif()
- unset(_lapack_libs)
-endif()
+_add_lapack_target()
_lapack_find_library_teardown()
diff --git a/Modules/FindLATEX.cmake b/Modules/FindLATEX.cmake
index b0dad7da3..1e82651fe 100644
--- a/Modules/FindLATEX.cmake
+++ b/Modules/FindLATEX.cmake
@@ -11,6 +11,10 @@ This module finds an installed LaTeX and determines the location
of the compiler. Additionally the module looks for Latex-related
software like BibTeX.
+.. versionadded:: 3.2
+ Component processing; support for htlatex, pdftops, Biber, xindy, XeLaTeX,
+ LuaLaTeX.
+
This module sets the following result variables::
LATEX_FOUND: whether found Latex and requested components
diff --git a/Modules/FindLibArchive.cmake b/Modules/FindLibArchive.cmake
index ce3c8b8e8..08078a295 100644
--- a/Modules/FindLibArchive.cmake
+++ b/Modules/FindLibArchive.cmake
@@ -22,6 +22,10 @@ The module defines the following ``IMPORTED`` targets:
::
LibArchive::LibArchive - target for linking against libarchive
+
+.. versionadded:: 3.6
+ Support for new libarchive 3.2 version string format.
+
#]=======================================================================]
find_path(LibArchive_INCLUDE_DIR
diff --git a/Modules/FindLibLZMA.cmake b/Modules/FindLibLZMA.cmake
index 4a79a1028..9ec8f075d 100644
--- a/Modules/FindLibLZMA.cmake
+++ b/Modules/FindLibLZMA.cmake
@@ -11,6 +11,8 @@ Find LZMA compression algorithm headers and library.
Imported Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.14
+
This module defines :prop_tgt:`IMPORTED` target ``LibLZMA::LibLZMA``, if
liblzma has been found.
diff --git a/Modules/FindLibXml2.cmake b/Modules/FindLibXml2.cmake
index 063160712..ce28d0302 100644
--- a/Modules/FindLibXml2.cmake
+++ b/Modules/FindLibXml2.cmake
@@ -10,12 +10,16 @@ Find the XML processing library (libxml2).
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.12
+
The following :prop_tgt:`IMPORTED` targets may be defined:
``LibXml2::LibXml2``
- If the libxml2 library has been found
+ libxml2 library.
``LibXml2::xmllint``
- If the xmllint command-line executable has been found
+ .. versionadded:: 3.17
+
+ xmllint command-line executable.
Result variables
^^^^^^^^^^^^^^^^
diff --git a/Modules/FindLibXslt.cmake b/Modules/FindLibXslt.cmake
index fc7adeb0f..97943d6d1 100644
--- a/Modules/FindLibXslt.cmake
+++ b/Modules/FindLibXslt.cmake
@@ -11,6 +11,8 @@ Transformations (XSLT) library (LibXslt)
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.18
+
The following :prop_tgt:`IMPORTED` targets may be defined:
``LibXslt::LibXslt``
@@ -35,7 +37,8 @@ Additionally, the following two variables are set (but not required
for using xslt):
``LIBXSLT_EXSLT_INCLUDE_DIR``
- The include directory for exslt.
+ .. versionadded:: 3.18
+ The include directory for exslt.
``LIBXSLT_EXSLT_LIBRARIES``
Link to these if you need to link against the exslt library.
``LIBXSLT_XSLTPROC_EXECUTABLE``
diff --git a/Modules/FindLua.cmake b/Modules/FindLua.cmake
index c4361b74b..32642fe23 100644
--- a/Modules/FindLua.cmake
+++ b/Modules/FindLua.cmake
@@ -5,10 +5,11 @@
FindLua
-------
-
-
Locate Lua library.
+.. versionadded:: 3.18
+ Support for Lua 5.4.
+
This module defines::
::
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index 789a72eb3..195ca4967 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -12,6 +12,10 @@ high-performance distributed-memory parallel applications, and is
typically deployed on a cluster. MPI is a standard interface (defined
by the MPI forum) for which many implementations are available.
+.. versionadded:: 3.10
+ Major overhaul of the module: many new variables, per-language components,
+ support for a wider variety of runtimes.
+
Variables for using MPI
^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +54,8 @@ project, where ``<lang>`` is one of C, CXX, or Fortran:
``MPI_<lang>_LIBRARIES``
All libraries to link MPI programs against.
-Additionally, the following :prop_tgt:`IMPORTED` targets are defined:
+.. versionadded:: 3.9
+ Additionally, the following :prop_tgt:`IMPORTED` targets are defined:
``MPI::MPI_<lang>``
Target for using MPI from ``<lang>``.
@@ -236,8 +241,10 @@ If the following variables are set to true, the respective search will be perfor
Backward Compatibility
^^^^^^^^^^^^^^^^^^^^^^
+.. deprecated:: 3.10
+
For backward compatibility with older versions of FindMPI, these
-variables are set, but deprecated:
+variables are set:
::
@@ -287,6 +294,11 @@ if(WIN32)
set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc.bat)
set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort.bat mpif77.bat mpif90.bat)
+ # Intel MPI compiler names
+ set(_MPI_IntelLLVM_C_COMPILER_NAMES mpiicc.bat)
+ set(_MPI_IntelLLVM_CXX_COMPILER_NAMES mpiicpc.bat)
+ set(_MPI_IntelLLVM_Fortran_COMPILER_NAMES mpiifort.bat mpif77.bat mpif90.bat)
+
# Intel MPI compiler names for MSMPI
set(_MPI_MSVC_C_COMPILER_NAMES mpicl.bat)
set(_MPI_MSVC_CXX_COMPILER_NAMES mpicl.bat)
@@ -295,6 +307,11 @@ else()
set(_MPI_Intel_C_COMPILER_NAMES mpiicc)
set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++)
set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77)
+
+ # Intel compiler names
+ set(_MPI_IntelLLVM_C_COMPILER_NAMES mpiicc)
+ set(_MPI_IntelLLVM_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++)
+ set(_MPI_IntelLLVM_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77)
endif()
# PGI compiler names
@@ -320,7 +337,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 MSVC PGI XL)
+ foreach (id IN ITEMS 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})
@@ -1411,7 +1428,9 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
else()
set(_MPI_FIND_${LANG} FALSE)
- string(APPEND _MPI_FAIL_REASON "MPI component '${LANG}' was requested, but language ${LANG} is not enabled. ")
+ if(${LANG} IN_LIST MPI_FIND_COMPONENTS)
+ string(APPEND _MPI_FAIL_REASON "MPI component '${LANG}' was requested, but language ${LANG} is not enabled. ")
+ endif()
endif()
if(_MPI_FIND_${LANG})
if( ${LANG} STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS )
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 01f04922f..2f56d1571 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -17,6 +17,9 @@ can also be used:
* to retrieve various information from Matlab (mex extensions, versions and
release queries, ...)
+.. versionadded:: 3.12
+ Added Matlab Compiler Runtime (MCR) support.
+
The module supports the following components:
* ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the ``ENG`` and ``MAT``
@@ -28,6 +31,17 @@ The module supports the following components:
* ``MCC_COMPILER`` the MCC compiler, included with the Matlab Compiler add-on.
* ``SIMULINK`` the Simulink environment.
+.. versionadded:: 3.7
+ Added the ``MAT_LIBRARY`` component.
+
+.. versionadded:: 3.13
+ Added the ``ENGINE_LIBRARY``, ``DATAARRAY_LIBRARY`` and ``MCC_COMPILER``
+ components.
+
+.. versionchanged:: 3.14
+ Removed the ``MX_LIBRARY``, ``ENGINE_LIBRARY`` and ``DATAARRAY_LIBRARY``
+ components. These libraries are found unconditionally.
+
.. note::
The version given to the :command:`find_package` directive is the Matlab
@@ -107,8 +121,12 @@ Result variables
Matlab matrix library. Available only if the component ``MAT_LIBRARY``
is requested.
``Matlab_ENGINE_LIBRARY``
+ .. versionadded:: 3.13
+
Matlab C++ engine library, always available for R2018a and newer.
``Matlab_DATAARRAY_LIBRARY``
+ .. versionadded:: 3.13
+
Matlab C++ data array library, always available for R2018a and newer.
``Matlab_LIBRARIES``
the whole set of libraries of Matlab
@@ -116,6 +134,8 @@ Result variables
the mex compiler of Matlab. Currently not used.
Available only if the component ``MEX_COMPILER`` is requested.
``Matlab_MCC_COMPILER``
+ .. versionadded:: 3.13
+
the mcc compiler of Matlab. Included with the Matlab Compiler add-on.
Available only if the component ``MCC_COMPILER`` is requested.
@@ -241,6 +261,7 @@ if(NOT MATLAB_ADDITIONAL_VERSIONS)
endif()
set(MATLAB_VERSIONS_MAPPING
+ "R2021a=9.10"
"R2020b=9.9"
"R2020a=9.8"
"R2019b=9.7"
@@ -389,12 +410,12 @@ function(matlab_extract_all_installed_versions_from_registry win64 matlab_versio
set(matlabs_from_registry)
- foreach(_installation_type IN ITEMS "MATLAB" "MATLAB Runtime")
+ foreach(_installation_type IN ITEMS "MATLAB" "MATLAB Runtime" "MATLAB Compiler Runtime")
# /reg:64 should be added on 64 bits capable OSs in order to enable the
# redirection of 64 bits applications
execute_process(
- COMMAND reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\${_installation_type} /f * /k ${APPEND_REG}
+ COMMAND reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\${_installation_type}" /f * /k ${APPEND_REG}
RESULT_VARIABLE resultMatlab
OUTPUT_VARIABLE varMatlab
ERROR_VARIABLE errMatlab
@@ -405,12 +426,12 @@ function(matlab_extract_all_installed_versions_from_registry win64 matlab_versio
if(resultMatlab EQUAL 0)
string(
- REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)"
+ REGEX MATCHALL "${_installation_type}\\\\([0-9]+(\\.[0-9]+)?)"
matlab_versions_regex ${varMatlab})
foreach(match IN LISTS matlab_versions_regex)
string(
- REGEX MATCH "MATLAB\\\\(([0-9]+)(\\.([0-9]+))?)"
+ REGEX MATCH "${_installation_type}\\\\(([0-9]+)(\\.([0-9]+))?)"
current_match ${match})
set(_matlab_current_version ${CMAKE_MATCH_1})
@@ -517,7 +538,7 @@ function(matlab_get_all_valid_matlab_roots_from_registry matlab_versions matlab_
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${_matlab_current_version};MATLABROOT]"
ABSOLUTE)
- if(EXISTS ${current_MATLAB_ROOT})
+ if(EXISTS "${current_MATLAB_ROOT}")
list(APPEND _matlab_roots_list "MATLAB" ${_matlab_current_version} ${current_MATLAB_ROOT})
endif()
@@ -533,7 +554,23 @@ function(matlab_get_all_valid_matlab_roots_from_registry matlab_versions matlab_
# remove the dot
string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
- if(EXISTS ${current_MATLAB_ROOT})
+ if(EXISTS "${current_MATLAB_ROOT}")
+ list(APPEND _matlab_roots_list "MCR" ${_matlab_current_version} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}")
+ endif()
+
+ endforeach()
+
+ # Check for old MCR installations
+ foreach(_matlab_current_version ${matlab_versions})
+ get_filename_component(
+ current_MATLAB_ROOT
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB Compiler Runtime\\${_matlab_current_version};MATLABROOT]"
+ ABSOLUTE)
+
+ # remove the dot
+ string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
+
+ if(EXISTS "${current_MATLAB_ROOT}")
list(APPEND _matlab_roots_list "MCR" ${_matlab_current_version} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}")
endif()
@@ -923,14 +960,26 @@ endfunction()
the same folder without any processing, with the same name as the final
mex file, and with extension `.m`. In that case, typing ``help <name>``
in Matlab prints the documentation contained in this file.
- ``R2017b`` or ``R2018a`` may be given to specify the version of the C API
+ ``R2017b`` or ``R2018a``
+ .. versionadded:: 3.14
+
+ May be given to specify the version of the C API
to use: ``R2017b`` specifies the traditional (separate complex) C API,
and corresponds to the ``-R2017b`` flag for the `mex` command. ``R2018a``
specifies the new interleaved complex C API, and corresponds to the
``-R2018a`` flag for the `mex` command. Ignored if MATLAB version prior
to R2018a. Defaults to ``R2017b``.
- ``MODULE`` or ``SHARED`` may be given to specify the type of library to be
- created. ``EXECUTABLE`` may be given to create an executable instead of
+
+ ``MODULE`` or ``SHARED``
+ .. versionadded:: 3.7
+
+ May be given to specify the type of library to be
+ created.
+
+ ``EXECUTABLE``
+ .. versionadded:: 3.7
+
+ May be given to create an executable instead of
a library. If no type is given explicitly, the type is ``SHARED``.
``EXCLUDE_FROM_ALL``
This option has the same meaning as for :prop_tgt:`EXCLUDE_FROM_ALL` and
@@ -1035,7 +1084,12 @@ function(matlab_add_mex)
target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS})
if(Matlab_HAS_CPP_API)
- target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY} ${Matlab_DATAARRAY_LIBRARY})
+ if(Matlab_ENGINE_LIBRARY)
+ target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY})
+ endif()
+ if(Matlab_DATAARRAY_LIBRARY)
+ target_link_libraries(${${prefix}_NAME} ${Matlab_DATAARRAY_LIBRARY})
+ endif()
endif()
target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${${prefix}_LINK_TO})
@@ -1655,32 +1709,34 @@ find_path(
)
list(APPEND _matlab_required_variables Matlab_INCLUDE_DIRS)
-_Matlab_find_library(
- ${_matlab_lib_prefix_for_search}
- Matlab_MEX_LIBRARY
- mex
- PATHS ${_matlab_lib_dir_for_search}
- NO_DEFAULT_PATH
-)
-list(APPEND _matlab_required_variables Matlab_MEX_LIBRARY)
+if(Matlab_Or_MCR STREQUAL "MATLAB" OR Matlab_Or_MCR STREQUAL "UNKNOWN")
+ _Matlab_find_library(
+ ${_matlab_lib_prefix_for_search}
+ Matlab_MEX_LIBRARY
+ mex
+ PATHS ${_matlab_lib_dir_for_search}
+ NO_DEFAULT_PATH
+ )
+ list(APPEND _matlab_required_variables Matlab_MEX_LIBRARY)
-# the MEX extension is required
-list(APPEND _matlab_required_variables Matlab_MEX_EXTENSION)
+ # the MEX extension is required
+ list(APPEND _matlab_required_variables Matlab_MEX_EXTENSION)
-# the matlab root is required
-list(APPEND _matlab_required_variables Matlab_ROOT_DIR)
+ # the matlab root is required
+ list(APPEND _matlab_required_variables Matlab_ROOT_DIR)
-# The MX library is required
-_Matlab_find_library(
- ${_matlab_lib_prefix_for_search}
- Matlab_MX_LIBRARY
- mx
- PATHS ${_matlab_lib_dir_for_search}
- NO_DEFAULT_PATH
-)
-list(APPEND _matlab_required_variables Matlab_MX_LIBRARY)
-if(Matlab_MX_LIBRARY)
- set(Matlab_MX_LIBRARY_FOUND TRUE)
+ # The MX library is required
+ _Matlab_find_library(
+ ${_matlab_lib_prefix_for_search}
+ Matlab_MX_LIBRARY
+ mx
+ PATHS ${_matlab_lib_dir_for_search}
+ NO_DEFAULT_PATH
+ )
+ list(APPEND _matlab_required_variables Matlab_MX_LIBRARY)
+ if(Matlab_MX_LIBRARY)
+ set(Matlab_MX_LIBRARY_FOUND TRUE)
+ endif()
endif()
if(Matlab_HAS_CPP_API)
@@ -1694,7 +1750,6 @@ if(Matlab_HAS_CPP_API)
DOC "MatlabEngine Library"
NO_DEFAULT_PATH
)
- list(APPEND _matlab_required_variables Matlab_ENGINE_LIBRARY)
if(Matlab_ENGINE_LIBRARY)
set(Matlab_ENGINE_LIBRARY_FOUND TRUE)
endif()
@@ -1708,7 +1763,6 @@ if(Matlab_HAS_CPP_API)
DOC "MatlabDataArray Library"
NO_DEFAULT_PATH
)
- list(APPEND _matlab_required_variables Matlab_DATAARRAY_LIBRARY)
if(Matlab_DATAARRAY_LIBRARY)
set(Matlab_DATAARRAY_LIBRARY_FOUND TRUE)
endif()
@@ -1801,8 +1855,15 @@ endif()
set(Matlab_LIBRARIES
${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY}
- ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY}
- ${Matlab_DATAARRAY_LIBRARY} ${Matlab_ENGINE_LIBRARY})
+ ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY})
+
+if(Matlab_ENGINE_LIBRARY)
+ list(APPEND Matlab_LIBRARIES ${Matlab_ENGINE_LIBRARY})
+endif()
+
+if(Matlab_DATAARRAY_LIBRARY)
+ list(APPEND Matlab_LIBRARIES ${Matlab_DATAARRAY_LIBRARY})
+endif()
find_package_handle_standard_args(
Matlab
diff --git a/Modules/FindOpenACC.cmake b/Modules/FindOpenACC.cmake
index ed52e3591..cf58f3b80 100644
--- a/Modules/FindOpenACC.cmake
+++ b/Modules/FindOpenACC.cmake
@@ -12,7 +12,17 @@ Detect OpenACC support by the compiler.
This module can be used to detect OpenACC support in a compiler.
If the compiler supports OpenACC, the flags required to compile with
OpenACC support are returned in variables for the different languages.
-Currently, only PGI, GNU and Cray compilers are supported.
+Currently, only NVHPC, PGI, GNU and Cray compilers are supported.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.16
+
+The module provides :prop_tgt:`IMPORTED` targets:
+
+``OpenACC::OpenACC_<lang>``
+ Target for using OpenACC from ``<lang>``.
Variables
^^^^^^^^^
@@ -25,14 +35,11 @@ project, where ``<lang>`` is one of C, CXX, or Fortran:
``OpenACC_<lang>_FLAGS``
OpenACC compiler flags for ``<lang>``, separated by spaces.
``OpenACC_<lang>_OPTIONS``
+ .. versionadded:: 3.16
+
OpenACC compiler flags for ``<lang>``, as a list. Suitable for usage
with target_compile_options or target_link_options.
-Additionally, the module provides :prop_tgt:`IMPORTED` targets:
-
-``OpenACC::OpenACC_<lang>``
- Target for using OpenACC from ``<lang>``.
-
The module will also try to provide the OpenACC version variables:
``OpenACC_<lang>_SPEC_DATE``
@@ -132,6 +139,7 @@ endfunction()
function(_OPENACC_GET_FLAGS_CANDIDATE LANG FLAG_VAR)
+ set(ACC_FLAG_NVHPC "-acc")
set(ACC_FLAG_PGI "-acc")
set(ACC_FLAG_GNU "-fopenacc")
set(ACC_FLAG_Cray "-h acc")
@@ -148,6 +156,7 @@ endfunction()
function(_OPENACC_GET_ACCEL_TARGET_FLAG LANG TARGET FLAG_VAR)
# Find target accelerator flags.
+ set(ACC_TARGET_FLAG_NVHPC "-ta")
set(ACC_TARGET_FLAG_PGI "-ta")
if(DEFINED ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID})
set("${FLAG_VAR}" "${ACC_TARGET_FLAG_${CMAKE_${LANG}_COMPILER_ID}}=${TARGET}" PARENT_SCOPE)
@@ -157,6 +166,7 @@ endfunction()
function(_OPENACC_GET_VERBOSE_FLAG LANG FLAG_VAR)
# Find compiler's verbose flag for OpenACC.
+ set(ACC_VERBOSE_FLAG_NVHPC "-Minfo=accel")
set(ACC_VERBOSE_FLAG_PGI "-Minfo=accel")
if(DEFINED ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID})
set("${FLAG_VAR}" "${ACC_VERBOSE_FLAG_${CMAKE_${LANG}_COMPILER_ID}}" PARENT_SCOPE)
diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake
index b3e5a9f8d..1b4662b76 100644
--- a/Modules/FindOpenCL.cmake
+++ b/Modules/FindOpenCL.cmake
@@ -9,9 +9,14 @@ FindOpenCL
Finds Open Computing Language (OpenCL)
+.. versionadded:: 3.10
+ Detection of OpenCL 2.1 and 2.2.
+
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.7
+
This module defines :prop_tgt:`IMPORTED` target ``OpenCL::OpenCL``, if
OpenCL has been found.
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index 110e7f963..d6d1c0000 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -7,27 +7,41 @@ FindOpenGL
FindModule for OpenGL and OpenGL Utility Library (GLU).
+.. versionchanged:: 3.2
+ X11 is no longer added as a dependency on Unix/Linux systems.
+
+.. versionadded:: 3.10
+ GLVND support on Linux. See the :ref:`Linux Specific` section below.
+
Optional COMPONENTS
^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.10
+
This module respects several optional COMPONENTS: ``EGL``, ``GLX``, and
``OpenGL``. There are corresponding import targets for each of these flags.
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.8
+
This module defines the :prop_tgt:`IMPORTED` targets:
``OpenGL::GL``
- Defined to the platform-specific OpenGL libraries if the system has OpenGL.
-``OpenGL::OpenGL``
- Defined to libOpenGL if the system is GLVND-based.
+ Defined to the platform-specific OpenGL libraries if the system has OpenGL.
``OpenGL::GLU``
- Defined if the system has OpenGL Utility Library (GLU).
+ Defined if the system has OpenGL Utility Library (GLU).
+
+.. versionadded:: 3.10
+ Additionally, the following GLVND-specific library targets are defined:
+
+``OpenGL::OpenGL``
+ Defined to libOpenGL if the system is GLVND-based.
``OpenGL::GLX``
- Defined if the system has OpenGL Extension to the X Window System (GLX).
+ Defined if the system has OpenGL Extension to the X Window System (GLX).
``OpenGL::EGL``
- Defined if the system has EGL.
+ Defined if the system has EGL.
Result Variables
^^^^^^^^^^^^^^^^
@@ -55,6 +69,9 @@ This module sets the following variables:
On Linux, this assumes GLX and is never correct for EGL-based targets.
Clients are encouraged to use the ``OpenGL::*`` import targets instead.
+.. versionadded:: 3.10
+ Variables for GLVND-specific libraries ``OpenGL``, ``EGL`` and ``GLX``.
+
Cache variables
^^^^^^^^^^^^^^^
@@ -72,6 +89,11 @@ The following cache variables may also be set:
Path to the OpenGL library. New code should prefer the ``OpenGL::*`` import
targets.
+.. versionadded:: 3.10
+ Variables for GLVND-specific libraries ``OpenGL``, ``EGL`` and ``GLX``.
+
+.. _`Linux Specific`:
+
Linux-specific
^^^^^^^^^^^^^^
@@ -97,14 +119,14 @@ The value may be one of:
``GLVND``
If the GLVND OpenGL and GLX libraries are available, prefer them.
This forces ``OPENGL_gl_LIBRARY`` to be empty.
- This is the default if components were requested (since components
- correspond to GLVND libraries) or if policy :policy:`CMP0072` is
- set to ``NEW``.
+
+ .. versionchanged:: 3.11
+ This is the default, unless policy :policy:`CMP0072` is set to ``OLD``
+ and no components are requeted (since components
+ correspond to GLVND libraries).
``LEGACY``
Prefer to use the legacy libGL library, if available.
- This is the default if no components were requested and
- policy :policy:`CMP0072` is not set to ``NEW``.
For EGL targets the client must rely on GLVND support on the user's system.
Linking should use the ``OpenGL::OpenGL OpenGL::EGL`` targets. Using GLES*
@@ -443,7 +465,7 @@ if(OPENGL_FOUND)
# ::GLX is a GLVND library, and thus Linux-only: we don't bother checking
# for a framework version of this library.
- if(OpenGL_GLX_FOUND AND NOT TARGET OpenGL::GLX)
+ if(OpenGL_GLX_FOUND AND NOT TARGET OpenGL::GLX AND TARGET OpenGL::OpenGL)
if(IS_ABSOLUTE "${OPENGL_glx_LIBRARY}")
add_library(OpenGL::GLX UNKNOWN IMPORTED)
set_target_properties(OpenGL::GLX PROPERTIES IMPORTED_LOCATION
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index bb38e28e1..52330a497 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -13,11 +13,15 @@ OpenMP support are returned in variables for the different languages.
The variables may be empty if the compiler does not need a special
flag to support OpenMP.
+.. versionadded:: 3.5
+ Clang support.
+
Variables
^^^^^^^^^
-The module exposes the components ``C``, ``CXX``, and ``Fortran``.
-Each of these controls the various languages to search OpenMP support for.
+.. versionadded:: 3.10
+ The module exposes the components ``C``, ``CXX``, and ``Fortran``.
+ Each of these controls the various languages to search OpenMP support for.
Depending on the enabled components the following variables will be set:
@@ -65,6 +69,8 @@ Specifically for Fortran, the module sets the following variables:
The module will also try to provide the OpenMP version variables:
``OpenMP_<lang>_SPEC_DATE``
+ .. versionadded:: 3.7
+
Date of the OpenMP specification implemented by the ``<lang>`` compiler.
``OpenMP_<lang>_VERSION_MAJOR``
Major version of OpenMP implemented by the ``<lang>`` compiler.
@@ -107,10 +113,17 @@ function(_OPENMP_FLAG_CANDIDATES LANG)
else()
set(OMP_FLAG_Intel "-qopenmp")
endif()
+ if(CMAKE_${LANG}_COMPILER_ID STREQUAL "IntelLLVM" AND
+ "x${CMAKE_${LANG}_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ set(OMP_FLAG_IntelLLVM "-Qiopenmp")
+ else()
+ set(OMP_FLAG_IntelLLVM "-fiopenmp")
+ endif()
set(OMP_FLAG_MSVC "-openmp")
set(OMP_FLAG_PathScale "-openmp")
set(OMP_FLAG_NAG "-openmp")
set(OMP_FLAG_Absoft "-openmp")
+ set(OMP_FLAG_NVHPC "-mp")
set(OMP_FLAG_PGI "-mp")
set(OMP_FLAG_Flang "-fopenmp")
set(OMP_FLAG_SunPro "-xopenmp")
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 91a65fdda..b1afa5f40 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -7,15 +7,29 @@ FindOpenSSL
Find the OpenSSL encryption library.
+This module finds an installed OpenSSL library and determines its version.
+
+.. versionadded:: 3.19
+ When a version is requested, it can be specified as a simple value or as a
+ range. For a detailed description of version range usage and capabilities,
+ refer to the :command:`find_package` command.
+
+.. versionadded:: 3.18
+ Support for OpenSSL 3.0.
+
Optional COMPONENTS
^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.12
+
This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``. Both
components have associated imported targets, as described below.
Imported Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.4
+
This module defines the following :prop_tgt:`IMPORTED` targets:
``OpenSSL::SSL``
@@ -23,6 +37,8 @@ This module defines the following :prop_tgt:`IMPORTED` targets:
``OpenSSL::Crypto``
The OpenSSL ``crypto`` library, if found.
``OpenSSL::applink``
+ .. versionadded:: 3.18
+
The OpenSSL ``applink`` components that might be need to be compiled into
projects under MSVC. This target is available only if found OpenSSL version
is not less than 0.9.8. By linking this target the above OpenSSL targets can
@@ -75,8 +91,12 @@ Hints
^^^^^
Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
-Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
-Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
+
+.. versionadded:: 3.4
+ Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
+
+.. versionadded:: 3.5
+ Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
#]=======================================================================]
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
@@ -128,16 +148,30 @@ if (WIN32)
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
ENV OPENSSL_ROOT_DIR
)
- file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
+
+ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
+ set(_arch "Win64")
+ file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
+ else()
+ set(_arch "Win32")
+ set(_progfiles_x86 "ProgramFiles(x86)")
+ if(NOT "$ENV{${_progfiles_x86}}" STREQUAL "")
+ # under windows 64 bit machine
+ file(TO_CMAKE_PATH "$ENV{${_progfiles_x86}}" _programfiles)
+ else()
+ # under windows 32 bit machine
+ file(TO_CMAKE_PATH "$ENV{ProgramFiles}" _programfiles)
+ endif()
+ endif()
+
set(_OPENSSL_ROOT_PATHS
"${_programfiles}/OpenSSL"
- "${_programfiles}/OpenSSL-Win32"
- "${_programfiles}/OpenSSL-Win64"
+ "${_programfiles}/OpenSSL-${_arch}"
"C:/OpenSSL/"
- "C:/OpenSSL-Win32/"
- "C:/OpenSSL-Win64/"
+ "C:/OpenSSL-${_arch}/"
)
unset(_programfiles)
+ unset(_arch)
else ()
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
@@ -539,6 +573,7 @@ find_package_handle_standard_args(OpenSSL
OPENSSL_INCLUDE_DIR
VERSION_VAR
OPENSSL_VERSION
+ HANDLE_VERSION_RANGE
HANDLE_COMPONENTS
FAIL_MESSAGE
"Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
diff --git a/Modules/FindPNG.cmake b/Modules/FindPNG.cmake
index fd0e4e93e..94d15db5f 100644
--- a/Modules/FindPNG.cmake
+++ b/Modules/FindPNG.cmake
@@ -10,6 +10,8 @@ Find libpng, the official reference library for the PNG image format.
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.5
+
This module defines the following :prop_tgt:`IMPORTED` target:
``PNG::PNG``
@@ -53,6 +55,7 @@ find_package(ZLIB ${_FIND_ZLIB_ARG})
if(ZLIB_FOUND)
find_path(PNG_PNG_INCLUDE_DIR png.h PATH_SUFFIXES include/libpng)
+ mark_as_advanced(PNG_PNG_INCLUDE_DIR)
list(APPEND PNG_NAMES png libpng)
unset(PNG_NAMES_DEBUG)
@@ -156,5 +159,3 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(PNG
REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR
VERSION_VAR PNG_VERSION_STRING)
-
-mark_as_advanced(PNG_PNG_INCLUDE_DIR PNG_LIBRARY )
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index 7e172779e..fbcf7cd88 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -51,7 +51,9 @@ implementing :command:`find_package(<PackageName>)` calls.
(recommended). Not valid in the full signature.
``FOUND_VAR <result-var>``
- Obsolete. Specifies either ``<PackageName>_FOUND`` or
+ .. deprecated:: 3.3
+
+ Specifies either ``<PackageName>_FOUND`` or
``<PACKAGENAME>_FOUND`` as the result variable. This exists only
for compatibility with older versions of CMake and is now ignored.
Result variables of both names are always set for compatibility.
@@ -61,8 +63,10 @@ implementing :command:`find_package(<PackageName>)` calls.
These may be named in the generated failure message asking the
user to set the missing variable values. Therefore these should
typically be cache entries such as ``FOO_LIBRARY`` and not output
- variables like ``FOO_LIBRARIES``. This option is mandatory if
- ``HANDLE_COMPONENTS`` is not specified.
+ variables like ``FOO_LIBRARIES``.
+
+ .. versionchanged:: 3.18
+ If ``HANDLE_COMPONENTS`` is specified, this option can be omitted.
``VERSION_VAR <version-var>``
Specify the name of a variable that holds the version of the package
@@ -74,6 +78,8 @@ implementing :command:`find_package(<PackageName>)` calls.
if the version is ok or not.
``HANDLE_VERSION_RANGE``
+ .. versionadded:: 3.19
+
Enable handling of a version range, if one is specified. Without this
option, a developer warning will be displayed if a version range is
specified.
@@ -94,6 +100,8 @@ implementing :command:`find_package(<PackageName>)` calls.
was found.
``REASON_FAILURE_MESSAGE <reason-failure-message>``
+ .. versionadded:: 3.16
+
Specify a custom message of the reason for the failure which will be
appended to the default generated message.
@@ -102,6 +110,8 @@ implementing :command:`find_package(<PackageName>)` calls.
generated message. Not recommended.
``NAME_MISMATCHED``
+ .. versionadded:: 3.17
+
Indicate that the ``<PackageName>`` does not match
``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a
warning, but it may be intentional for usage of the command for components
@@ -163,6 +173,8 @@ message.
.. command:: find_package_check_version
+ .. versionadded:: 3.19
+
Helper function which can be used to check if a ``<version>`` is valid
against version-related arguments of :command:`find_package`.
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 360f43923..38c8da754 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -635,19 +635,38 @@ endmacro()
When the ``QUIET`` argument is given, no status messages will be printed.
- By default, if :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` is 3.1 or
- later, or if :variable:`PKG_CONFIG_USE_CMAKE_PREFIX_PATH` is set to a
- boolean ``True`` value, then the :variable:`CMAKE_PREFIX_PATH`,
- :variable:`CMAKE_FRAMEWORK_PATH`, and :variable:`CMAKE_APPBUNDLE_PATH` cache
- and environment variables will be added to the ``pkg-config`` search path.
- The ``NO_CMAKE_PATH`` and ``NO_CMAKE_ENVIRONMENT_PATH`` arguments
- disable this behavior for the cache variables and environment variables
- respectively.
-
- The ``IMPORTED_TARGET`` argument will create an imported target named
- ``PkgConfig::<prefix>`` that can be passed directly as an argument to
- :command:`target_link_libraries`. The ``GLOBAL`` argument will make the
- imported target available in global scope.
+ .. versionadded:: 3.1
+ The :variable:`CMAKE_PREFIX_PATH`,
+ :variable:`CMAKE_FRAMEWORK_PATH`, and :variable:`CMAKE_APPBUNDLE_PATH` cache
+ and environment variables will be added to the ``pkg-config`` search path.
+ The ``NO_CMAKE_PATH`` and ``NO_CMAKE_ENVIRONMENT_PATH`` arguments
+ disable this behavior for the cache variables and environment variables
+ respectively.
+ The :variable:`PKG_CONFIG_USE_CMAKE_PREFIX_PATH` variable set to ``FALSE``
+ disables this behavior globally.
+
+ .. This didn't actually work until 3.3.
+
+ .. versionadded:: 3.6
+ The ``IMPORTED_TARGET`` argument will create an imported target named
+ ``PkgConfig::<prefix>`` that can be passed directly as an argument to
+ :command:`target_link_libraries`.
+
+ .. This didn't actually work until 3.7.
+
+ .. versionadded:: 3.13
+ The ``GLOBAL`` argument will make the
+ imported target available in global scope.
+
+ .. versionadded:: 3.15
+ Non-library linker options reported by ``pkg-config`` are stored in the
+ :prop_tgt:`INTERFACE_LINK_OPTIONS` target property.
+
+ .. versionchanged:: 3.18
+ Include directories specified with ``-isystem`` are stored in the
+ :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target property. Previous
+ versions of CMake left them in the :prop_tgt:`INTERFACE_COMPILE_OPTIONS`
+ property.
Each ``<moduleSpec>`` can be either a bare module name or it can be a
module name with a version constraint (operators ``=``, ``<``, ``>``,
@@ -686,6 +705,11 @@ endmacro()
All but ``<XXX>_FOUND`` may be a :ref:`;-list <CMake Language Lists>` if the
associated variable returned from ``pkg-config`` has multiple values.
+ .. versionchanged:: 3.18
+ Include directories specified with ``-isystem`` are stored in the
+ ``<XXX>_INCLUDE_DIRS`` variable. Previous versions of CMake left them
+ in ``<XXX>_CFLAGS_OTHER``.
+
There are some special variables whose prefix depends on the number of
``<moduleSpec>`` given. When there is only one ``<moduleSpec>``,
``<YYY>`` will simply be ``<prefix>``, but if two or more ``<moduleSpec>``
@@ -700,6 +724,16 @@ endmacro()
``<YYY>_LIBDIR``
lib directory of the module
+ .. versionchanged:: 3.8
+ For any given ``<prefix>``, ``pkg_check_modules()`` can be called multiple
+ times with different parameters. Previous versions of CMake cached and
+ returned the first successful result.
+
+ .. versionchanged:: 3.16
+ If a full path to the found library can't be determined, but it's still
+ visible to the linker, pass it through as ``-l<name>``. Previous versions
+ of CMake failed in this case.
+
Examples:
.. code-block:: cmake
@@ -771,9 +805,10 @@ endmacro()
[IMPORTED_TARGET [GLOBAL]]
<moduleSpec> [<moduleSpec>...])
- If a module is found, the ``<prefix>_MODULE_NAME`` variable will contain the
- name of the matching module. This variable can be used if you need to run
- :command:`pkg_get_variable`.
+ .. versionadded:: 3.16
+ If a module is found, the ``<prefix>_MODULE_NAME`` variable will contain the
+ name of the matching module. This variable can be used if you need to run
+ :command:`pkg_get_variable`.
Example:
@@ -818,6 +853,8 @@ endmacro()
#[========================================[.rst:
.. command:: pkg_get_variable
+ .. versionadded:: 3.4
+
Retrieves the value of a pkg-config variable ``varName`` and stores it in the
result variable ``resultVar`` in the calling scope.
@@ -852,10 +889,15 @@ Variables Affecting Behavior
This can be set to the path of the pkg-config executable. If not provided,
it will be set by the module as a result of calling :command:`find_program`
- internally. The ``PKG_CONFIG`` environment variable can be used as a hint.
+ internally.
+
+ .. versionadded:: 3.1
+ The ``PKG_CONFIG`` environment variable can be used as a hint.
.. variable:: PKG_CONFIG_USE_CMAKE_PREFIX_PATH
+ .. versionadded:: 3.1
+
Specifies whether :command:`pkg_check_modules` and
:command:`pkg_search_module` should add the paths in the
:variable:`CMAKE_PREFIX_PATH`, :variable:`CMAKE_FRAMEWORK_PATH` and
diff --git a/Modules/FindPostgreSQL.cmake b/Modules/FindPostgreSQL.cmake
index 1970b26a3..147071a0f 100644
--- a/Modules/FindPostgreSQL.cmake
+++ b/Modules/FindPostgreSQL.cmake
@@ -10,6 +10,8 @@ Find the PostgreSQL installation.
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.14
+
This module defines :prop_tgt:`IMPORTED` target ``PostgreSQL::PostgreSQL``
if PostgreSQL has been found.
@@ -28,6 +30,16 @@ This module will set the following variables in your project:
the link directories for PostgreSQL libraries
``PostgreSQL_VERSION_STRING``
the version of PostgreSQL found
+``PostgreSQL_TYPE_INCLUDE_DIR``
+ the directories of the PostgreSQL server headers
+
+Components
+^^^^^^^^^^
+
+This module contains additional ``Server`` component, that forcibly checks
+for the presence of server headers. Note that ``PostgreSQL_TYPE_INCLUDE_DIR``
+is set regardless of the presence of the ``Server`` component in find_package call.
+
#]=======================================================================]
# ----------------------------------------------------------------------------
@@ -79,6 +91,9 @@ This module will set the following variables in your project:
#
# ----------------------------------------------------------------------------
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
set(PostgreSQL_INCLUDE_PATH_DESCRIPTION "top-level directory containing the PostgreSQL include directories. E.g /usr/local/include/PostgreSQL/8.4 or C:/Program Files/PostgreSQL/8.4/include")
set(PostgreSQL_INCLUDE_DIR_MESSAGE "Set the PostgreSQL_INCLUDE_DIR cmake cache entry to the ${PostgreSQL_INCLUDE_PATH_DESCRIPTION}")
set(PostgreSQL_LIBRARY_PATH_DESCRIPTION "top-level directory containing the PostgreSQL libraries.")
@@ -242,10 +257,18 @@ if (PostgreSQL_INCLUDE_DIR)
unset(pgsql_version_str)
endif()
+if("Server" IN_LIST PostgreSQL_FIND_COMPONENTS)
+ set(PostgreSQL_Server_FOUND TRUE)
+ if(NOT PostgreSQL_TYPE_INCLUDE_DIR)
+ set(PostgreSQL_Server_FOUND FALSE)
+ endif()
+endif()
+
# Did we find anything?
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(PostgreSQL
- REQUIRED_VARS PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR
+ REQUIRED_VARS PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR
+ HANDLE_COMPONENTS
VERSION_VAR PostgreSQL_VERSION_STRING)
set(PostgreSQL_FOUND ${POSTGRESQL_FOUND})
@@ -269,16 +292,21 @@ endfunction()
# Now try to get the include and library path.
if(PostgreSQL_FOUND)
+ set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR})
+ if(PostgreSQL_TYPE_INCLUDE_DIR)
+ list(APPEND PostgreSQL_INCLUDE_DIRS ${PostgreSQL_TYPE_INCLUDE_DIR})
+ endif()
+ set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR})
if (NOT TARGET PostgreSQL::PostgreSQL)
add_library(PostgreSQL::PostgreSQL UNKNOWN IMPORTED)
set_target_properties(PostgreSQL::PostgreSQL PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES "${PostgreSQL_INCLUDE_DIR};${PostgreSQL_TYPE_INCLUDE_DIR}")
+ INTERFACE_INCLUDE_DIRECTORIES "${PostgreSQL_INCLUDE_DIRS}")
__postgresql_import_library(PostgreSQL::PostgreSQL PostgreSQL_LIBRARY "")
__postgresql_import_library(PostgreSQL::PostgreSQL PostgreSQL_LIBRARY "RELEASE")
__postgresql_import_library(PostgreSQL::PostgreSQL PostgreSQL_LIBRARY "DEBUG")
endif ()
- set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR} ${PostgreSQL_TYPE_INCLUDE_DIR} )
- set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR} )
endif()
mark_as_advanced(PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR)
+
+cmake_policy(POP)
diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake
index 4bf54efe3..4b1e33689 100644
--- a/Modules/FindProtobuf.cmake
+++ b/Modules/FindProtobuf.cmake
@@ -7,6 +7,13 @@ FindProtobuf
Locate and configure the Google Protocol Buffers library.
+.. versionadded:: 3.6
+ Support for :command:`find_package` version checks.
+
+.. versionchanged:: 3.6
+ All input and output variables use the ``Protobuf_`` prefix.
+ Variables with ``PROTOBUF_`` prefix are still supported for compatibility.
+
The following variables can be set and are optional:
``Protobuf_SRC_ROOT_FOLDER``
@@ -19,8 +26,12 @@ The following variables can be set and are optional:
List of additional directories to be searched for
imported .proto files.
``Protobuf_DEBUG``
+ .. versionadded:: 3.6
+
Show debug messages.
``Protobuf_USE_STATIC_LIBS``
+ .. versionadded:: 3.9
+
Set to ON to force the use of the static libraries.
Default is OFF.
@@ -30,6 +41,8 @@ Defines the following variables:
Found the Google Protocol Buffers library
(libprotobuf & header files)
``Protobuf_VERSION``
+ .. versionadded:: 3.6
+
Version of package found.
``Protobuf_INCLUDE_DIRS``
Include directories for Google Protocol Buffers
@@ -40,7 +53,8 @@ Defines the following variables:
``Protobuf_LITE_LIBRARIES``
The protobuf-lite libraries
-The following :prop_tgt:`IMPORTED` targets are also defined:
+.. versionadded:: 3.9
+ The following :prop_tgt:`IMPORTED` targets are also defined:
``protobuf::libprotobuf``
The protobuf library.
@@ -49,7 +63,8 @@ The following :prop_tgt:`IMPORTED` targets are also defined:
``protobuf::libprotoc``
The protoc library.
``protobuf::protoc``
- The protoc compiler.
+ .. versionadded:: 3.10
+ The protoc compiler.
The following cache variables are also available to set or use:
@@ -101,7 +116,8 @@ Example:
``HDRS``
Variable to define with autogenerated header files
``DESCRIPTORS``
- Variable to define with autogenerated descriptor files, if requested.
+ .. versionadded:: 3.10
+ Variable to define with autogenerated descriptor files, if requested.
``EXPORT_MACRO``
is a macro which should expand to ``__declspec(dllexport)`` or
``__declspec(dllimport)`` depending on what is being compiled.
@@ -110,6 +126,8 @@ Example:
.. command:: protobuf_generate_python
+ .. versionadded:: 3.4
+
Add custom commands to process ``.proto`` files to Python::
protobuf_generate_python (<PY> [<ARGN>...])
@@ -204,7 +222,7 @@ function(protobuf_generate)
foreach(_proto ${protobuf_generate_PROTOS})
get_filename_component(_abs_file ${_proto} ABSOLUTE)
get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
- get_filename_component(_basename ${_proto} NAME_WE)
+ get_filename_component(_basename ${_proto} NAME_WLE)
file(RELATIVE_PATH _rel_dir ${CMAKE_CURRENT_SOURCE_DIR} ${_abs_dir})
set(_possible_rel_dir)
diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake
index 5fc6a3b21..a4b7a0385 100644
--- a/Modules/FindPython.cmake
+++ b/Modules/FindPython.cmake
@@ -10,25 +10,32 @@ FindPython
Find Python interpreter, compiler and development environment (include
directories and libraries).
-When a version is requested, it can be specified as a simple value or as a
-range. For a detailed description of version range usage and capabilities,
-refer to the :command:`find_package` command.
+.. versionadded:: 3.19
+ When a version is requested, it can be specified as a simple value or as a
+ range. For a detailed description of version range usage and capabilities,
+ refer to the :command:`find_package` command.
The following components are supported:
* ``Interpreter``: search for Python interpreter.
* ``Compiler``: search for Python compiler. Only offered by IronPython.
* ``Development``: search for development artifacts (include directories and
- libraries). This component includes two sub-components which can be specified
- independently:
+ libraries).
- * ``Development.Module``: search for artifacts for Python module
- developments.
- * ``Development.Embed``: search for artifacts for Python embedding
- developments.
+ .. versionadded:: 3.18
+ This component includes two sub-components which can be specified
+ independently:
+
+ * ``Development.Module``: search for artifacts for Python module
+ developments.
+ * ``Development.Embed``: search for artifacts for Python embedding
+ developments.
* ``NumPy``: search for NumPy include directories.
+.. versionadded:: 3.14
+ Added the ``NumPy`` component.
+
If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
If component ``Development`` is specified, it implies sub-components
@@ -56,20 +63,30 @@ To manage concurrent versions 3 and 2 of Python, use :module:`FindPython3` and
Imported Targets
^^^^^^^^^^^^^^^^
-This module defines the following :ref:`Imported Targets <Imported Targets>`
-(when :prop_gbl:`CMAKE_ROLE` is ``PROJECT``):
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+.. versionchanged:: 3.14
+ :ref:`Imported Targets <Imported Targets>` are only created when
+ :prop_gbl:`CMAKE_ROLE` is ``PROJECT``.
``Python::Interpreter``
Python interpreter. Target defined if component ``Interpreter`` is found.
``Python::Compiler``
Python compiler. Target defined if component ``Compiler`` is found.
+
``Python::Module``
+ .. versionadded:: 3.15
+
Python library for Python module. Target defined if component
``Development.Module`` is found.
+
``Python::Python``
Python library for Python embedding. Target defined if component
``Development.Embed`` is found.
+
``Python::NumPy``
+ .. versionadded:: 3.14
+
NumPy Python library. Target defined if component ``NumPy`` is found.
Result Variables
@@ -116,7 +133,10 @@ This module will set the following variables in your project
Information returned by
``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``
or else ``sysconfig.get_path('platlib')``.
+
``Python_SOABI``
+ .. versionadded:: 3.17
+
Extension suffix for modules.
Information returned by
@@ -125,6 +145,7 @@ This module will set the following variables in your project
``python-config --extension-suffix``. If package ``distutils.sysconfig`` is
not available, ``sysconfig.get_config_var('SOABI')`` or
``sysconfig.get_config_var('EXT_SUFFIX')`` are used.
+
``Python_Compiler_FOUND``
System has the Python compiler.
``Python_COMPILER``
@@ -132,19 +153,35 @@ This module will set the following variables in your project
``Python_COMPILER_ID``
A short string unique to the compiler. Possible values include:
* IronPython
+
``Python_DOTNET_LAUNCHER``
+ .. versionadded:: 3.18
+
The ``.Net`` interpreter. Only used by ``IronPython`` implementation.
+
``Python_Development_FOUND``
System has the Python development artifacts.
+
``Python_Development.Module_FOUND``
+ .. versionadded:: 3.18
+
System has the Python development artifacts for Python module.
+
``Python_Development.Embed_FOUND``
+ .. versionadded:: 3.18
+
System has the Python development artifacts for Python embedding.
+
``Python_INCLUDE_DIRS``
+
The Python include directories.
+
``Python_LINK_OPTIONS``
+ .. versionadded:: 3.19
+
The Python link options. Some configurations require specific link options
for a correct build and execution.
+
``Python_LIBRARIES``
The Python libraries.
``Python_LIBRARY_DIRS``
@@ -159,13 +196,25 @@ This module will set the following variables in your project
Python minor version.
``Python_VERSION_PATCH``
Python patch version.
+
``Python_PyPy_VERSION``
+ .. versionadded:: 3.18
+
Python PyPy version.
+
``Python_NumPy_FOUND``
+ .. versionadded:: 3.14
+
System has the NumPy.
+
``Python_NumPy_INCLUDE_DIRS``
+ .. versionadded:: 3.14
+
The NumPy include directories.
+
``Python_NumPy_VERSION``
+ .. versionadded:: 3.14
+
The NumPy version.
Hints
@@ -181,6 +230,8 @@ Hints
* If set to FALSE, search **only** for shared libraries.
``Python_FIND_ABI``
+ .. versionadded:: 3.16
+
This variable defines which ABIs, as defined in
`PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched.
@@ -226,6 +277,8 @@ Hints
each flag is ``OFF`` or ``ANY``.
``Python_FIND_STRATEGY``
+ .. versionadded:: 3.15
+
This variable defines how lookup will be done.
The ``Python_FIND_STRATEGY`` variable can be set to one of the following:
@@ -238,6 +291,8 @@ Hints
This is the default if policy :policy:`CMP0094` is set to ``NEW``.
``Python_FIND_REGISTRY``
+ .. versionadded:: 3.13
+
On Windows the ``Python_FIND_REGISTRY`` variable determine the order
of preference between registry and environment variables.
the ``Python_FIND_REGISTRY`` variable can be set to one of the following:
@@ -248,6 +303,8 @@ Hints
* ``NEVER``: Never try to use registry.
``Python_FIND_FRAMEWORK``
+ .. versionadded:: 3.15
+
On macOS the ``Python_FIND_FRAMEWORK`` variable determine the order of
preference between Apple-style and unix-style package components.
This variable can take same values as :variable:`CMAKE_FIND_FRAMEWORK`
@@ -261,6 +318,8 @@ Hints
variable will be used, if any.
``Python_FIND_VIRTUALENV``
+ .. versionadded:: 3.15
+
This variable defines the handling of virtual environments managed by
``virtualenv`` or ``conda``. It is meaningful only when a virtual environment
is active (i.e. the ``activate`` script has been evaluated). In this case, it
@@ -279,6 +338,9 @@ Hints
``NEVER`` to select preferably the interpreter from the virtual
environment.
+ .. versionadded:: 3.17
+ Added support for ``conda`` environments.
+
.. note::
If the component ``Development`` is requested, it is **strongly**
@@ -286,6 +348,8 @@ Hints
result.
``Python_FIND_IMPLEMENTATIONS``
+ .. versionadded:: 3.18
+
This variable defines, in an ordered list, the different implementations
which will be searched. The ``Python_FIND_IMPLEMENTATIONS`` variable can
hold the following values:
@@ -318,9 +382,26 @@ Hints
``.Net`` interpreter (i.e. ``mono`` command) is expected to be available
through the ``PATH`` variable.
+``Python_FIND_UNVERSIONED_NAMES``
+ .. versionadded:: 3.20
+
+ This variable defines how the generic names will be searched. Currently, it
+ only applies to the generic names of the interpreter, namely, ``python3`` or
+ ``python2`` and ``python``.
+ The ``Python_FIND_UNVERSIONED_NAMES`` variable can be set to one of the
+ following values:
+
+ * ``FIRST``: The generic names are searched before the more specialized ones
+ (such as ``python2.5`` for example).
+ * ``LAST``: The generic names are searched after the more specialized ones.
+ This is the default.
+ * ``NEVER``: The generic name are not searched at all.
+
Artifacts Specification
^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.16
+
To solve special cases, it is possible to specify directly the artifacts by
setting the following variables:
@@ -331,6 +412,8 @@ setting the following variables:
The path to the compiler.
``Python_DOTNET_LAUNCHER``
+ .. versionadded:: 3.18
+
The ``.Net`` interpreter. Only used by ``IronPython`` implementation.
``Python_LIBRARY``
@@ -367,6 +450,8 @@ specification. So, to enable also interactive specification, module behavior
can be controlled with the following variable:
``Python_ARTIFACTS_INTERACTIVE``
+ .. versionadded:: 3.18
+
Selects the behavior of the module. This is a boolean variable:
* If set to ``TRUE``: Create CMake cache entries for the above artifact
@@ -389,8 +474,9 @@ Python module naming rules::
If the library type is not specified, ``MODULE`` is assumed.
-For ``MODULE`` library type, if option ``WITH_SOABI`` is specified, the
-module suffix will include the ``Python_SOABI`` value, if any.
+.. versionadded:: 3.17
+ For ``MODULE`` library type, if option ``WITH_SOABI`` is specified, the
+ module suffix will include the ``Python_SOABI`` value, if any.
#]=======================================================================]
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index 8b2d73948..8e70e111b 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -337,6 +337,9 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
foreach (implementation IN LISTS _PGN_IMPLEMENTATIONS)
if (implementation STREQUAL "CPython")
+ if (_PGN_INTERPRETER AND _${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES STREQUAL "FIRST")
+ list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python)
+ endif()
foreach (version IN LISTS _PGN_VERSION)
if (_PGN_WIN32)
string (REPLACE "." "" version_no_dots ${version})
@@ -386,7 +389,7 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
endif()
endif()
endforeach()
- if (_PGN_INTERPRETER)
+ if (_PGN_INTERPRETER AND _${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES STREQUAL "LAST")
list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python)
endif()
elseif (implementation STREQUAL "IronPython")
@@ -1372,9 +1375,22 @@ else()
endif()
+# Python naming handling
+if (DEFINED ${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES)
+ if (NOT ${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES MATCHES "^(FIRST|LAST|NEVER)$")
+ message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${_${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES}: invalid value for '${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES'. 'FIRST', 'LAST' or 'NEVER' expected. 'LAST' will be used instead.")
+ set (_${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES LAST)
+ else()
+ set (_${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES ${${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES})
+ endif()
+else()
+ set (_${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES LAST)
+endif()
+
+
# Compute search signature
# This signature will be used to check validity of cached variables on new search
-set (_${_PYTHON_PREFIX}_SIGNATURE "${${_PYTHON_PREFIX}_ROOT_DIR}:${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS}:${_${_PYTHON_PREFIX}_FIND_STRATEGY}:${${_PYTHON_PREFIX}_FIND_VIRTUALENV}")
+set (_${_PYTHON_PREFIX}_SIGNATURE "${${_PYTHON_PREFIX}_ROOT_DIR}:${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS}:${_${_PYTHON_PREFIX}_FIND_STRATEGY}:${${_PYTHON_PREFIX}_FIND_VIRTUALENV}${_${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES}")
if (NOT WIN32)
string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_USE_STATIC_LIBS}:")
endif()
@@ -3005,8 +3021,9 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
unset(_${_PYTHON_PREFIX}_is_prefix)
foreach (_${_PYTHON_PREFIX}_implementation IN LISTS _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS)
foreach (_${_PYTHON_PREFIX}_framework IN LISTS _${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_implementation}_FRAMEWORKS)
- if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "^${_${_PYTHON_PREFIX}_framework}")
- get_filename_component (_${_PYTHON_PREFIX}_framework "${_${_PYTHON_PREFIX}_framework}" DIRECTORY)
+ cmake_path (IS_PREFIX _${_PYTHON_PREFIX}_framework "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" _${_PYTHON_PREFIX}_is_prefix)
+ if (_${_PYTHON_PREFIX}_is_prefix)
+ cmake_path (GET _${_PYTHON_PREFIX}_framework PARENT_PATH _${_PYTHON_PREFIX}_framework)
set (${_PYTHON_PREFIX}_LINK_OPTIONS "LINKER:-rpath,${_${_PYTHON_PREFIX}_framework}")
break()
endif()
diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake
index 9cd22e174..bb965b9d3 100644
--- a/Modules/FindPython2.cmake
+++ b/Modules/FindPython2.cmake
@@ -10,25 +10,32 @@ FindPython2
Find Python 2 interpreter, compiler and development environment (include
directories and libraries).
-When a version is requested, it can be specified as a simple value or as a
-range. For a detailed description of version range usage and capabilities,
-refer to the :command:`find_package` command.
+.. versionadded:: 3.19
+ When a version is requested, it can be specified as a simple value or as a
+ range. For a detailed description of version range usage and capabilities,
+ refer to the :command:`find_package` command.
The following components are supported:
* ``Interpreter``: search for Python 2 interpreter
* ``Compiler``: search for Python 2 compiler. Only offered by IronPython.
* ``Development``: search for development artifacts (include directories and
- libraries). This component includes two sub-components which can be specified
- independently:
+ libraries).
- * ``Development.Module``: search for artifacts for Python 2 module
- developments.
- * ``Development.Embed``: search for artifacts for Python 2 embedding
- developments.
+ .. versionadded:: 3.18
+ This component includes two sub-components which can be specified
+ independently:
+
+ * ``Development.Module``: search for artifacts for Python 2 module
+ developments.
+ * ``Development.Embed``: search for artifacts for Python 2 embedding
+ developments.
* ``NumPy``: search for NumPy include directories.
+.. versionadded:: 3.14
+ Added the ``NumPy`` component.
+
If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
If component ``Development`` is specified, it implies sub-components
@@ -57,20 +64,29 @@ for you.
Imported Targets
^^^^^^^^^^^^^^^^
-This module defines the following :ref:`Imported Targets <Imported Targets>`
-(when :prop_gbl:`CMAKE_ROLE` is ``PROJECT``):
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+.. versionchanged:: 3.14
+ :ref:`Imported Targets <Imported Targets>` are only created when
+ :prop_gbl:`CMAKE_ROLE` is ``PROJECT``.
``Python2::Interpreter``
Python 2 interpreter. Target defined if component ``Interpreter`` is found.
``Python2::Compiler``
Python 2 compiler. Target defined if component ``Compiler`` is found.
``Python2::Module``
+ .. versionadded:: 3.15
+
Python 2 library for Python module. Target defined if component
``Development.Module`` is found.
+
``Python2::Python``
Python 2 library for Python embedding. Target defined if component
``Development.Embed`` is found.
+
``Python2::NumPy``
+ .. versionadded:: 3.14
+
NumPy library for Python 2. Target defined if component ``NumPy`` is found.
Result Variables
@@ -124,19 +140,34 @@ This module will set the following variables in your project
``Python2_COMPILER_ID``
A short string unique to the compiler. Possible values include:
* IronPython
+
``Python2_DOTNET_LAUNCHER``
+ .. versionadded:: 3.18
+
The ``.Net`` interpreter. Only used by ``IronPython`` implementation.
+
``Python2_Development_FOUND``
System has the Python 2 development artifacts.
+
``Python2_Development.Module_FOUND``
+ .. versionadded:: 3.18
+
System has the Python 2 development artifacts for Python module.
+
``Python2_Development.Embed_FOUND``
+ .. versionadded:: 3.18
+
System has the Python 2 development artifacts for Python embedding.
+
``Python2_INCLUDE_DIRS``
The Python 2 include directories.
+
``Python2_LINK_OPTIONS``
+ .. versionadded:: 3.19
+
The Python 2 link options. Some configurations require specific link options
for a correct build and execution.
+
``Python2_LIBRARIES``
The Python 2 libraries.
``Python2_LIBRARY_DIRS``
@@ -151,13 +182,25 @@ This module will set the following variables in your project
Python 2 minor version.
``Python2_VERSION_PATCH``
Python 2 patch version.
+
``Python2_PyPy_VERSION``
+ .. versionadded:: 3.18
+
Python 2 PyPy version.
+
``Python2_NumPy_FOUND``
+ .. versionadded:: 3.14
+
System has the NumPy.
+
``Python2_NumPy_INCLUDE_DIRS``
+ .. versionadded:: 3.14
+
The NumPy include directories.
+
``Python2_NumPy_VERSION``
+ .. versionadded:: 3.14
+
The NumPy version.
Hints
@@ -173,6 +216,8 @@ Hints
* If set to FALSE, search **only** for shared libraries.
``Python2_FIND_STRATEGY``
+ .. versionadded:: 3.15
+
This variable defines how lookup will be done.
The ``Python2_FIND_STRATEGY`` variable can be set to one of the following:
@@ -185,6 +230,8 @@ Hints
This is the default if policy :policy:`CMP0094` is set to ``NEW``.
``Python2_FIND_REGISTRY``
+ .. versionadded:: 3.13
+
On Windows the ``Python2_FIND_REGISTRY`` variable determine the order
of preference between registry and environment variables.
the ``Python2_FIND_REGISTRY`` variable can be set to one of the following:
@@ -195,6 +242,8 @@ Hints
* ``NEVER``: Never try to use registry.
``Python2_FIND_FRAMEWORK``
+ .. versionadded:: 3.15
+
On macOS the ``Python2_FIND_FRAMEWORK`` variable determine the order of
preference between Apple-style and unix-style package components.
This variable can take same values as :variable:`CMAKE_FIND_FRAMEWORK`
@@ -208,6 +257,8 @@ Hints
variable will be used, if any.
``Python2_FIND_VIRTUALENV``
+ .. versionadded:: 3.15
+
This variable defines the handling of virtual environments managed by
``virtualenv`` or ``conda``. It is meaningful only when a virtual environment
is active (i.e. the ``activate`` script has been evaluated). In this case, it
@@ -226,6 +277,9 @@ Hints
``NEVER`` to select preferably the interpreter from the virtual
environment.
+ .. versionadded:: 3.17
+ Added support for ``conda`` environments.
+
.. note::
If the component ``Development`` is requested, it is **strongly**
@@ -233,6 +287,8 @@ Hints
result.
``Python2_FIND_IMPLEMENTATIONS``
+ .. versionadded:: 3.18
+
This variable defines, in an ordered list, the different implementations
which will be searched. The ``Python2_FIND_IMPLEMENTATIONS`` variable can
hold the following values:
@@ -265,9 +321,26 @@ Hints
``.Net`` interpreter (i.e. ``mono`` command) is expected to be available
through the ``PATH`` variable.
+``Python2_FIND_UNVERSIONED_NAMES``
+ .. versionadded:: 3.20
+
+ This variable defines how the generic names will be searched. Currently, it
+ only applies to the generic names of the interpreter, namely, ``python2`` and
+ ``python``.
+ The ``Python2_FIND_UNVERSIONED_NAMES`` variable can be set to one of the
+ following values:
+
+ * ``FIRST``: The generic names are searched before the more specialized ones
+ (such as ``python2.5`` for example).
+ * ``LAST``: The generic names are searched after the more specialized ones.
+ This is the default.
+ * ``NEVER``: The generic name are not searched at all.
+
Artifacts Specification
^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.16
+
To solve special cases, it is possible to specify directly the artifacts by
setting the following variables:
@@ -278,6 +351,8 @@ setting the following variables:
The path to the compiler.
``Python2_DOTNET_LAUNCHER``
+ .. versionadded:: 3.18
+
The ``.Net`` interpreter. Only used by ``IronPython`` implementation.
``Python2_LIBRARY``
@@ -314,6 +389,8 @@ specification. So, to enable also interactive specification, module behavior
can be controlled with the following variable:
``Python2_ARTIFACTS_INTERACTIVE``
+ .. versionadded:: 3.18
+
Selects the behavior of the module. This is a boolean variable:
* If set to ``TRUE``: Create CMake cache entries for the above artifact
diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake
index c79d482dd..f826fcfe2 100644
--- a/Modules/FindPython3.cmake
+++ b/Modules/FindPython3.cmake
@@ -10,25 +10,32 @@ FindPython3
Find Python 3 interpreter, compiler and development environment (include
directories and libraries).
-When a version is requested, it can be specified as a simple value or as a
-range. For a detailed description of version range usage and capabilities,
-refer to the :command:`find_package` command.
+.. versionadded:: 3.19
+ When a version is requested, it can be specified as a simple value or as a
+ range. For a detailed description of version range usage and capabilities,
+ refer to the :command:`find_package` command.
The following components are supported:
* ``Interpreter``: search for Python 3 interpreter
* ``Compiler``: search for Python 3 compiler. Only offered by IronPython.
* ``Development``: search for development artifacts (include directories and
- libraries). This component includes two sub-components which can be specified
- independently:
+ libraries).
- * ``Development.Module``: search for artifacts for Python 3 module
- developments.
- * ``Development.Embed``: search for artifacts for Python 3 embedding
- developments.
+ .. versionadded:: 3.18
+ This component includes two sub-components which can be specified
+ independently:
+
+ * ``Development.Module``: search for artifacts for Python 3 module
+ developments.
+ * ``Development.Embed``: search for artifacts for Python 3 embedding
+ developments.
* ``NumPy``: search for NumPy include directories.
+.. versionadded:: 3.14
+ Added the ``NumPy`` component.
+
If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
If component ``Development`` is specified, it implies sub-components
@@ -57,20 +64,30 @@ for you.
Imported Targets
^^^^^^^^^^^^^^^^
-This module defines the following :ref:`Imported Targets <Imported Targets>`
-(when :prop_gbl:`CMAKE_ROLE` is ``PROJECT``):
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+.. versionchanged:: 3.14
+ :ref:`Imported Targets <Imported Targets>` are only created when
+ :prop_gbl:`CMAKE_ROLE` is ``PROJECT``.
``Python3::Interpreter``
Python 3 interpreter. Target defined if component ``Interpreter`` is found.
``Python3::Compiler``
Python 3 compiler. Target defined if component ``Compiler`` is found.
+
``Python3::Module``
+ .. versionadded:: 3.15
+
Python 3 library for Python module. Target defined if component
``Development.Module`` is found.
+
``Python3::Python``
Python 3 library for Python embedding. Target defined if component
``Development.Embed`` is found.
+
``Python3::NumPy``
+ .. versionadded:: 3.14
+
NumPy library for Python 3. Target defined if component ``NumPy`` is found.
Result Variables
@@ -117,7 +134,10 @@ This module will set the following variables in your project
Information returned by
``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``
or else ``sysconfig.get_path('platlib')``.
+
``Python3_SOABI``
+ .. versionadded:: 3.17
+
Extension suffix for modules.
Information returned by
@@ -126,6 +146,7 @@ This module will set the following variables in your project
``python3-config --extension-suffix``. If package ``distutils.sysconfig`` is
not available, ``sysconfig.get_config_var('SOABI')`` or
``sysconfig.get_config_var('EXT_SUFFIX')`` are used.
+
``Python3_Compiler_FOUND``
System has the Python 3 compiler.
``Python3_COMPILER``
@@ -133,19 +154,36 @@ This module will set the following variables in your project
``Python3_COMPILER_ID``
A short string unique to the compiler. Possible values include:
* IronPython
+
``Python3_DOTNET_LAUNCHER``
+ .. versionadded:: 3.18
+
The ``.Net`` interpreter. Only used by ``IronPython`` implementation.
+
``Python3_Development_FOUND``
+
System has the Python 3 development artifacts.
+
``Python3_Development.Module_FOUND``
+ .. versionadded:: 3.18
+
System has the Python 3 development artifacts for Python module.
+
``Python3_Development.Embed_FOUND``
+ .. versionadded:: 3.18
+
System has the Python 3 development artifacts for Python embedding.
+
``Python3_INCLUDE_DIRS``
+
The Python 3 include directories.
+
``Python3_LINK_OPTIONS``
+ .. versionadded:: 3.19
+
The Python 3 link options. Some configurations require specific link options
for a correct build and execution.
+
``Python3_LIBRARIES``
The Python 3 libraries.
``Python3_LIBRARY_DIRS``
@@ -160,13 +198,25 @@ This module will set the following variables in your project
Python 3 minor version.
``Python3_VERSION_PATCH``
Python 3 patch version.
+
``Python3_PyPy_VERSION``
+ .. versionadded:: 3.18
+
Python 3 PyPy version.
+
``Python3_NumPy_FOUND``
+ .. versionadded:: 3.14
+
System has the NumPy.
+
``Python3_NumPy_INCLUDE_DIRS``
+ .. versionadded:: 3.14
+
The NumPy include directories.
+
``Python3_NumPy_VERSION``
+ .. versionadded:: 3.14
+
The NumPy version.
Hints
@@ -182,6 +232,8 @@ Hints
* If set to FALSE, search **only** for shared libraries.
``Python3_FIND_ABI``
+ .. versionadded:: 3.16
+
This variable defines which ABIs, as defined in
`PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched.
@@ -223,6 +275,8 @@ Hints
each flag is ``OFF`` or ``ANY``.
``Python3_FIND_STRATEGY``
+ .. versionadded:: 3.15
+
This variable defines how lookup will be done.
The ``Python3_FIND_STRATEGY`` variable can be set to one of the following:
@@ -235,6 +289,8 @@ Hints
This is the default if policy :policy:`CMP0094` is set to ``NEW``.
``Python3_FIND_REGISTRY``
+ .. versionadded:: 3.13
+
On Windows the ``Python3_FIND_REGISTRY`` variable determine the order
of preference between registry and environment variables.
The ``Python3_FIND_REGISTRY`` variable can be set to one of the following:
@@ -245,6 +301,8 @@ Hints
* ``NEVER``: Never try to use registry.
``Python3_FIND_FRAMEWORK``
+ .. versionadded:: 3.15
+
On macOS the ``Python3_FIND_FRAMEWORK`` variable determine the order of
preference between Apple-style and unix-style package components.
This variable can take same values as :variable:`CMAKE_FIND_FRAMEWORK`
@@ -258,6 +316,8 @@ Hints
variable will be used, if any.
``Python3_FIND_VIRTUALENV``
+ .. versionadded:: 3.15
+
This variable defines the handling of virtual environments managed by
``virtualenv`` or ``conda``. It is meaningful only when a virtual environment
is active (i.e. the ``activate`` script has been evaluated). In this case, it
@@ -276,6 +336,9 @@ Hints
``NEVER`` to select preferably the interpreter from the virtual
environment.
+ .. versionadded:: 3.17
+ Added support for ``conda`` environments.
+
.. note::
If the component ``Development`` is requested, it is **strongly**
@@ -283,6 +346,8 @@ Hints
result.
``Python3_FIND_IMPLEMENTATIONS``
+ .. versionadded:: 3.18
+
This variable defines, in an ordered list, the different implementations
which will be searched. The ``Python3_FIND_IMPLEMENTATIONS`` variable can
hold the following values:
@@ -315,9 +380,26 @@ Hints
``.Net`` interpreter (i.e. ``mono`` command) is expected to be available
through the ``PATH`` variable.
+``Python3_FIND_UNVERSIONED_NAMES``
+ .. versionadded:: 3.20
+
+ This variable defines how the generic names will be searched. Currently, it
+ only applies to the generic names of the interpreter, namely, ``python3`` and
+ ``python``.
+ The ``Python3_FIND_UNVERSIONED_NAMES`` variable can be set to one of the
+ following values:
+
+ * ``FIRST``: The generic names are searched before the more specialized ones
+ (such as ``python3.5`` for example).
+ * ``LAST``: The generic names are searched after the more specialized ones.
+ This is the default.
+ * ``NEVER``: The generic name are not searched at all.
+
Artifacts Specification
^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.16
+
To solve special cases, it is possible to specify directly the artifacts by
setting the following variables:
@@ -328,6 +410,8 @@ setting the following variables:
The path to the compiler.
``Python3_DOTNET_LAUNCHER``
+ .. versionadded:: 3.18
+
The ``.Net`` interpreter. Only used by ``IronPython`` implementation.
``Python3_LIBRARY``
@@ -364,6 +448,8 @@ specification. So, to enable also interactive specification, module behavior
can be controlled with the following variable:
``Python3_ARTIFACTS_INTERACTIVE``
+ .. versionadded:: 3.18
+
Selects the behavior of the module. This is a boolean variable:
* If set to ``TRUE``: Create CMake cache entries for the above artifact
@@ -386,8 +472,9 @@ of Python module naming rules::
If the library type is not specified, ``MODULE`` is assumed.
-For ``MODULE`` library type, if option ``WITH_SOABI`` is specified, the
-module suffix will include the ``Python3_SOABI`` value, if any.
+.. versionadded:: 3.17
+ For ``MODULE`` library type, if option ``WITH_SOABI`` is specified, the
+ module suffix will include the ``Python3_SOABI`` value, if any.
#]=======================================================================]
diff --git a/Modules/FindQt.cmake b/Modules/FindQt.cmake
index d6a06628e..44a1f414c 100644
--- a/Modules/FindQt.cmake
+++ b/Modules/FindQt.cmake
@@ -5,14 +5,14 @@
FindQt
------
+.. deprecated:: 3.14
+ This module is available only if policy :policy:`CMP0084` is not set to ``NEW``.
+
Searches for all installed versions of Qt3 or Qt4.
This module cannot handle Qt5 or any later versions.
For those, see :manual:`cmake-qt(7)`.
-This module exists for the :command:`find_package` command only if
-policy :policy:`CMP0084` is not set to ``NEW``.
-
This module should only be used if your project can work with multiple
versions of Qt. If not, you should just directly use FindQt4 or
FindQt3. If multiple versions of Qt are found on the machine, then
diff --git a/Modules/FindQt3.cmake b/Modules/FindQt3.cmake
index b5bc8b1cf..da82e5929 100644
--- a/Modules/FindQt3.cmake
+++ b/Modules/FindQt3.cmake
@@ -56,7 +56,9 @@ file(GLOB GLOB_PATHS /usr/lib/qt-3*)
foreach(GLOB_PATH ${GLOB_PATHS})
list(APPEND GLOB_PATHS_BIN "${GLOB_PATH}/bin")
endforeach()
-find_path(QT_INCLUDE_DIR qt.h
+find_path(QT_INCLUDE_DIR
+ NAMES qt.h
+ PATHS
"[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.2.1;InstallDir]/include/Qt"
"[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.2.0;InstallDir]/include/Qt"
"[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.1.0;InstallDir]/include/Qt"
@@ -179,7 +181,8 @@ if(QT_UIC_EXECUTABLE)
endif()
if (WIN32)
- find_library(QT_QTMAIN_LIBRARY qtmain
+ find_library(QT_QTMAIN_LIBRARY
+ NAMES qtmain
HINTS
ENV QTDIR
"[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.2.1;InstallDir]"
diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake
index d12f8255d..ee07f8345 100644
--- a/Modules/FindRuby.cmake
+++ b/Modules/FindRuby.cmake
@@ -37,7 +37,8 @@ This module will set the following variables in your project:
``Ruby_INCLUDE_DIRS``
include dirs to be used when using the ruby library
``Ruby_LIBRARIES``
- libraries needed to use ruby from C.
+ .. versionadded:: 3.18
+ libraries needed to use ruby from C.
``Ruby_VERSION``
the version of ruby which was found, e.g. "1.8.7"
``Ruby_VERSION_MAJOR``
@@ -47,9 +48,10 @@ This module will set the following variables in your project:
``Ruby_VERSION_PATCH``
Ruby patch version.
-
-The following variables are also provided for compatibility reasons,
-don't use them in new code:
+.. versionchanged:: 3.18
+ Previous versions of CMake used the ``RUBY_`` prefix for all variables.
+ The following variables are provided for compatibility reasons,
+ don't use them in new code:
``RUBY_EXECUTABLE``
same as Ruby_EXECUTABLE.
@@ -67,6 +69,8 @@ don't use them in new code:
Hints
^^^^^
+.. versionadded:: 3.18
+
``Ruby_ROOT_DIR``
Define the root directory of a Ruby installation.
diff --git a/Modules/FindSDL.cmake b/Modules/FindSDL.cmake
index 59eddbbc9..c68e18d96 100644
--- a/Modules/FindSDL.cmake
+++ b/Modules/FindSDL.cmake
@@ -11,6 +11,8 @@ Locate the SDL library
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.19
+
This module defines the following :prop_tgt:`IMPORTED` target:
``SDL::SDL``
@@ -36,6 +38,10 @@ This module will set the following variables in your project:
``SDL_VERSION_PATCH``
SDL patch version
+.. versionadded:: 3.19
+ Added the ``SDL_INCLUDE_DIRS``, ``SDL_LIBRARIES`` and ``SDL_VERSION[_<PART>]``
+ variables.
+
Cache variables
^^^^^^^^^^^^^^^
@@ -63,6 +69,8 @@ This module responds to the flag:
Obsolete variables
^^^^^^^^^^^^^^^^^^
+.. deprecated:: 3.19
+
These variables are obsolete and provided for backwards compatibility:
``SDL_VERSION_STRING``
diff --git a/Modules/FindSWIG.cmake b/Modules/FindSWIG.cmake
index 87a389463..4c7ad89dc 100644
--- a/Modules/FindSWIG.cmake
+++ b/Modules/FindSWIG.cmake
@@ -7,14 +7,17 @@ FindSWIG
Find the Simplified Wrapper and Interface Generator (SWIG_) executable.
-This module finds an installed SWIG and determines its version. If a
-``COMPONENTS`` or ``OPTIONAL_COMPONENTS`` argument is given to the
-:command:`find_package` command, it will also determine supported target
-languages.
-
-When a version is requested, it can be specified as a simple value or as a
-range. For a detailed description of version range usage and capabilities,
-refer to the :command:`find_package` command.
+This module finds an installed SWIG and determines its version.
+
+.. versionadded:: 3.18
+ If a ``COMPONENTS`` or ``OPTIONAL_COMPONENTS`` argument is given to the
+ :command:`find_package` command, it will also determine supported target
+ languages.
+
+.. versionadded:: 3.19
+ When a version is requested, it can be specified as a simple value or as a
+ range. For a detailed description of version range usage and capabilities,
+ refer to the :command:`find_package` command.
The module defines the following variables:
diff --git a/Modules/FindSquish.cmake b/Modules/FindSquish.cmake
index 91d141008..9a17fdbaf 100644
--- a/Modules/FindSquish.cmake
+++ b/Modules/FindSquish.cmake
@@ -47,7 +47,8 @@ to cmake using Squish >= 4.x:
AUT targetName SUITE suiteName TEST squishTestName
[SETTINGSGROUP group] [PRE_COMMAND command] [POST_COMMAND command] )
-
+.. versionchanged:: 3.18
+ In previous CMake versions, this function was named ``squish_v4_add_test``.
The arguments have the following meaning:
diff --git a/Modules/FindSubversion.cmake b/Modules/FindSubversion.cmake
index 07cb770cf..7a9c440f6 100644
--- a/Modules/FindSubversion.cmake
+++ b/Modules/FindSubversion.cmake
@@ -31,9 +31,12 @@ If the command line client executable is found two macros are defined:
``Subversion_WC_INFO`` extracts information of a subversion working copy at a
given location. This macro defines the following variables if running
Subversion's ``info`` command on ``<dir>`` succeeds; otherwise a
-``SEND_ERROR`` message is generated. The error can be ignored by providing the
-``IGNORE_SVN_FAILURE`` option, which causes these variables to remain
-undefined.
+``SEND_ERROR`` message is generated.
+
+.. versionadded:: 3.13
+ The error can be ignored by providing the
+ ``IGNORE_SVN_FAILURE`` option, which causes these variables to remain
+ undefined.
::
diff --git a/Modules/FindTIFF.cmake b/Modules/FindTIFF.cmake
index 3b74c94f0..ed2657c4a 100644
--- a/Modules/FindTIFF.cmake
+++ b/Modules/FindTIFF.cmake
@@ -17,12 +17,16 @@ imported target, as described below.
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.5
+
This module defines the following :prop_tgt:`IMPORTED` targets:
``TIFF::TIFF``
The TIFF library, if found.
``TIFF::CXX``
+ .. versionadded:: 3.19
+
The C++ wrapper libtiffxx, if requested by the `COMPONENTS CXX` option,
if the compiler is not MSVC (which includes the C++ wrapper in libtiff),
and if found.
@@ -56,6 +60,9 @@ The following cache variables may also be set:
the path to the TIFFXX library for release configurations
``TIFFXX_LIBRARY_DEBUG``
the path to the TIFFXX library for debug configurations
+
+.. versionadded:: 3.4
+ Debug and Release variants are found separately.
#]=======================================================================]
cmake_policy(PUSH)
diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake
index e3e6591a3..87e88bc31 100644
--- a/Modules/FindThreads.cmake
+++ b/Modules/FindThreads.cmake
@@ -10,6 +10,8 @@ This module determines the thread library of the system.
Imported Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.1
+
This module defines the following :prop_tgt:`IMPORTED` target:
``Threads::Threads``
@@ -38,6 +40,8 @@ Variables Affecting Behavior
.. variable:: THREADS_PREFER_PTHREAD_FLAG
+ .. versionadded:: 3.1
+
If the use of the -pthread compiler and linker flag is preferred then
the caller can set this variable to TRUE. The compiler flag can only be
used with the imported target. Use of both the imported target as well
diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake
index 0ec60133c..ceb1921e9 100644
--- a/Modules/FindVulkan.cmake
+++ b/Modules/FindVulkan.cmake
@@ -16,8 +16,9 @@ IMPORTED Targets
This module defines :prop_tgt:`IMPORTED` target ``Vulkan::Vulkan``, if
Vulkan has been found.
-This module defines :prop_tgt:`IMPORTED` target ``Vulkan::glslc``, if
-Vulkan and the GLSLC SPIR-V compiler 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.
Result Variables
^^^^^^^^^^^^^^^^
@@ -37,6 +38,8 @@ The module will also define three cache variables::
Hints
^^^^^
+.. versionadded:: 3.18
+
The ``VULKAN_SDK`` environment variable optionally specifies the
location of the Vulkan SDK root directory for the given
architecture. It is typically set by sourcing the toplevel
diff --git a/Modules/FindX11.cmake b/Modules/FindX11.cmake
index a865597af..d480fc480 100644
--- a/Modules/FindX11.cmake
+++ b/Modules/FindX11.cmake
@@ -17,6 +17,9 @@ Try to find X11 on UNIX systems. The following values are defined
and also the following more fine grained variables and targets:
+.. versionadded:: 3.14
+ Imported targets.
+
::
X11_ICE_INCLUDE_PATH, X11_ICE_LIB, X11_ICE_FOUND, X11::ICE
@@ -62,6 +65,23 @@ and also the following more fine grained variables and targets:
X11_Xshape_INCLUDE_PATH, (in X11_Xext_LIB), X11_Xshape_FOUND
X11_XSync_INCLUDE_PATH, (in X11_Xext_LIB), X11_XSync_FOUND
X11_Xaw_INCLUDE_PATH, X11_Xaw_LIB X11_Xaw_FOUND X11::Xaw
+
+.. versionadded:: 3.14
+ Renamed ``Xxf86misc``, ``X11_Xxf86misc``, ``X11_Xxf86vm``, ``X11_xkbfile``,
+ ``X11_Xtst``, and ``X11_Xss`` libraries to match their file names.
+ Deprecated the ``X11_Xinput`` library. Old names are still available
+ for compatibility.
+
+.. versionadded:: 3.14
+ Added the ``X11_Xext_INCLUDE_PATH`` variable.
+
+.. versionadded:: 3.18
+ Added the ``xcb``, ``X11-xcb``, ``xcb-icccm``, ``xcb-xkb``, ``xkbcommon``,
+ and ``xkbcommon-X11`` libraries.
+
+.. versionadded:: 3.19
+ Added the ``Xaw``, ``xcb_util``, and ``xcb_xfixes`` libraries.
+
#]=======================================================================]
if (UNIX)
diff --git a/Modules/FindXercesC.cmake b/Modules/FindXercesC.cmake
index abe18c057..af1b0b438 100644
--- a/Modules/FindXercesC.cmake
+++ b/Modules/FindXercesC.cmake
@@ -12,6 +12,8 @@ Find the Apache Xerces-C++ validating XML parser headers and libraries.
Imported targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.5
+
This module defines the following :prop_tgt:`IMPORTED` targets:
``XercesC::XercesC``
@@ -40,6 +42,9 @@ The following cache variables may also be set:
the directory containing the Xerces headers
``XercesC_LIBRARY``
the Xerces library
+
+.. versionadded:: 3.4
+ Debug and Release variants are found separately.
#]=======================================================================]
# Written by Roger Leigh <rleigh@codelibre.net>
diff --git a/Modules/FindZLIB.cmake b/Modules/FindZLIB.cmake
index 79e2313d5..5778b031b 100644
--- a/Modules/FindZLIB.cmake
+++ b/Modules/FindZLIB.cmake
@@ -10,6 +10,8 @@ Find the native ZLIB includes and library.
IMPORTED Targets
^^^^^^^^^^^^^^^^
+.. versionadded:: 3.1
+
This module defines :prop_tgt:`IMPORTED` target ``ZLIB::ZLIB``, if
ZLIB has been found.
@@ -32,6 +34,9 @@ This module defines the following variables:
ZLIB_VERSION_PATCH - The patch version of zlib
ZLIB_VERSION_TWEAK - The tweak version of zlib
+.. versionadded:: 3.4
+ Debug and Release variants are found separately.
+
Backward Compatibility
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index eab09f157..63af9b68d 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -14,6 +14,12 @@ package:
find_package(wxWidgets COMPONENTS core base ... OPTIONAL_COMPONENTS net ...)
+.. versionadded:: 3.4
+ Support for :command:`find_package` version argument; ``webview`` component.
+
+.. versionadded:: 3.14
+ ``OPTIONAL_COMPONENTS`` support.
+
There are two search branches: a windows style and a unix style. For
windows, the following variables are searched for and set to defaults
in case of multiple choices. Change them if the defaults are not
@@ -82,6 +88,9 @@ and unix style:
"`wx-config --cxxflags`".
wxWidgets_USE_FILE - Convenience include file.
+.. versionadded:: 3.11
+ The following environment variables can be used as hints: ``WX_CONFIG``,
+ ``WXRC_CMD``.
Sample usage:
diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake
index 547346ba9..733c7232c 100644
--- a/Modules/FortranCInterface.cmake
+++ b/Modules/FortranCInterface.cmake
@@ -343,6 +343,13 @@ function(FortranCInterface_VERIFY)
set(_desc "Verifying Fortran/${lang} Compiler Compatibility")
message(CHECK_START "${_desc}")
+ cmake_policy(GET CMP0056 _FortranCInterface_CMP0056)
+ if(_FortranCInterface_CMP0056 STREQUAL "NEW")
+ set(_FortranCInterface_EXE_LINKER_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}")
+ else()
+ set(_FortranCInterface_EXE_LINKER_FLAGS "")
+ endif()
+
# Build a sample project which reports symbols.
set(CMAKE_TRY_COMPILE_CONFIGURATION Release)
try_compile(FortranCInterface_VERIFY_${lang}_COMPILED
@@ -358,6 +365,7 @@ function(FortranCInterface_VERIFY)
"-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}"
"-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE}"
"-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}"
+ ${_FortranCInterface_EXE_LINKER_FLAGS}
OUTPUT_VARIABLE _output)
file(WRITE "${FortranCInterface_BINARY_DIR}/Verify${lang}/output.txt" "${_output}")
diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake
index c75067b32..998faf1ec 100644
--- a/Modules/FortranCInterface/Detect.cmake
+++ b/Modules/FortranCInterface/Detect.cmake
@@ -26,6 +26,14 @@ unset(FortranCInterface_VERIFIED_CXX CACHE)
set(_result)
+cmake_policy(GET CMP0056 _FortranCInterface_CMP0056)
+if(_FortranCInterface_CMP0056 STREQUAL "NEW")
+ set(_FortranCInterface_EXE_LINKER_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}")
+else()
+ set(_FortranCInterface_EXE_LINKER_FLAGS "")
+endif()
+unset(_FortranCInterface_CMP0056)
+
# Build a sample project which reports symbols.
set(CMAKE_TRY_COMPILE_CONFIGURATION Release)
try_compile(FortranCInterface_COMPILED
@@ -38,9 +46,11 @@ try_compile(FortranCInterface_COMPILED
"-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}"
"-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}"
"-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}"
+ ${_FortranCInterface_EXE_LINKER_FLAGS}
OUTPUT_VARIABLE FortranCInterface_OUTPUT)
set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED})
unset(FortranCInterface_COMPILED CACHE)
+unset(_FortranCInterface_EXE_LINKER_FLAGS)
# Locate the sample project executable.
set(FortranCInterface_EXE)
diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake
index 13d067a2d..37869fbab 100644
--- a/Modules/GNUInstallDirs.cmake
+++ b/Modules/GNUInstallDirs.cmake
@@ -46,7 +46,8 @@ where ``<dir>`` is one of:
``LOCALSTATEDIR``
modifiable single-machine data (``var``)
``RUNSTATEDIR``
- run-time variable data (``LOCALSTATEDIR/run``)
+ .. versionadded:: 3.9
+ run-time variable data (``LOCALSTATEDIR/run``)
``LIBDIR``
object code libraries (``lib`` or ``lib64``
or ``lib/<multiarch-tuple>`` on Debian)
@@ -73,6 +74,8 @@ used and the value will appear in the cache for editing by the user.
Special Cases
^^^^^^^^^^^^^
+.. versionadded:: 3.4
+
The following values of :variable:`CMAKE_INSTALL_PREFIX` are special:
``/``
@@ -113,7 +116,9 @@ Macros
::
- GNUInstallDirs_get_absolute_install_dir(absvar var)
+ GNUInstallDirs_get_absolute_install_dir(absvar var dirname)
+
+ .. versionadded:: 3.7
Set the given variable ``absvar`` to the absolute path contained
within the variable ``var``. This is to allow the computation of an
@@ -121,7 +126,12 @@ Macros
above. While this macro is used to compute the various
``CMAKE_INSTALL_FULL_<dir>`` variables, it is exposed publicly to
allow users who create additional path variables to also compute
- absolute paths where necessary, using the same logic.
+ absolute paths where necessary, using the same logic. ``dirname`` is
+ the directory name to get, e.g. ``BINDIR``.
+
+ .. versionchanged:: 3.20
+ Added the ``<dirname>`` parameter. Previous versions of CMake passed
+ this value through the variable ``${dir}``.
#]=======================================================================]
cmake_policy(PUSH)
@@ -334,13 +344,25 @@ 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)
+ list(GET GGAID_extra_args 0 GGAID_dir)
+ else()
+ # Historical behaviour: use ${dir} from caller's scope
+ set(GGAID_dir "${dir}")
+ message(AUTHOR_WARNING
+ "GNUInstallDirs_get_absolute_install_dir called without third argument. "
+ "Using \${dir} from the caller's scope for compatibility with CMake 3.19 and below.")
+ endif()
+
if(NOT IS_ABSOLUTE "${${var}}")
# Handle special cases:
# - CMAKE_INSTALL_PREFIX == /
# - CMAKE_INSTALL_PREFIX == /usr
# - CMAKE_INSTALL_PREFIX == /opt/...
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/")
- if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR")
+ if("${GGAID_dir}" STREQUAL "SYSCONFDIR" OR "${GGAID_dir}" STREQUAL "LOCALSTATEDIR" OR "${GGAID_dir}" STREQUAL "RUNSTATEDIR")
set(${absvar} "/${${var}}")
else()
if (NOT "${${var}}" MATCHES "^usr/")
@@ -349,13 +371,13 @@ macro(GNUInstallDirs_get_absolute_install_dir absvar var)
set(${absvar} "/${${var}}")
endif()
elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
- if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR")
+ if("${GGAID_dir}" STREQUAL "SYSCONFDIR" OR "${GGAID_dir}" STREQUAL "LOCALSTATEDIR" OR "${GGAID_dir}" STREQUAL "RUNSTATEDIR")
set(${absvar} "/${${var}}")
else()
set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}")
endif()
elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/opt/.*")
- if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR")
+ if("${GGAID_dir}" STREQUAL "SYSCONFDIR" OR "${GGAID_dir}" STREQUAL "LOCALSTATEDIR" OR "${GGAID_dir}" STREQUAL "RUNSTATEDIR")
set(${absvar} "/${${var}}${CMAKE_INSTALL_PREFIX}")
else()
set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}")
@@ -366,6 +388,10 @@ macro(GNUInstallDirs_get_absolute_install_dir absvar var)
else()
set(${absvar} "${${var}}")
endif()
+
+ unset(GGAID_dir)
+ unset(GGAID_extra_arg_count)
+ unset(GGAID_extra_args)
endmacro()
# Result directories
@@ -388,7 +414,7 @@ foreach(dir
MANDIR
DOCDIR
)
- GNUInstallDirs_get_absolute_install_dir(CMAKE_INSTALL_FULL_${dir} CMAKE_INSTALL_${dir})
+ GNUInstallDirs_get_absolute_install_dir(CMAKE_INSTALL_FULL_${dir} CMAKE_INSTALL_${dir} ${dir})
endforeach()
cmake_policy(POP)
diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake
index e4481f66d..a9a9c5935 100644
--- a/Modules/GenerateExportHeader.cmake
+++ b/Modules/GenerateExportHeader.cmake
@@ -9,6 +9,9 @@ Function for generation of export macros for libraries
This module provides the function ``GENERATE_EXPORT_HEADER()``.
+.. versionadded:: 3.12
+ Added support for C projects. Previous versions supported C++ project only.
+
The ``GENERATE_EXPORT_HEADER`` function can be used to generate a file
suitable for preprocessor inclusion which contains EXPORT macros to be
used in library classes::
@@ -27,7 +30,6 @@ used in library classes::
[CUSTOM_CONTENT_FROM_VARIABLE <variable>]
)
-
The target properties :prop_tgt:`CXX_VISIBILITY_PRESET <<LANG>_VISIBILITY_PRESET>`
and :prop_tgt:`VISIBILITY_INLINES_HIDDEN` can be used to add the appropriate
compile flags for targets. See the documentation of those target properties,
@@ -170,20 +172,30 @@ For example:
Generates the macros ``VTK_SOMELIB_EXPORT`` etc.
+.. versionadded:: 3.1
+ Library target can be an ``OBJECT`` library.
+
+.. versionadded:: 3.7
+ Added the ``CUSTOM_CONTENT_FROM_VARIABLE`` option.
+
+.. versionadded:: 3.11
+ Added the ``INCLUDE_GUARD_NAME`` option.
+
::
ADD_COMPILER_EXPORT_FLAGS( [<output_variable>] )
+.. deprecated:: 3.0
+ Set the target properties
+ :prop_tgt:`CXX_VISIBILITY_PRESET <<LANG>_VISIBILITY_PRESET>` and
+ :prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead.
+
The ``ADD_COMPILER_EXPORT_FLAGS`` function adds ``-fvisibility=hidden`` to
:variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` if supported, and is a no-op
on Windows which does not need extra compiler flags for exporting support.
You may optionally pass a single argument to ``ADD_COMPILER_EXPORT_FLAGS``
that will be populated with the ``CXX_FLAGS`` required to enable visibility
support for the compiler/architecture in use.
-
-This function is deprecated. Set the target properties
-:prop_tgt:`CXX_VISIBILITY_PRESET <<LANG>_VISIBILITY_PRESET>` and
-:prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead.
#]=======================================================================]
include(CheckCCompilerFlag)
@@ -209,7 +221,7 @@ macro(_test_compiler_hidden_visibility)
set(GCC_TOO_OLD TRUE)
elseif(CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2")
set(GCC_TOO_OLD TRUE)
- elseif(CMAKE_CXX_COMPILER_ID MATCHES Intel AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0")
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0")
set(_INTEL_TOO_OLD TRUE)
endif()
@@ -220,7 +232,7 @@ macro(_test_compiler_hidden_visibility)
AND NOT WIN32
AND NOT CYGWIN
AND NOT CMAKE_CXX_COMPILER_ID MATCHES XL
- AND NOT CMAKE_CXX_COMPILER_ID MATCHES PGI
+ AND NOT CMAKE_CXX_COMPILER_ID MATCHES "^(PGI|NVHPC)$"
AND NOT CMAKE_CXX_COMPILER_ID MATCHES Watcom)
if (CMAKE_CXX_COMPILER_LOADED)
check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
@@ -242,7 +254,7 @@ macro(_test_compiler_has_deprecated)
OR CMAKE_CXX_COMPILER_ID MATCHES Embarcadero
OR CMAKE_CXX_COMPILER_ID MATCHES HP
OR GCC_TOO_OLD
- OR CMAKE_CXX_COMPILER_ID MATCHES PGI
+ OR CMAKE_CXX_COMPILER_ID MATCHES "^(PGI|NVHPC)$"
OR CMAKE_CXX_COMPILER_ID MATCHES Watcom)
set(COMPILER_HAS_DEPRECATED "" CACHE INTERNAL
"Compiler support for a deprecated attribute")
diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake
index 2d4765aaa..ed5c38b05 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -25,6 +25,9 @@ files:
ldd (Linux/Unix)
otool (Mac OSX)
+.. versionchanged:: 3.16
+ The tool specified by ``CMAKE_OBJDUMP`` will be used, if set.
+
The following functions are provided by this module:
::
@@ -42,9 +45,6 @@ The following functions are provided by this module:
(projects can override with gp_resolved_file_type_override)
gp_file_type
-Requires CMake 2.6 or greater because it uses function, break, return
-and PARENT_SCOPE.
-
::
GET_PREREQUISITES(<target> <prerequisites_var> <exclude_system> <recurse>
@@ -67,8 +67,9 @@ searched first when a target without any path info is given. Then
standard system locations are also searched: PATH, Framework
locations, /usr/lib...
-The variable GET_PREREQUISITES_VERBOSE can be set to true to enable verbose
-output.
+.. versionadded:: 3.14
+ The variable GET_PREREQUISITES_VERBOSE can be set to true to enable verbose
+ output.
::
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
index 057b29d6d..2ea9e7425 100644
--- a/Modules/GoogleTest.cmake
+++ b/Modules/GoogleTest.cmake
@@ -101,6 +101,8 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
with the list of discovered test cases. This allows the caller to do
things like manipulate test properties of the discovered tests.
+ Usage example:
+
.. code-block:: cmake
include(GoogleTest)
@@ -157,6 +159,8 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
[DISCOVERY_MODE <POST_BUILD|PRE_TEST>]
)
+ .. versionadded:: 3.10
+
``gtest_discover_tests()`` sets up a post-build command on the test executable
that generates the list of tests by parsing the output from running the test
with the ``--gtest_list_tests`` argument. Compared to the source parsing
@@ -223,6 +227,8 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
Note that this variable is only available in CTest.
``DISCOVERY_TIMEOUT num``
+ .. versionadded:: 3.10.3
+
Specifies how long (in seconds) CMake will wait for the test to enumerate
available tests. If the test takes longer than this, discovery (and your
build) will fail. Most test executables will enumerate their tests very
@@ -241,6 +247,8 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
and 3.10.2 has not been preserved.
``XML_OUTPUT_DIR dir``
+ .. versionadded:: 3.18
+
If specified, the parameter is passed along with ``--gtest_output=xml:``
to test executable. The actual file name is the same as the test target,
including prefix and suffix. This should be used instead of
@@ -248,6 +256,8 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
XML result output when using parallel test execution.
``DISCOVERY_MODE``
+ .. versionadded:: 3.18
+
Provides greater control over when ``gtest_discover_tests()`` performs test
discovery. By default, ``POST_BUILD`` sets up a post-build command
to perform test discovery at build time. In certain scenarios, like
diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake
index 883e1f48d..0f79c9afc 100644
--- a/Modules/GoogleTestAddTests.cmake
+++ b/Modules/GoogleTestAddTests.cmake
@@ -136,7 +136,7 @@ function(gtest_discover_tests_impl)
${TEST_XML_OUTPUT_PARAM}
${extra_args}
)
- if(suite MATCHES "^DISABLED" OR test MATCHES "^DISABLED")
+ if(suite MATCHES "^DISABLED_" OR test MATCHES "^DISABLED_")
add_command(set_tests_properties
"${testname}"
PROPERTIES DISABLED TRUE
diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake
index 29d1ec0e7..2d08e0845 100644
--- a/Modules/InstallRequiredSystemLibraries.cmake
+++ b/Modules/InstallRequiredSystemLibraries.cmake
@@ -27,14 +27,17 @@ may be set prior to including the module to adjust behavior:
tools even if the release runtime libraries are also available.
``CMAKE_INSTALL_UCRT_LIBRARIES``
+ .. versionadded:: 3.6
+
Set to TRUE to install the Windows Universal CRT libraries for
app-local deployment (e.g. to Windows XP). This is meaningful
only with MSVC from Visual Studio 2015 or higher.
- One may set a ``CMAKE_WINDOWS_KITS_10_DIR`` *environment variable*
- to an absolute path to tell CMake to look for Windows 10 SDKs in
- a custom location. The specified directory is expected to contain
- ``Redist/ucrt/DLLs/*`` directories.
+ .. versionadded:: 3.9
+ One may set a ``CMAKE_WINDOWS_KITS_10_DIR`` *environment variable*
+ to an absolute path to tell CMake to look for Windows 10 SDKs in
+ a custom location. The specified directory is expected to contain
+ ``Redist/ucrt/DLLs/*`` directories.
``CMAKE_INSTALL_MFC_LIBRARIES``
Set to TRUE to install the MSVC MFC runtime libraries.
@@ -53,8 +56,13 @@ may be set prior to including the module to adjust behavior:
not provide the redistributable files.)
``CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT``
+ .. versionadded:: 3.3
+
Specify the :command:`install(PROGRAMS)` command ``COMPONENT``
option. If not specified, no such option will be used.
+
+.. versionadded:: 3.10
+ Support for installing Intel compiler runtimes.
#]=======================================================================]
cmake_policy(PUSH)
@@ -63,7 +71,7 @@ cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
set(_IRSL_HAVE_Intel FALSE)
set(_IRSL_HAVE_MSVC FALSE)
foreach(LANG IN ITEMS C CXX Fortran)
- if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Intel")
+ if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "Intel")
if(NOT _IRSL_HAVE_Intel)
get_filename_component(_Intel_basedir "${CMAKE_${LANG}_COMPILER}" PATH)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -93,16 +101,18 @@ endforeach()
if(MSVC)
file(TO_CMAKE_PATH "$ENV{SYSTEMROOT}" SYSTEMROOT)
- if(CMAKE_CL_64)
- if(MSVC_VERSION GREATER 1599)
- # VS 10 and later:
- set(CMAKE_MSVC_ARCH x64)
- else()
+ if(MSVC_C_ARCHITECTURE_ID)
+ string(TOLOWER "${MSVC_C_ARCHITECTURE_ID}" CMAKE_MSVC_ARCH)
+ elseif(MSVC_CXX_ARCHITECTURE_ID)
+ string(TOLOWER "${MSVC_CXX_ARCHITECTURE_ID}" CMAKE_MSVC_ARCH)
+ else()
+ set(CMAKE_MSVC_ARCH x86)
+ endif()
+ if(CMAKE_MSVC_ARCH STREQUAL "x64")
+ if(MSVC_VERSION LESS 1600)
# VS 9 and earlier:
set(CMAKE_MSVC_ARCH amd64)
endif()
- else()
- set(CMAKE_MSVC_ARCH x86)
endif()
get_filename_component(devenv_dir "${CMAKE_MAKE_PROGRAM}" PATH)
@@ -627,10 +637,10 @@ if(_IRSL_HAVE_Intel)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
endforeach()
- if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel)
+ if(CMAKE_C_COMPILER_ID MATCHES Intel OR CMAKE_CXX_COMPILER_ID MATCHES Intel)
list(APPEND __install_libs "${_Intel_redistdir}/libgfxoffload.dll")
endif()
- if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
+ if(CMAKE_Fortran_COMPILER_ID MATCHES Intel)
foreach(__Intel_lib IN ITEMS ifdlg100.dll libicaf.dll libifcoremd.dll libifcoremdd.dll libifcorert.dll libifcorertd.dll libifportmd.dll)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
@@ -640,12 +650,12 @@ if(_IRSL_HAVE_Intel)
foreach(__Intel_lib IN ITEMS libchkp.dylib libcilkrts.5.dylib libcilkrts.dylib libimf.dylib libintlc.dylib libirc.dylib libirng.dylib libsvml.dylib)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
endforeach()
- if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel)
+ if(CMAKE_C_COMPILER_ID MATCHES Intel OR CMAKE_CXX_COMPILER_ID MATCHES Intel)
if(_Intel_compiler_ver VERSION_LESS 17)
list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.dylib")
endif()
endif()
- if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
+ if(CMAKE_Fortran_COMPILER_ID MATCHES Intel)
foreach(__Intel_lib IN ITEMS libifcore.dylib libifcoremt.dylib libifport.dylib libifportmt.dylib)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
@@ -662,7 +672,7 @@ if(_IRSL_HAVE_Intel)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
endforeach()
endif()
- if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel)
+ if(CMAKE_C_COMPILER_ID MATCHES Intel OR CMAKE_CXX_COMPILER_ID MATCHES Intel)
set(__install_dirs "${_Intel_redistdir}/irml")
list(APPEND __install_libs "${_Intel_redistdir}/cilk_db.so")
if(_Intel_compiler_ver VERSION_GREATER_EQUAL 15)
@@ -681,7 +691,7 @@ if(_IRSL_HAVE_Intel)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
endforeach()
endif()
- if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
+ if(CMAKE_Fortran_COMPILER_ID MATCHES Intel)
foreach(__Intel_lib IN ITEMS libicaf.so libifcore.so libifcore.so.5 libifcoremt.so libifcoremt.so.5 libifport.so libifport.so.5)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
diff --git a/Modules/Internal/CPack/CPack.NuGet.nuspec.in b/Modules/Internal/CPack/CPack.NuGet.nuspec.in
index b7beb5de0..d89d69ff0 100644
--- a/Modules/Internal/CPack/CPack.NuGet.nuspec.in
+++ b/Modules/Internal/CPack/CPack.NuGet.nuspec.in
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
+<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<!-- Required elements-->
<id>@CPACK_NUGET_PACKAGE_NAME@</id>
@@ -12,11 +12,14 @@
@_CPACK_NUGET_OWNERS_TAG@
@_CPACK_NUGET_PROJECTURL_TAG@
@_CPACK_NUGET_LICENSEURL_TAG@
+ @_CPACK_NUGET_LICENSE_TAG@
@_CPACK_NUGET_ICONURL_TAG@
+ @_CPACK_NUGET_ICON_TAG@
@_CPACK_NUGET_REQUIRELICENSEACCEPTANCE_TAG@
@_CPACK_NUGET_SUMMARY_TAG@
@_CPACK_NUGET_RELEASENOTES_TAG@
@_CPACK_NUGET_COPYRIGHT_TAG@
+ @_CPACK_NUGET_LANGUAGE_TAG@
@_CPACK_NUGET_TAGS_TAG@
@_CPACK_NUGET_DEPENDENCIES_TAG@
</metadata>
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 431b074c9..2ef0489b6 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -310,10 +310,23 @@ function(cpack_deb_prepare_package_vars)
set(IGNORE_MISSING_INFO_FLAG "--ignore-missing-info")
endif()
+ if(CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS)
+ unset(PRIVATE_SEARCH_DIR_OPTIONS)
+ # Add -l option if the tool supports it
+ if(DEFINED SHLIBDEPS_EXECUTABLE_VERSION AND SHLIBDEPS_EXECUTABLE_VERSION VERSION_GREATER_EQUAL 1.17.0)
+ foreach(dir IN LISTS CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS)
+ list(APPEND PRIVATE_SEARCH_DIR_OPTIONS "-l${dir}")
+ endforeach()
+ else()
+ message(WARNING "CPackDeb: dkpg-shlibdeps is too old. \"CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS\" is therefore ignored.")
+ endif()
+ endif()
+
# Execute dpkg-shlibdeps
# --ignore-missing-info : allow dpkg-shlibdeps to run even if some libs do not belong to a package
+ # -l<dir>: make dpkg-shlibdeps also search in this directory for (private) shared library dependencies
# -O : print to STDOUT
- execute_process(COMMAND ${SHLIBDEPS_EXECUTABLE} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}
+ execute_process(COMMAND ${SHLIBDEPS_EXECUTABLE} ${PRIVATE_SEARCH_DIR_OPTIONS} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE SHLIBDEPS_OUTPUT
RESULT_VARIABLE SHLIBDEPS_RESULT
@@ -325,7 +338,7 @@ function(cpack_deb_prepare_package_vars)
endif()
if(NOT SHLIBDEPS_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: dpkg-shlibdeps: '${SHLIBDEPS_ERROR}';\n"
- "executed command: '${SHLIBDEPS_EXECUTABLE} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}';\n"
+ "executed command: '${SHLIBDEPS_EXECUTABLE} ${PRIVATE_SEARCH_DIR_OPTIONS} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}';\n"
"found files: '${INSTALL_FILE_}';\n"
"files info: '${CPACK_DEB_INSTALL_FILES}';\n"
"binary files: '${CPACK_DEB_BINARY_FILES}'")
@@ -768,6 +781,10 @@ function(cpack_deb_prepare_package_vars)
set(GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_DBGSYM_OUTPUT_FILE_NAME}" PARENT_SCOPE)
list(JOIN BUILD_IDS " " BUILD_IDS)
set(GEN_BUILD_IDS "${BUILD_IDS}" PARENT_SCOPE)
+ else()
+ unset(GEN_DBGSYMDIR PARENT_SCOPE)
+ unset(GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME PARENT_SCOPE)
+ unset(GEN_BUILD_IDS PARENT_SCOPE)
endif()
endfunction()
diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake
index 20eed2eef..fb363f448 100644
--- a/Modules/Internal/CPack/CPackNuGet.cmake
+++ b/Modules/Internal/CPack/CPackNuGet.cmake
@@ -107,21 +107,44 @@ endfunction()
function(_cpack_nuget_variable_fallback_and_wrap_into_element ELEMENT NUGET_VAR_NAME)
set(_options)
set(_one_value_args)
- set(_multi_value_args FALLBACK_VARS)
- cmake_parse_arguments(PARSE_ARGV 0 _args "${_options}" "${_one_value_args}" "${_multi_value_args}")
+ set(_multi_value_args FALLBACK_VARS ATTRIBUTES)
+ cmake_parse_arguments(PARSE_ARGV 2 _args "${_options}" "${_one_value_args}" "${_multi_value_args}")
+
+ if(_args_ATTRIBUTES)
+ list(JOIN _args_ATTRIBUTES " " _attributes)
+ string(PREPEND _attributes " ")
+ endif()
_cpack_nuget_variable_fallback(_value ${NUGET_VAR_NAME} ${ARGN} USE_CDATA)
+ string(TOUPPER "${ELEMENT}" _ELEMENT_UP)
if(_value)
- string(TOUPPER "${ELEMENT}" _ELEMENT_UP)
set(
_CPACK_NUGET_${_ELEMENT_UP}_TAG
- "<${ELEMENT}>${_value}</${ELEMENT}>"
+ "<${ELEMENT}${_attributes}>${_value}</${ELEMENT}>"
+ PARENT_SCOPE
+ )
+ elseif(_attributes)
+ set(
+ _CPACK_NUGET_${_ELEMENT_UP}_TAG
+ "<${ELEMENT}${_attributes} />"
PARENT_SCOPE
)
endif()
endfunction()
+# Warn of obsolete nuspec fields, referencing CMake variables and suggested
+# replacement, if any
+function(_cpack_nuget_deprecation_warning NUGET_ELEMENT VARNAME REPLACEMENT)
+ if(${VARNAME})
+ if(REPLACEMENT)
+ message(DEPRECATION "nuspec element `${NUGET_ELEMENT}` is deprecated in NuGet; consider replacing `${VARNAME}` with `${REPLACEMENT}`")
+ else()
+ message(DEPRECATION "nuspec element `${NUGET_ELEMENT}` is deprecated in NuGet; consider removing `${VARNAME}`")
+ endif()
+ endif()
+endfunction()
+
# Print some debug info
_cpack_nuget_debug("---[CPack NuGet Input Variables]---")
_cpack_nuget_debug_var(CPACK_PACKAGE_NAME)
@@ -168,6 +191,21 @@ function(_cpack_nuget_render_spec)
set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
endif()
+ # Warn about deprecated nuspec elements; warnings only display if
+ # variable is set
+ # Note that while nuspec's "summary" element is deprecated, there
+ # is no suggested replacement so (for now) no deprecation warning
+ # is shown for `CPACK_NUGET_*_DESCRIPTION_SUMMARY`
+ _cpack_nuget_deprecation_warning("licenseUrl" CPACK_NUGET_PACKAGE_LICENSEURL
+ "CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME or CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION")
+ _cpack_nuget_deprecation_warning("licenseUrl" CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_LICENSEURL
+ "CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_LICENSE_FILE_NAME or CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_LICENSE_EXPRESSION")
+ _cpack_nuget_deprecation_warning("iconUrl" CPACK_NUGET_PACKAGE_ICONURL
+ "CPACK_NUGET_PACKAGE_ICON")
+ _cpack_nuget_deprecation_warning("iconUrl" CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_ICONURL
+ "CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_ICON")
+
+ # Set nuspec fields
_cpack_nuget_variable_fallback(
CPACK_NUGET_PACKAGE_VERSION VERSION
FALLBACK_VARS
@@ -207,8 +245,35 @@ function(_cpack_nuget_render_spec)
FALLBACK_VARS
CPACK_PACKAGE_HOMEPAGE_URL
)
+
+ # "licenseUrl" is deprecated in favor of "license"
_cpack_nuget_variable_fallback_and_wrap_into_element(licenseUrl LICENSEURL)
+
+ # "iconUrl" is deprecated in favor of "icon"
_cpack_nuget_variable_fallback_and_wrap_into_element(iconUrl ICONURL)
+
+ # "license" takes a "type" attribute of either "file" or "expression"
+ # "file" refers to a file path of a .txt or .md file relative to the installation root
+ # "expression" refers to simple or compound expression of license identifiers
+ # listed at https://spdx.org/licenses/
+ # Note that only one of CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME and
+ # CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION may be specified. If both are specified,
+ # CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME takes precedence and CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION is ignored.
+ if(CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ license LICENSE_FILE_NAME
+ ATTRIBUTES [[type="file"]]
+ )
+ elseif(CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ license LICENSE_EXPRESSION
+ ATTRIBUTES [[type="expression"]]
+ )
+ endif()
+
+ # "icon" refers to a file path relative to the installation root
+ _cpack_nuget_variable_fallback_and_wrap_into_element(icon ICON)
+ # "summary" is deprecated in favor of "description"
_cpack_nuget_variable_fallback_and_wrap_into_element(
summary DESCRIPTION_SUMMARY
FALLBACK_VARS
@@ -222,7 +287,12 @@ function(_cpack_nuget_render_spec)
endif()
_cpack_nuget_variable_fallback_and_wrap_into_element(releaseNotes RELEASE_NOTES)
_cpack_nuget_variable_fallback_and_wrap_into_element(copyright COPYRIGHT)
+ # "language" is a locale identifier such as "en_CA"
+ _cpack_nuget_variable_fallback_and_wrap_into_element(language LANGUAGE)
_cpack_nuget_variable_fallback_and_wrap_into_element(tags TAGS LIST_GLUE " ")
+ # "repository" holds repository metadata consisting of four optional
+ # attributes: "type", "url", "branch", and "commit". While all fields are
+ # considered optional, they are not independent. Currently unsupported.
# Handle dependencies
_cpack_nuget_variable_fallback(_deps DEPENDENCIES)
@@ -262,7 +332,7 @@ endfunction()
function(_cpack_nuget_make_files_tag)
set(_files)
foreach(_comp IN LISTS ARGN)
- string(APPEND _files " <file src=\"${_comp}\\**\" target=\".\" />\n")
+ string(APPEND _files " <file src=\"${_comp}/**\" target=\".\" />\n")
endforeach()
set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE)
endfunction()
diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in
index 6009ce0a6..e6439ad7e 100644
--- a/Modules/Internal/CPack/NSIS.template.in
+++ b/Modules/Internal/CPack/NSIS.template.in
@@ -1,4 +1,4 @@
-; CPack install script designed for a nmake build
+; CPack install script designed for a nmake build
;--------------------------------
; You must define these values
@@ -42,6 +42,7 @@
@CPACK_NSIS_DEFINES@
@CPACK_NSIS_MANIFEST_DPI_AWARE_CODE@
+@CPACK_NSIS_BRANDING_TEXT_CODE@
!include Sections.nsh
diff --git a/Modules/MacroAddFileDependencies.cmake b/Modules/MacroAddFileDependencies.cmake
index ca60b5702..8fdc26452 100644
--- a/Modules/MacroAddFileDependencies.cmake
+++ b/Modules/MacroAddFileDependencies.cmake
@@ -5,26 +5,25 @@
MacroAddFileDependencies
------------------------
-MACRO_ADD_FILE_DEPENDENCIES(<_file> depend_files...)
+.. deprecated:: 3.14
-Using the macro MACRO_ADD_FILE_DEPENDENCIES() is discouraged. There
-are usually better ways to specify the correct dependencies.
+::
+
+ MACRO_ADD_FILE_DEPENDENCIES(<source> <files>...)
+
+Do not use this command in new code. It is just a wrapper around:
+
+.. code-block:: cmake
+
+ set_property(SOURCE <source> APPEND PROPERTY OBJECT_DEPENDS <files>...)
+
+Instead use the :command:`set_property` command to append to the
+:prop_sf:`OBJECT_DEPENDS` source file property directly.
-MACRO_ADD_FILE_DEPENDENCIES(<_file> depend_files...) is just a
-convenience wrapper around the OBJECT_DEPENDS source file property.
-You can just use set_property(SOURCE <file> APPEND PROPERTY
-OBJECT_DEPENDS depend_files) instead.
#]=======================================================================]
macro (MACRO_ADD_FILE_DEPENDENCIES _file)
- get_source_file_property(_deps ${_file} OBJECT_DEPENDS)
- if (_deps)
- set(_deps ${_deps} ${ARGN})
- else ()
- set(_deps ${ARGN})
- endif ()
-
- set_source_files_properties(${_file} PROPERTIES OBJECT_DEPENDS "${_deps}")
+ set_property(SOURCE "${_file}" APPEND PROPERTY OBJECT_DEPENDS "${ARGN}")
endmacro ()
diff --git a/Modules/Platform/Android-Clang.cmake b/Modules/Platform/Android-Clang.cmake
index 160eadae0..3a279cadc 100644
--- a/Modules/Platform/Android-Clang.cmake
+++ b/Modules/Platform/Android-Clang.cmake
@@ -7,6 +7,23 @@ if(__ANDROID_COMPILER_CLANG)
endif()
set(__ANDROID_COMPILER_CLANG 1)
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/pre/Android-Clang.cmake OPTIONAL)
+endif()
+
+# Load flags from NDK. This file may provides the following variables:
+# _ANDROID_NDK_INIT_CFLAGS
+# _ANDROID_NDK_INIT_CFLAGS_DEBUG
+# _ANDROID_NDK_INIT_CFLAGS_RELEASE
+# _ANDROID_NDK_INIT_LDFLAGS
+# _ANDROID_NDK_INIT_LDFLAGS_EXE
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/flags.cmake OPTIONAL
+ RESULT_VARIABLE _INCLUDED_FLAGS)
+endif()
+
# Support for NVIDIA Nsight Tegra Visual Studio Edition was previously
# implemented in the CMake VS IDE generators. Avoid interfering with
# that functionality for now. Later we may try to integrate this.
@@ -34,20 +51,29 @@ endif()
include(Platform/Android-Common)
-# The NDK toolchain configuration files at:
-#
-# <ndk>/[build/core/]toolchains/*-clang*/setup.mk
-#
-# contain logic to set LLVM_TRIPLE for Clang-based toolchains for each target.
-# We need to produce the same target here to produce compatible binaries.
-include(Platform/Android/abi-${CMAKE_ANDROID_ARCH_ABI}-Clang)
+if(_INCLUDED_FLAGS)
+ # NDK provides the flags.
+ set(_ANDROID_ABI_INIT_CFLAGS "${_ANDROID_NDK_INIT_CFLAGS}")
+ set(_ANDROID_ABI_INIT_CFLAGS_DEBUG "${_ANDROID_NDK_INIT_CFLAGS_DEBUG}")
+ set(_ANDROID_ABI_INIT_CFLAGS_RELEASE "${_ANDROID_NDK_INIT_CFLAGS_RELEASE}")
+ set(_ANDROID_ABI_INIT_LDFLAGS "${_ANDROID_NDK_INIT_LDFLAGS}")
+ set(_ANDROID_ABI_INIT_EXE_LDFLAGS "${_ANDROID_NDK_INIT_LDFLAGS_EXE}")
+else()
+ # The NDK toolchain configuration files at:
+ #
+ # <ndk>/[build/core/]toolchains/*-clang*/setup.mk
+ #
+ # contain logic to set LLVM_TRIPLE for Clang-based toolchains for each target.
+ # We need to produce the same target here to produce compatible binaries.
+ include(Platform/Android/abi-${CMAKE_ANDROID_ARCH_ABI}-Clang)
+endif()
macro(__android_compiler_clang lang)
if(NOT "x${lang}" STREQUAL "xASM")
__android_compiler_common(${lang})
endif()
if(NOT CMAKE_${lang}_COMPILER_TARGET)
- set(CMAKE_${lang}_COMPILER_TARGET "${_ANDROID_ABI_CLANG_TARGET}")
+ set(CMAKE_${lang}_COMPILER_TARGET "${CMAKE_ANDROID_ARCH_LLVM_TRIPLE}")
if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
string(APPEND CMAKE_${lang}_COMPILER_TARGET "${CMAKE_SYSTEM_VERSION}")
endif()
@@ -57,3 +83,9 @@ macro(__android_compiler_clang lang)
set(_ANDROID_STL_NOSTDLIBXX 1)
endif()
endmacro()
+
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/post/Android-Clang.cmake OPTIONAL)
+endif()
diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake
index 581fde4c6..39da93300 100644
--- a/Modules/Platform/Android-Common.cmake
+++ b/Modules/Platform/Android-Common.cmake
@@ -53,6 +53,12 @@ if(CMAKE_ANDROID_STL_TYPE)
set(_ANDROID_STL_RTTI 0)
macro(__android_stl lang)
string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libstdc++")
+ if(_ANDROID_STL_EXCEPTIONS OR _ANDROID_STL_RTTI)
+ string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -lc++abi")
+ if(CMAKE_SYSTEM_VERSION LESS 21)
+ list(APPEND CMAKE_${lang}_STANDARD_LIBRARIES "-landroid_support")
+ endif()
+ endif()
endmacro()
elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_static")
set(_ANDROID_STL_EXCEPTIONS 1)
@@ -81,6 +87,12 @@ if(CMAKE_ANDROID_STL_TYPE)
"Android: STL '${CMAKE_ANDROID_STL_TYPE}' not supported by this NDK."
)
endif()
+ if(DEFINED CMAKE_ANDROID_RTTI)
+ set(_ANDROID_STL_RTTI ${CMAKE_ANDROID_RTTI})
+ endif()
+ if(DEFINED CMAKE_ANDROID_EXCEPTIONS)
+ set(_ANDROID_STL_EXCEPTIONS ${CMAKE_ANDROID_EXCEPTIONS})
+ endif()
elseif(CMAKE_ANDROID_NDK)
macro(__android_stl_inc lang dir req)
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index bc66ba1df..2d2cd5c72 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -5,6 +5,12 @@
# This module detects platform-wide information about the Android target
# in order to store it in "CMakeSystem.cmake".
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/pre/Android-Determine.cmake OPTIONAL)
+endif()
+
# Support for NVIDIA Nsight Tegra Visual Studio Edition was previously
# implemented in the CMake VS IDE generators. Avoid interfering with
# that functionality for now.
@@ -209,9 +215,55 @@ if(CMAKE_ANDROID_NDK)
# NDK >= 18 has abis.cmake. It provides:
# NDK_KNOWN_DEVICE_ABI32S
# NDK_KNOWN_DEVICE_ABI64S
+ # NDK >= 23 also provides:
+ # NDK_KNOWN_DEVICE_ABIS
+ # NDK_ABI_<abi>_PROC
+ # NDK_ABI_<abi>_ARCH
+ # NDK_ABI_<abi>_TRIPLE
+ # NDK_ABI_<abi>_LLVM_TRIPLE
+ # NDK_PROC_<processor>_ABI
+ # NDK_ARCH_<arch>_ABI
include("${CMAKE_ANDROID_NDK}/build/cmake/abis.cmake" OPTIONAL RESULT_VARIABLE _INCLUDED_ABIS)
endif()
+if(CMAKE_ANDROID_NDK AND EXISTS "${CMAKE_ANDROID_NDK}/source.properties")
+ # Android NDK revision
+ # Possible formats:
+ # * r16, build 1234: 16.0.1234
+ # * r16b, build 1234: 16.1.1234
+ # * r16 beta 1, build 1234: 16.0.1234-beta1
+ #
+ # Canary builds are not specially marked.
+ file(READ "${CMAKE_ANDROID_NDK}/source.properties" _ANDROID_NDK_SOURCE_PROPERTIES)
+
+ set(_ANDROID_NDK_REVISION_REGEX
+ "^Pkg\\.Desc = Android NDK\nPkg\\.Revision = ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-beta([0-9]+))?")
+ if(NOT _ANDROID_NDK_SOURCE_PROPERTIES MATCHES "${_ANDROID_NDK_REVISION_REGEX}")
+ string(REPLACE "\n" "\n " _ANDROID_NDK_SOURCE_PROPERTIES "${_ANDROID_NDK_SOURCE_PROPERTIES}")
+ message(FATAL_ERROR
+ "Android: Failed to parse NDK revision from:\n"
+ " ${CMAKE_ANDROID_NDK}/source.properties\n"
+ "with content:\n"
+ " ${_ANDROID_NDK_SOURCE_PROPERTIES}")
+ endif()
+
+ set(_ANDROID_NDK_MAJOR "${CMAKE_MATCH_1}")
+ set(_ANDROID_NDK_MINOR "${CMAKE_MATCH_2}")
+ set(_ANDROID_NDK_BUILD "${CMAKE_MATCH_3}")
+ set(_ANDROID_NDK_BETA "${CMAKE_MATCH_5}")
+ if(_ANDROID_NDK_BETA STREQUAL "")
+ set(_ANDROID_NDK_BETA "0")
+ endif()
+ set(CMAKE_ANDROID_NDK_VERSION "${_ANDROID_NDK_MAJOR}.${_ANDROID_NDK_MINOR}")
+
+ unset(_ANDROID_NDK_SOURCE_PROPERTIES)
+ unset(_ANDROID_NDK_REVISION_REGEX)
+ unset(_ANDROID_NDK_MAJOR)
+ unset(_ANDROID_NDK_MINOR)
+ unset(_ANDROID_NDK_BUILD)
+ unset(_ANDROID_NDK_BETA)
+endif()
+
if(CMAKE_ANDROID_NDK)
# Identify the host platform.
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
@@ -247,60 +299,75 @@ else()
endif()
if(_INCLUDED_ABIS)
- set(_ANDROID_KNOWN_ABIS ${NDK_KNOWN_DEVICE_ABI32S} ${NDK_KNOWN_DEVICE_ABI64S})
+ if(NDK_KNOWN_DEVICE_ABIS)
+ set(_ANDROID_KNOWN_ABIS ${NDK_KNOWN_DEVICE_ABIS})
+ else()
+ set(_ANDROID_KNOWN_ABIS ${NDK_KNOWN_DEVICE_ABI32S} ${NDK_KNOWN_DEVICE_ABI64S})
+ endif()
endif()
-# https://developer.android.com/ndk/guides/abis.html
-
-set(_ANDROID_ABI_arm64-v8a_PROC "aarch64")
-set(_ANDROID_ABI_arm64-v8a_ARCH "arm64")
-set(_ANDROID_ABI_arm64-v8a_TRIPLE "aarch64-linux-android")
-set(_ANDROID_ABI_armeabi-v7a_PROC "armv7-a")
-set(_ANDROID_ABI_armeabi-v7a_ARCH "arm")
-set(_ANDROID_ABI_armeabi-v7a_TRIPLE "arm-linux-androideabi")
-set(_ANDROID_ABI_armeabi-v6_PROC "armv6")
-set(_ANDROID_ABI_armeabi-v6_ARCH "arm")
-set(_ANDROID_ABI_armeabi-v6_TRIPLE "arm-linux-androideabi")
-set(_ANDROID_ABI_armeabi_PROC "armv5te")
-set(_ANDROID_ABI_armeabi_ARCH "arm")
-set(_ANDROID_ABI_armeabi_TRIPLE "arm-linux-androideabi")
-set(_ANDROID_ABI_mips_PROC "mips")
-set(_ANDROID_ABI_mips_ARCH "mips")
-set(_ANDROID_ABI_mips_TRIPLE "mipsel-linux-android")
-set(_ANDROID_ABI_mips64_PROC "mips64")
-set(_ANDROID_ABI_mips64_ARCH "mips64")
-set(_ANDROID_ABI_mips64_TRIPLE "mips64el-linux-android")
-set(_ANDROID_ABI_x86_PROC "i686")
-set(_ANDROID_ABI_x86_ARCH "x86")
-set(_ANDROID_ABI_x86_TRIPLE "i686-linux-android")
-set(_ANDROID_ABI_x86_64_PROC "x86_64")
-set(_ANDROID_ABI_x86_64_ARCH "x86_64")
-set(_ANDROID_ABI_x86_64_TRIPLE "x86_64-linux-android")
-
-set(_ANDROID_PROC_aarch64_ARCH_ABI "arm64-v8a")
-set(_ANDROID_PROC_armv7-a_ARCH_ABI "armeabi-v7a")
-set(_ANDROID_PROC_armv6_ARCH_ABI "armeabi-v6")
-set(_ANDROID_PROC_armv5te_ARCH_ABI "armeabi")
-set(_ANDROID_PROC_i686_ARCH_ABI "x86")
-set(_ANDROID_PROC_mips_ARCH_ABI "mips")
-set(_ANDROID_PROC_mips64_ARCH_ABI "mips64")
-set(_ANDROID_PROC_x86_64_ARCH_ABI "x86_64")
-
-set(_ANDROID_ARCH_arm64_ABI "arm64-v8a")
-set(_ANDROID_ARCH_arm_ABI "armeabi")
-set(_ANDROID_ARCH_mips_ABI "mips")
-set(_ANDROID_ARCH_mips64_ABI "mips64")
-set(_ANDROID_ARCH_x86_ABI "x86")
-set(_ANDROID_ARCH_x86_64_ABI "x86_64")
+if(NOT DEFINED NDK_KNOWN_DEVICE_ABIS)
+ # The NDK is not new enough to provide ABI information.
+ # https://developer.android.com/ndk/guides/abis.html
+
+ set(NDK_ABI_arm64-v8a_PROC "aarch64")
+ set(NDK_ABI_arm64-v8a_ARCH "arm64")
+ set(NDK_ABI_arm64-v8a_TRIPLE "aarch64-linux-android")
+ set(NDK_ABI_arm64-v8a_LLVM_TRIPLE "aarch64-none-linux-android")
+ set(NDK_ABI_armeabi-v7a_PROC "armv7-a")
+ set(NDK_ABI_armeabi-v7a_ARCH "arm")
+ set(NDK_ABI_armeabi-v7a_TRIPLE "arm-linux-androideabi")
+ set(NDK_ABI_armeabi-v7a_LLVM_TRIPLE "armv7-none-linux-androideabi")
+ set(NDK_ABI_armeabi-v6_PROC "armv6")
+ set(NDK_ABI_armeabi-v6_ARCH "arm")
+ set(NDK_ABI_armeabi-v6_TRIPLE "arm-linux-androideabi")
+ set(NDK_ABI_armeabi-v6_LLVM_TRIPLE "armv6-none-linux-androideabi")
+ set(NDK_ABI_armeabi_PROC "armv5te")
+ set(NDK_ABI_armeabi_ARCH "arm")
+ set(NDK_ABI_armeabi_TRIPLE "arm-linux-androideabi")
+ set(NDK_ABI_armeabi_LLVM_TRIPLE "armv5te-none-linux-androideabi")
+ set(NDK_ABI_mips_PROC "mips")
+ set(NDK_ABI_mips_ARCH "mips")
+ set(NDK_ABI_mips_TRIPLE "mipsel-linux-android")
+ set(NDK_ABI_mips_LLVM_TRIPLE "mipsel-none-linux-android")
+ set(NDK_ABI_mips64_PROC "mips64")
+ set(NDK_ABI_mips64_ARCH "mips64")
+ set(NDK_ABI_mips64_TRIPLE "mips64el-linux-android")
+ set(NDK_ABI_mips64_LLVM_TRIPLE "mips64el-none-linux-android")
+ set(NDK_ABI_x86_PROC "i686")
+ set(NDK_ABI_x86_ARCH "x86")
+ set(NDK_ABI_x86_TRIPLE "i686-linux-android")
+ set(NDK_ABI_x86_LLVM_TRIPLE "i686-none-linux-android")
+ set(NDK_ABI_x86_64_PROC "x86_64")
+ set(NDK_ABI_x86_64_ARCH "x86_64")
+ set(NDK_ABI_x86_64_TRIPLE "x86_64-linux-android")
+ set(NDK_ABI_x86_64_LLVM_TRIPLE "x86_64-none-linux-android")
+
+ set(NDK_PROC_aarch64_ABI "arm64-v8a")
+ set(NDK_PROC_armv7-a_ABI "armeabi-v7a")
+ set(NDK_PROC_armv6_ABI "armeabi-v6")
+ set(NDK_PROC_armv5te_ABI "armeabi")
+ set(NDK_PROC_i686_ABI "x86")
+ set(NDK_PROC_mips_ABI "mips")
+ set(NDK_PROC_mips64_ABI "mips64")
+ set(NDK_PROC_x86_64_ABI "x86_64")
+
+ set(NDK_ARCH_arm64_ABI "arm64-v8a")
+ set(NDK_ARCH_arm_ABI "armeabi")
+ set(NDK_ARCH_mips_ABI "mips")
+ set(NDK_ARCH_mips64_ABI "mips64")
+ set(NDK_ARCH_x86_ABI "x86")
+ set(NDK_ARCH_x86_64_ABI "x86_64")
+endif()
# Validate inputs.
-if(CMAKE_ANDROID_ARCH_ABI AND NOT DEFINED "_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC")
+if(CMAKE_ANDROID_ARCH_ABI AND NOT DEFINED "NDK_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC")
message(FATAL_ERROR "Android: Unknown ABI CMAKE_ANDROID_ARCH_ABI='${CMAKE_ANDROID_ARCH_ABI}'.")
endif()
-if(CMAKE_SYSTEM_PROCESSOR AND NOT DEFINED "_ANDROID_PROC_${CMAKE_SYSTEM_PROCESSOR}_ARCH_ABI")
+if(CMAKE_SYSTEM_PROCESSOR AND NOT DEFINED "NDK_PROC_${CMAKE_SYSTEM_PROCESSOR}_ABI")
message(FATAL_ERROR "Android: Unknown processor CMAKE_SYSTEM_PROCESSOR='${CMAKE_SYSTEM_PROCESSOR}'.")
endif()
-if(_ANDROID_SYSROOT_ARCH AND NOT DEFINED "_ANDROID_ARCH_${_ANDROID_SYSROOT_ARCH}_ABI")
+if(_ANDROID_SYSROOT_ARCH AND NOT DEFINED "NDK_ARCH_${_ANDROID_SYSROOT_ARCH}_ABI")
message(FATAL_ERROR
"Android: Unknown architecture '${_ANDROID_SYSROOT_ARCH}' specified in CMAKE_SYSROOT:\n"
" ${CMAKE_SYSROOT}"
@@ -310,9 +377,9 @@ endif()
# Select an ABI.
if(NOT CMAKE_ANDROID_ARCH_ABI)
if(CMAKE_SYSTEM_PROCESSOR)
- set(CMAKE_ANDROID_ARCH_ABI "${_ANDROID_PROC_${CMAKE_SYSTEM_PROCESSOR}_ARCH_ABI}")
+ set(CMAKE_ANDROID_ARCH_ABI "${NDK_PROC_${CMAKE_SYSTEM_PROCESSOR}_ABI}")
elseif(_ANDROID_SYSROOT_ARCH)
- set(CMAKE_ANDROID_ARCH_ABI "${_ANDROID_ARCH_${_ANDROID_SYSROOT_ARCH}_ABI}")
+ set(CMAKE_ANDROID_ARCH_ABI "${NDK_ARCH_${_ANDROID_SYSROOT_ARCH}_ABI}")
elseif(_INCLUDED_ABIS)
# Default to the oldest ARM ABI.
foreach(abi armeabi armeabi-v7a arm64-v8a)
@@ -368,7 +435,7 @@ if(_INCLUDED_ABIS AND NOT CMAKE_ANDROID_ARCH_ABI IN_LIST _ANDROID_KNOWN_ABIS)
"Supported ABIS: ${_ANDROID_KNOWN_ABIS}."
)
endif()
-set(CMAKE_ANDROID_ARCH "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_ARCH}")
+set(CMAKE_ANDROID_ARCH "${NDK_ABI_${CMAKE_ANDROID_ARCH_ABI}_ARCH}")
if(_ANDROID_SYSROOT_ARCH AND NOT "x${_ANDROID_SYSROOT_ARCH}" STREQUAL "x${CMAKE_ANDROID_ARCH}")
message(FATAL_ERROR
"Android: Architecture '${_ANDROID_SYSROOT_ARCH}' specified in CMAKE_SYSROOT:\n"
@@ -376,15 +443,17 @@ if(_ANDROID_SYSROOT_ARCH AND NOT "x${_ANDROID_SYSROOT_ARCH}" STREQUAL "x${CMAKE_
"does not match architecture '${CMAKE_ANDROID_ARCH}' for the ABI '${CMAKE_ANDROID_ARCH_ABI}'."
)
endif()
-set(CMAKE_ANDROID_ARCH_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_TRIPLE}")
+set(CMAKE_ANDROID_ARCH_TRIPLE "${NDK_ABI_${CMAKE_ANDROID_ARCH_ABI}_TRIPLE}")
+set(CMAKE_ANDROID_ARCH_LLVM_TRIPLE
+ "${NDK_ABI_${CMAKE_ANDROID_ARCH_ABI}_LLVM_TRIPLE}")
# Select a processor.
if(NOT CMAKE_SYSTEM_PROCESSOR)
- set(CMAKE_SYSTEM_PROCESSOR "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC}")
+ set(CMAKE_SYSTEM_PROCESSOR "${NDK_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC}")
endif()
# If the user specified both an ABI and a processor then they might not match.
-if(NOT _ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC STREQUAL CMAKE_SYSTEM_PROCESSOR)
+if(NOT NDK_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC STREQUAL CMAKE_SYSTEM_PROCESSOR)
message(FATAL_ERROR "Android: The specified CMAKE_ANDROID_ARCH_ABI='${CMAKE_ANDROID_ARCH_ABI}' and CMAKE_SYSTEM_PROCESSOR='${CMAKE_SYSTEM_PROCESSOR}' is not a valid combination.")
endif()
@@ -491,6 +560,8 @@ set(CMAKE_ANDROID_ARCH_ABI \"${CMAKE_ANDROID_ARCH_ABI}\")
if(CMAKE_ANDROID_NDK)
string(APPEND CMAKE_SYSTEM_CUSTOM_CODE
"set(CMAKE_ANDROID_ARCH_TRIPLE \"${CMAKE_ANDROID_ARCH_TRIPLE}\")\n"
+ "set(CMAKE_ANDROID_ARCH_LLVM_TRIPLE \"${CMAKE_ANDROID_ARCH_LLVM_TRIPLE}\")\n"
+ "set(CMAKE_ANDROID_NDK_VERSION \"${CMAKE_ANDROID_NDK_VERSION}\")\n"
"set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS \"${CMAKE_ANDROID_NDK_DEPRECATED_HEADERS}\")\n"
"set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}\")\n"
"set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED \"${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}\")\n"
@@ -528,3 +599,9 @@ endif()
message(STATUS "Android: Targeting API '${CMAKE_SYSTEM_VERSION}' with architecture '${CMAKE_ANDROID_ARCH}', ABI '${CMAKE_ANDROID_ARCH_ABI}', and processor '${CMAKE_SYSTEM_PROCESSOR}'")
cmake_policy(POP)
+
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/post/Android-Determine.cmake OPTIONAL)
+endif()
diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake
index 5019c28bd..6116ae1c8 100644
--- a/Modules/Platform/Android-Initialize.cmake
+++ b/Modules/Platform/Android-Initialize.cmake
@@ -4,6 +4,12 @@
# When CMAKE_SYSTEM_NAME is "Android", CMakeSystemSpecificInitialize loads this
# module.
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/pre/Android-Initialize.cmake OPTIONAL)
+endif()
+
# Support for NVIDIA Nsight Tegra Visual Studio Edition was previously
# implemented in the CMake VS IDE generators. Avoid interfering with
# that functionality for now.
@@ -17,7 +23,7 @@ if(CMAKE_SYSTEM_VERSION EQUAL 1)
return()
endif()
-set(CMAKE_BUILD_TYPE_INIT Debug)
+set(CMAKE_BUILD_TYPE_INIT "RelWithDebInfo")
# Skip sysroot selection if the NDK has a unified toolchain.
if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
@@ -53,3 +59,9 @@ else()
"Android: No CMAKE_SYSROOT was selected."
)
endif()
+
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/post/Android-Initialize.cmake OPTIONAL)
+endif()
diff --git a/Modules/Platform/Android.cmake b/Modules/Platform/Android.cmake
index 8ffa1b2d3..e4b9a0929 100644
--- a/Modules/Platform/Android.cmake
+++ b/Modules/Platform/Android.cmake
@@ -1,3 +1,9 @@
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/pre/Android.cmake OPTIONAL)
+endif()
+
include(Platform/Linux)
set(ANDROID 1)
@@ -22,3 +28,65 @@ set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "")
if(CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")
set(CMAKE_LINK_LIBRARY_FLAG "")
endif()
+
+# Commonly used Android toolchain files that pre-date CMake upstream support
+# set CMAKE_SYSTEM_VERSION to 1. Avoid interfering with them.
+if(CMAKE_SYSTEM_VERSION EQUAL 1)
+ return()
+endif()
+
+if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+ # Tell CMake not to search host sysroots for headers/libraries.
+
+ # All paths added to CMAKE_SYSTEM_*_PATH below will be rerooted under
+ # CMAKE_FIND_ROOT_PATH. This is set because:
+ # 1. Users may structure their libraries in a way similar to NDK. When they do that,
+ # they can simply append another path to CMAKE_FIND_ROOT_PATH.
+ # 2. CMAKE_FIND_ROOT_PATH must be non-empty for CMAKE_FIND_ROOT_PATH_MODE_* == ONLY
+ # to be meaningful. https://github.com/android-ndk/ndk/issues/890
+ list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/sysroot")
+
+ # Allow users to override these values in case they want more strict behaviors.
+ # For example, they may want to prevent the NDK's libz from being picked up so
+ # they can use their own.
+ # https://github.com/android-ndk/ndk/issues/517
+ if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+ endif()
+
+ if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+ endif()
+
+ if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+ endif()
+
+ if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
+ 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}")
+
+ # Instructs CMake to search the correct API level for libraries.
+ # Besides the paths like <root>/<prefix>/lib/<arch>, cmake also searches <root>/<prefix>.
+ # So we can add the API level specific directory directly.
+ # https://github.com/android/ndk/issues/929
+ list(PREPEND CMAKE_SYSTEM_PREFIX_PATH
+ "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/${CMAKE_SYSTEM_VERSION}"
+ )
+
+ list(APPEND CMAKE_SYSTEM_PROGRAM_PATH "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin")
+endif()
+
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/post/Android.cmake OPTIONAL)
+endif()
diff --git a/Modules/Platform/Android/Determine-Compiler.cmake b/Modules/Platform/Android/Determine-Compiler.cmake
index f9c2d8968..f8eae6221 100644
--- a/Modules/Platform/Android/Determine-Compiler.cmake
+++ b/Modules/Platform/Android/Determine-Compiler.cmake
@@ -7,6 +7,12 @@ if(__ANDROID_DETERMINE_COMPILER)
endif()
set(__ANDROID_DETERMINE_COMPILER 1)
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/pre/Determine-Compiler.cmake OPTIONAL)
+endif()
+
# Support for NVIDIA Nsight Tegra Visual Studio Edition was previously
# implemented in the CMake VS IDE generators. Avoid interfering with
# that functionality for now. Later we may try to integrate this.
@@ -83,3 +89,9 @@ set(CMAKE_${lang}_ANDROID_TOOLCHAIN_SUFFIX \"${_ANDROID_TOOL_${lang}_TOOLCHAIN_S
")
endif()
endmacro()
+
+# Include the NDK hook.
+# It can be used by NDK to inject necessary fixes for an earlier cmake.
+if(CMAKE_ANDROID_NDK)
+ include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/post/Determine-Compiler.cmake OPTIONAL)
+endif()
diff --git a/Modules/Platform/Android/abi-arm64-v8a-Clang.cmake b/Modules/Platform/Android/abi-arm64-v8a-Clang.cmake
index f4717d5f6..c18c0a269 100644
--- a/Modules/Platform/Android/abi-arm64-v8a-Clang.cmake
+++ b/Modules/Platform/Android/abi-arm64-v8a-Clang.cmake
@@ -1,6 +1,3 @@
-# <ndk>/build/core/toolchains/aarch64-linux-android-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "aarch64-none-linux-android")
-
# Suppress -Wl,-z,nocopyreloc flag on arm64-v8a
set(_ANDROID_ABI_INIT_EXE_LDFLAGS_NO_nocopyreloc 1)
diff --git a/Modules/Platform/Android/abi-armeabi-Clang.cmake b/Modules/Platform/Android/abi-armeabi-Clang.cmake
index b857bd373..2b1de03f6 100644
--- a/Modules/Platform/Android/abi-armeabi-Clang.cmake
+++ b/Modules/Platform/Android/abi-armeabi-Clang.cmake
@@ -1,6 +1,3 @@
-# <ndk>/build/core/toolchains/arm-linux-androideabi-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "armv5te-none-linux-androideabi")
-
string(APPEND _ANDROID_ABI_INIT_CFLAGS
" -march=armv5te"
)
diff --git a/Modules/Platform/Android/abi-armeabi-v6-Clang.cmake b/Modules/Platform/Android/abi-armeabi-v6-Clang.cmake
index a7412f5bd..bb176aed5 100644
--- a/Modules/Platform/Android/abi-armeabi-v6-Clang.cmake
+++ b/Modules/Platform/Android/abi-armeabi-v6-Clang.cmake
@@ -1,6 +1,3 @@
-# <ndk>/build/core/toolchains/arm-linux-androideabi-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "armv6-none-linux-androideabi")
-
string(APPEND _ANDROID_ABI_INIT_CFLAGS
" -march=armv6"
)
diff --git a/Modules/Platform/Android/abi-armeabi-v7a-Clang.cmake b/Modules/Platform/Android/abi-armeabi-v7a-Clang.cmake
index e2ab58b32..6feeef685 100644
--- a/Modules/Platform/Android/abi-armeabi-v7a-Clang.cmake
+++ b/Modules/Platform/Android/abi-armeabi-v7a-Clang.cmake
@@ -1,6 +1,3 @@
-# <ndk>/build/core/toolchains/arm-linux-androideabi-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "armv7-none-linux-androideabi")
-
string(APPEND _ANDROID_ABI_INIT_CFLAGS
" -march=armv7-a"
)
diff --git a/Modules/Platform/Android/abi-mips-Clang.cmake b/Modules/Platform/Android/abi-mips-Clang.cmake
index 73adddecf..7df6a3676 100644
--- a/Modules/Platform/Android/abi-mips-Clang.cmake
+++ b/Modules/Platform/Android/abi-mips-Clang.cmake
@@ -1,4 +1 @@
-# <ndk>/build/core/toolchains/mipsel-linux-android-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "mipsel-none-linux-android")
-
include(Platform/Android/abi-common-Clang)
diff --git a/Modules/Platform/Android/abi-mips64-Clang.cmake b/Modules/Platform/Android/abi-mips64-Clang.cmake
index 603f1b209..7df6a3676 100644
--- a/Modules/Platform/Android/abi-mips64-Clang.cmake
+++ b/Modules/Platform/Android/abi-mips64-Clang.cmake
@@ -1,4 +1 @@
-# <ndk>/build/core/toolchains/mips64el-linux-android-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "mips64el-none-linux-android")
-
include(Platform/Android/abi-common-Clang)
diff --git a/Modules/Platform/Android/abi-x86-Clang.cmake b/Modules/Platform/Android/abi-x86-Clang.cmake
index fe7eacef5..7df6a3676 100644
--- a/Modules/Platform/Android/abi-x86-Clang.cmake
+++ b/Modules/Platform/Android/abi-x86-Clang.cmake
@@ -1,4 +1 @@
-# <ndk>/build/core/toolchains/x86-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "i686-none-linux-android")
-
include(Platform/Android/abi-common-Clang)
diff --git a/Modules/Platform/Android/abi-x86_64-Clang.cmake b/Modules/Platform/Android/abi-x86_64-Clang.cmake
index 3cbcd491f..7df6a3676 100644
--- a/Modules/Platform/Android/abi-x86_64-Clang.cmake
+++ b/Modules/Platform/Android/abi-x86_64-Clang.cmake
@@ -1,4 +1 @@
-# <ndk>/build/core/toolchains/x86_64-clang/setup.mk
-set(_ANDROID_ABI_CLANG_TARGET "x86_64-none-linux-android")
-
include(Platform/Android/abi-common-Clang)
diff --git a/Modules/Platform/Apple-IntelLLVM-C.cmake b/Modules/Platform/Apple-IntelLLVM-C.cmake
new file mode 100644
index 000000000..8e7472909
--- /dev/null
+++ b/Modules/Platform/Apple-IntelLLVM-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/Apple-IntelLLVM)
+__apple_compiler_intel_llvm(C)
diff --git a/Modules/Platform/Apple-IntelLLVM-CXX.cmake b/Modules/Platform/Apple-IntelLLVM-CXX.cmake
new file mode 100644
index 000000000..38640e13d
--- /dev/null
+++ b/Modules/Platform/Apple-IntelLLVM-CXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/Apple-IntelLLVM)
+__apple_compiler_intel_llvm(CXX)
diff --git a/Modules/Platform/Apple-IntelLLVM-Fortran.cmake b/Modules/Platform/Apple-IntelLLVM-Fortran.cmake
new file mode 100644
index 000000000..d0486edca
--- /dev/null
+++ b/Modules/Platform/Apple-IntelLLVM-Fortran.cmake
@@ -0,0 +1,8 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include(Platform/Apple-IntelLLVM)
+__apple_compiler_intel_llvm(Fortran)
+
+set(CMAKE_Fortran_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
+set(CMAKE_Fortran_OSX_CURRENT_VERSION_FLAG "-current_version ")
diff --git a/Modules/Platform/Apple-IntelLLVM.cmake b/Modules/Platform/Apple-IntelLLVM.cmake
new file mode 100644
index 000000000..2f9f0cabc
--- /dev/null
+++ b/Modules/Platform/Apple-IntelLLVM.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.
+include_guard()
+
+macro(__apple_compiler_intel_llvm lang)
+ set(CMAKE_${lang}_VERBOSE_FLAG "-v -Wl,-v") # also tell linker to print verbose output
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
+ set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names")
+
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
+ set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
+endmacro()
diff --git a/Modules/Platform/Linux-IntelLLVM-C.cmake b/Modules/Platform/Linux-IntelLLVM-C.cmake
new file mode 100644
index 000000000..5356c4f71
--- /dev/null
+++ b/Modules/Platform/Linux-IntelLLVM-C.cmake
@@ -0,0 +1,3 @@
+include(Platform/Linux-IntelLLVM)
+__linux_compiler_intel_llvm(C)
+set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
diff --git a/Modules/Platform/Linux-IntelLLVM-CXX.cmake b/Modules/Platform/Linux-IntelLLVM-CXX.cmake
new file mode 100644
index 000000000..44ce0e8cd
--- /dev/null
+++ b/Modules/Platform/Linux-IntelLLVM-CXX.cmake
@@ -0,0 +1,3 @@
+include(Platform/Linux-IntelLLVM)
+__linux_compiler_intel_llvm(CXX)
+set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ")
diff --git a/Modules/Platform/Linux-IntelLLVM-Fortran.cmake b/Modules/Platform/Linux-IntelLLVM-Fortran.cmake
new file mode 100644
index 000000000..1cd9b1f81
--- /dev/null
+++ b/Modules/Platform/Linux-IntelLLVM-Fortran.cmake
@@ -0,0 +1,4 @@
+include(Platform/Linux-IntelLLVM)
+__linux_compiler_intel_llvm(Fortran)
+string(APPEND CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS " -nofor-main")
+set(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "")
diff --git a/Modules/Platform/Linux-IntelLLVM.cmake b/Modules/Platform/Linux-IntelLLVM.cmake
new file mode 100644
index 000000000..1363b4427
--- /dev/null
+++ b/Modules/Platform/Linux-IntelLLVM.cmake
@@ -0,0 +1,55 @@
+# 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_INTEL_LLVM)
+ return()
+endif()
+set(__LINUX_COMPILER_INTEL_LLVM 1)
+
+if(NOT XIAR)
+ set(_intel_xiar_hints)
+ foreach(lang C CXX Fortran)
+ if(IS_ABSOLUTE "${CMAKE_${lang}_COMPILER}")
+ get_filename_component(_hint "${CMAKE_${lang}_COMPILER}" PATH)
+ list(APPEND _intel_xiar_hints ${_hint})
+ endif()
+ endforeach()
+ find_program(XIAR NAMES xiar HINTS ${_intel_xiar_hints})
+ mark_as_advanced(XIAR)
+endif()
+
+macro(__linux_compiler_intel_llvm lang)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
+ set(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER NO)
+ set(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER YES)
+ set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-pie")
+ set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-no-pie")
+ set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+
+ # We pass this for historical reasons. Projects may have
+ # executables that use dlopen but do not set ENABLE_EXPORTS.
+ set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
+
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+
+ if(XIAR)
+ # INTERPROCEDURAL_OPTIMIZATION
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO -ipo)
+ set(CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO
+ "${XIAR} cr <TARGET> <LINK_FLAGS> <OBJECTS> "
+ "${XIAR} -s <TARGET> ")
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+ set(_CMAKE_${lang}_IPO_LEGACY_BEHAVIOR YES)
+ else()
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+ endif()
+
+ set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
+endmacro()
diff --git a/Modules/Platform/Linux-NVHPC-C.cmake b/Modules/Platform/Linux-NVHPC-C.cmake
new file mode 100644
index 000000000..4aab32711
--- /dev/null
+++ b/Modules/Platform/Linux-NVHPC-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/Linux-NVHPC)
+__linux_compiler_nvhpc(C)
diff --git a/Modules/Platform/Linux-NVHPC-CXX.cmake b/Modules/Platform/Linux-NVHPC-CXX.cmake
new file mode 100644
index 000000000..57380eb4e
--- /dev/null
+++ b/Modules/Platform/Linux-NVHPC-CXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/Linux-NVHPC)
+__linux_compiler_nvhpc(CXX)
diff --git a/Modules/Platform/Linux-NVHPC-Fortran.cmake b/Modules/Platform/Linux-NVHPC-Fortran.cmake
new file mode 100644
index 000000000..c68430c24
--- /dev/null
+++ b/Modules/Platform/Linux-NVHPC-Fortran.cmake
@@ -0,0 +1,2 @@
+include(Platform/Linux-NVHPC)
+__linux_compiler_nvhpc(Fortran)
diff --git a/Modules/Platform/Linux-NVHPC.cmake b/Modules/Platform/Linux-NVHPC.cmake
new file mode 100644
index 000000000..aad17f1e9
--- /dev/null
+++ b/Modules/Platform/Linux-NVHPC.cmake
@@ -0,0 +1,15 @@
+# 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_NVIDIA)
+ return()
+endif()
+set(__LINUX_COMPILER_NVIDIA 1)
+
+include(Platform/Linux-PGI)
+
+macro(__linux_compiler_nvhpc lang)
+ __linux_compiler_pgi(${lang})
+endmacro()
diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake
index b5d5464ea..23b48bdc7 100644
--- a/Modules/Platform/Linux.cmake
+++ b/Modules/Platform/Linux.cmake
@@ -48,6 +48,7 @@ endif()
# Match multiarch library directory names.
set(CMAKE_LIBRARY_ARCHITECTURE_REGEX "[a-z0-9_]+(-[a-z0-9_]+)?-linux-gnu[a-z0-9_]*")
+set(CMAKE_LIBRARY_ARCHITECTURE_REGEX_VERSIONED "gcc/[a-z0-9_]+(-[a-z0-9_]+)?-linux(-gnu)?/[0-9]+(\\.[0-9]+\\.[0-9]+)*")
include(Platform/UnixPaths)
diff --git a/Modules/Platform/Windows-Clang-C.cmake b/Modules/Platform/Windows-Clang-C.cmake
index d00710579..322e3fb68 100644
--- a/Modules/Platform/Windows-Clang-C.cmake
+++ b/Modules/Platform/Windows-Clang-C.cmake
@@ -1,2 +1,18 @@
include(Platform/Windows-Clang)
__windows_compiler_clang(C)
+
+if("x${MAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+ endif()
+elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_C_DEPFILE_FORMAT gcc)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+ endif()
+endif()
diff --git a/Modules/Platform/Windows-Clang-CXX.cmake b/Modules/Platform/Windows-Clang-CXX.cmake
index f1d40f265..b4aaf1e82 100644
--- a/Modules/Platform/Windows-Clang-CXX.cmake
+++ b/Modules/Platform/Windows-Clang-CXX.cmake
@@ -1,3 +1,19 @@
include(Platform/Windows-Clang)
set(_COMPILE_CXX_MSVC " -TP")
__windows_compiler_clang(CXX)
+
+if("x${MAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+ endif()
+elseif("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_CXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+ endif()
+endif()
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake
index 7697407fd..c508ac1a5 100644
--- a/Modules/Platform/Windows-Clang.cmake
+++ b/Modules/Platform/Windows-Clang.cmake
@@ -27,7 +27,7 @@ macro(__windows_compiler_clang_gnu lang)
set(CMAKE_SHARED_MODULE_SUFFIX ".dll")
set(CMAKE_STATIC_LIBRARY_SUFFIX ".lib")
if(NOT "${lang}" STREQUAL "ASM")
- set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <OBJECT> -MF <DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
endif()
set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
@@ -71,6 +71,9 @@ 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")
+
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)
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -D_DLL -D_MT -Xclang --dependent-lib=msvcrt)
@@ -114,8 +117,10 @@ macro(__enable_llvm_rc_preprocessing clang_option_prefix extra_pp_flags)
set(CMAKE_RC_PREPROCESSOR CMAKE_CXX_COMPILER)
endif()
if(DEFINED CMAKE_RC_PREPROCESSOR)
- set(CMAKE_DEPFILE_FLAGS_RC "${clang_option_prefix}-MD ${clang_option_prefix}-MF ${clang_option_prefix}<DEPFILE>")
- set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_COMMAND> -E cmake_llvm_rc <SOURCE> <OBJECT>.pp <${CMAKE_RC_PREPROCESSOR}> <DEFINES> -DRC_INVOKED <INCLUDES> <FLAGS> ${extra_pp_flags} -E -- <SOURCE> ++ <CMAKE_RC_COMPILER> <DEFINES> -I <SOURCE_DIR> <INCLUDES> /fo <OBJECT> <OBJECT>.pp")
+ set(CMAKE_DEPFILE_FLAGS_RC "${clang_option_prefix}-MD ${clang_option_prefix}-MF ${clang_option_prefix}<DEP_FILE>")
+ # The <FLAGS> are passed to the preprocess and the resource compiler to pick
+ # up the eventual -D / -C options passed through the CMAKE_RC_FLAGS.
+ set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_COMMAND> -E cmake_llvm_rc <SOURCE> <OBJECT>.pp <${CMAKE_RC_PREPROCESSOR}> <DEFINES> -DRC_INVOKED <INCLUDES> <FLAGS> ${extra_pp_flags} -E -- <SOURCE> ++ <CMAKE_RC_COMPILER> <DEFINES> -I <SOURCE_DIR> <INCLUDES> <FLAGS> /fo <OBJECT> <OBJECT>.pp")
if(CMAKE_GENERATOR MATCHES "Ninja")
set(CMAKE_NINJA_CMCLDEPS_RC 0)
set(CMAKE_NINJA_DEP_TYPE_RC gcc)
diff --git a/Modules/Platform/Windows-Embarcadero.cmake b/Modules/Platform/Windows-Embarcadero.cmake
index 59f3ca59f..8f1d02430 100644
--- a/Modules/Platform/Windows-Embarcadero.cmake
+++ b/Modules/Platform/Windows-Embarcadero.cmake
@@ -35,8 +35,8 @@ else()
set(_tR "-tR") # Target uses the dynamic RTL
set(_tW "-tW") # Target is a Windows application
endif()
-set(_COMPILE_C "-c")
-set(_COMPILE_CXX "-P -c")
+set(_COMPILE_C "")
+set(_COMPILE_CXX " -P")
set(CMAKE_LIBRARY_PATH_FLAG "-L")
set(CMAKE_LINK_LIBRARY_FLAG "")
@@ -87,7 +87,7 @@ macro(__embarcadero_language lang)
# place <DEFINES> outside the response file because Borland refuses
# to parse quotes from the response file.
set(CMAKE_${lang}_COMPILE_OBJECT
- "<CMAKE_${lang}_COMPILER> ${_tR} -DWIN32 <DEFINES> <INCLUDES> <FLAGS> -o<OBJECT> ${_COMPILE_${lang}} <SOURCE>"
+ "<CMAKE_${lang}_COMPILER> ${_tR} -DWIN32 <DEFINES> <INCLUDES> <FLAGS> -o<OBJECT>${_COMPILE_${lang}} -c <SOURCE>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE
@@ -98,7 +98,7 @@ macro(__embarcadero_language lang)
# place <DEFINES> outside the response file because Borland refuses
# to parse quotes from the response file.
set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE
- "cpp32 -DWIN32 <DEFINES> <INCLUDES> <FLAGS> -o<PREPROCESSED_SOURCE> ${_COMPILE_${lang}} <SOURCE>"
+ "cpp32 -DWIN32 <DEFINES> <INCLUDES> <FLAGS> -o<PREPROCESSED_SOURCE>${_COMPILE_${lang}} -c <SOURCE>"
)
# Borland >= 5.6 allows -P option for cpp32, <= 5.5 does not
diff --git a/Modules/Platform/Windows-Intel-C.cmake b/Modules/Platform/Windows-Intel-C.cmake
index 06d8f50ff..152b27c30 100644
--- a/Modules/Platform/Windows-Intel-C.cmake
+++ b/Modules/Platform/Windows-Intel-C.cmake
@@ -1,4 +1,27 @@
include(Platform/Windows-Intel)
__windows_compiler_intel(C)
-set(CMAKE_NINJA_DEPTYPE_C intel) # special value handled by CMake
-set(CMAKE_DEPFILE_FLAGS_C "-QMMD -QMT <OBJECT> -QMF <DEPFILE>")
+
+set(CMAKE_DEPFILE_FLAGS_C "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
+set(CMAKE_C_DEPFILE_FORMAT gcc)
+
+if(CMAKE_GENERATOR MATCHES "^Ninja")
+ if(_CMAKE_NINJA_VERSION VERSION_LESS 1.9)
+ # This ninja version is too old to support the Intel depfile format.
+ # Fall back to msvc depfile format.
+ set(CMAKE_DEPFILE_FLAGS_C "/showIncludes")
+ set(CMAKE_C_DEPFILE_FORMAT msvc)
+ endif()
+endif()
+
+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_C_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+if("${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR}" MATCHES " ")
+ # The Intel compiler does not properly escape spaces in a depfile.
+ # Fall back to msvc depfile format.
+ set(CMAKE_DEPFILE_FLAGS_C "/showIncludes")
+ set(CMAKE_C_DEPFILE_FORMAT msvc)
+endif()
diff --git a/Modules/Platform/Windows-Intel-CXX.cmake b/Modules/Platform/Windows-Intel-CXX.cmake
index 666de6ee4..ce33ae186 100644
--- a/Modules/Platform/Windows-Intel-CXX.cmake
+++ b/Modules/Platform/Windows-Intel-CXX.cmake
@@ -1,5 +1,28 @@
include(Platform/Windows-Intel)
set(_COMPILE_CXX " /TP")
__windows_compiler_intel(CXX)
-set(CMAKE_NINJA_DEPTYPE_CXX intel) # special value handled by CMake
-set(CMAKE_DEPFILE_FLAGS_CXX "-QMMD -QMT <OBJECT> -QMF <DEPFILE>")
+
+set(CMAKE_DEPFILE_FLAGS_CXX "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
+set(CMAKE_CXX_DEPFILE_FORMAT gcc)
+
+if(CMAKE_GENERATOR MATCHES "^Ninja")
+ if(_CMAKE_NINJA_VERSION VERSION_LESS 1.9)
+ # This ninja version is too old to support the Intel depfile format.
+ # Fall back to msvc depfile format.
+ set(CMAKE_DEPFILE_FLAGS_CXX "/showIncludes")
+ set(CMAKE_CXX_DEPFILE_FORMAT msvc)
+ endif()
+endif()
+
+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_CXX_DEPENDS_USE_COMPILER TRUE)
+endif()
+
+if("${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR}" MATCHES " ")
+ # The Intel compiler does not properly escape spaces in a depfile.
+ # Fall back to msvc depfile format.
+ set(CMAKE_DEPFILE_FLAGS_CXX "/showIncludes")
+ set(CMAKE_CXX_DEPFILE_FORMAT msvc)
+endif()
diff --git a/Modules/Platform/Windows-Intel.cmake b/Modules/Platform/Windows-Intel.cmake
index 5d8f7fc35..01f8dd0b1 100644
--- a/Modules/Platform/Windows-Intel.cmake
+++ b/Modules/Platform/Windows-Intel.cmake
@@ -8,6 +8,20 @@ if(__WINDOWS_INTEL)
endif()
set(__WINDOWS_INTEL 1)
+
+if (CMAKE_GENERATOR MATCHES "^Ninja")
+ # retrieve ninja version to enable dependencies configuration
+ # against Ninja capabilities
+ execute_process(COMMAND "${CMAKE_MAKE_PROGRAM}" --version
+ RESULT_VARIABLE _CMAKE_NINJA_RESULT
+ OUTPUT_VARIABLE _CMAKE_NINJA_VERSION
+ ERROR_VARIABLE _CMAKE_NINJA_VERSION)
+ if (NOT _CMAKE_NINJA_RESULT AND _CMAKE_NINJA_VERSION MATCHES "[0-9]+(\\.[0-9]+)*")
+ set (_CMAKE_NINJA_VERSION "${CMAKE_MATCH_0}")
+ endif()
+ unset(_CMAKE_NINJA_RESULT)
+endif()
+
include(Platform/Windows-MSVC)
macro(__windows_compiler_intel lang)
__windows_compiler_msvc(${lang})
diff --git a/Modules/Platform/Windows-IntelLLVM-ASM.cmake b/Modules/Platform/Windows-IntelLLVM-ASM.cmake
new file mode 100644
index 000000000..f355e49fa
--- /dev/null
+++ b/Modules/Platform/Windows-IntelLLVM-ASM.cmake
@@ -0,0 +1,2 @@
+include(Platform/Windows-IntelLLVM)
+__windows_compiler_intel(ASM)
diff --git a/Modules/Platform/Windows-IntelLLVM-C.cmake b/Modules/Platform/Windows-IntelLLVM-C.cmake
new file mode 100644
index 000000000..93c33648d
--- /dev/null
+++ b/Modules/Platform/Windows-IntelLLVM-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/Windows-IntelLLVM)
+__windows_compiler_intel(C)
diff --git a/Modules/Platform/Windows-IntelLLVM-CXX.cmake b/Modules/Platform/Windows-IntelLLVM-CXX.cmake
new file mode 100644
index 000000000..46678952a
--- /dev/null
+++ b/Modules/Platform/Windows-IntelLLVM-CXX.cmake
@@ -0,0 +1,3 @@
+include(Platform/Windows-IntelLLVM)
+set(_COMPILE_CXX " /TP")
+__windows_compiler_intel(CXX)
diff --git a/Modules/Platform/Windows-IntelLLVM-Fortran.cmake b/Modules/Platform/Windows-IntelLLVM-Fortran.cmake
new file mode 100644
index 000000000..06d0a00d1
--- /dev/null
+++ b/Modules/Platform/Windows-IntelLLVM-Fortran.cmake
@@ -0,0 +1,44 @@
+include(Platform/Windows-IntelLLVM)
+set(CMAKE_BUILD_TYPE_INIT Debug)
+set(_COMPILE_Fortran " /fpp")
+set(CMAKE_Fortran_MODDIR_FLAG "-module:")
+set(CMAKE_Fortran_STANDARD_LIBRARIES_INIT "user32.lib")
+__windows_compiler_intel(Fortran)
+if(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
+ set(_LIBSDLL "")
+ set(_DBGLIBS "")
+ set(_THREADS "")
+else()
+ set(_LIBSDLL " /libs:dll")
+ set(_DBGLIBS " /dbglibs")
+ set(_THREADS " /threads")
+endif()
+
+cmake_policy(GET CMP0092 _cmp0092)
+if(NOT _cmp0092 STREQUAL "NEW")
+ string(APPEND CMAKE_Fortran_FLAGS_INIT " /W1")
+endif()
+unset(_cmp0092)
+
+string(APPEND CMAKE_Fortran_FLAGS_INIT " /nologo /fpp${_LIBSDLL}${_THREADS}")
+string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " /Od /debug:full${_DBGLIBS}")
+string(APPEND CMAKE_Fortran_FLAGS_MINSIZEREL_INIT " /O1 /DNDEBUG")
+string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " /O2 /DNDEBUG")
+string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " /O2 /debug:full /DNDEBUG")
+unset(_LIBSDLL)
+unset(_DBGLIBS)
+unset(_THREADS)
+
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -threads -libs:static)
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -threads -libs:dll)
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -threads -libs:static -dbglibs)
+set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -threads -libs:dll -dbglibs)
+
+# Intel Fortran for Windows supports single-threaded RTL but it is
+# not implemented by the Visual Studio integration.
+if(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreaded -libs:static)
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreadedDLL -libs:dll)
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreadedDebug -libs:static -dbglibs)
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_SingleThreadedDebugDLL -libs:dll -dbglibs)
+endif()
diff --git a/Modules/Platform/Windows-IntelLLVM.cmake b/Modules/Platform/Windows-IntelLLVM.cmake
new file mode 100644
index 000000000..b9ea03799
--- /dev/null
+++ b/Modules/Platform/Windows-IntelLLVM.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(__WINDOWS_INTEL)
+ return()
+endif()
+set(__WINDOWS_INTEL 1)
+
+include(Platform/Windows-MSVC)
+macro(__windows_compiler_intel lang)
+ __windows_compiler_msvc(${lang})
+
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
+ set(CMAKE_${lang}_DEPFILE_FORMAT gcc)
+endmacro()
diff --git a/Modules/Platform/Windows-MSVC-C.cmake b/Modules/Platform/Windows-MSVC-C.cmake
index cbe1586e1..67b68277d 100644
--- a/Modules/Platform/Windows-MSVC-C.cmake
+++ b/Modules/Platform/Windows-MSVC-C.cmake
@@ -3,3 +3,10 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 18.0)
set(_FS_C " /FS")
endif()
__windows_compiler_msvc(C)
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+endif()
diff --git a/Modules/Platform/Windows-MSVC-CXX.cmake b/Modules/Platform/Windows-MSVC-CXX.cmake
index 0e8500532..6fea6174a 100644
--- a/Modules/Platform/Windows-MSVC-CXX.cmake
+++ b/Modules/Platform/Windows-MSVC-CXX.cmake
@@ -4,3 +4,10 @@ if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0)
set(_FS_CXX " /FS")
endif()
__windows_compiler_msvc(CXX)
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+endif()
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index bd0871843..e384af456 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -154,7 +154,9 @@ set(CMAKE_BUILD_TYPE_INIT Debug)
# Compute an architecture family from the architecture id.
foreach(lang C CXX)
set(_MSVC_${lang}_ARCHITECTURE_FAMILY "${MSVC_${lang}_ARCHITECTURE_ID}")
- if(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^ARM64")
+ if(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^ARM64EC")
+ set(_MSVC_${lang}_ARCHITECTURE_FAMILY "ARM64EC")
+ elseif(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^ARM64")
set(_MSVC_${lang}_ARCHITECTURE_FAMILY "ARM64")
elseif(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^ARM")
set(_MSVC_${lang}_ARCHITECTURE_FAMILY "ARM")
@@ -163,6 +165,14 @@ foreach(lang C CXX)
endif()
endforeach()
+cmake_policy(GET CMP0117 __WINDOWS_MSVC_CMP0117)
+if(__WINDOWS_MSVC_CMP0117 STREQUAL "NEW")
+ set(_GR "")
+else()
+ set(_GR " /GR")
+endif()
+unset(__WINDOWS_MSVC_CMP0117)
+
if(WINCE)
foreach(lang C CXX)
string(TOUPPER "${_MSVC_${lang}_ARCHITECTURE_FAMILY}" _MSVC_${lang}_ARCHITECTURE_FAMILY_UPPER)
@@ -182,7 +192,7 @@ if(WINCE)
set(_RTC1 "")
set(_FLAGS_C "")
- set(_FLAGS_CXX " /GR /EHsc")
+ set(_FLAGS_CXX "${_GR} /EHsc")
foreach(lang C CXX)
if(_MSVC_${lang}_ARCHITECTURE_FAMILY STREQUAL "ARM")
@@ -204,7 +214,7 @@ if(WINCE)
elseif(WINDOWS_PHONE OR WINDOWS_STORE)
set(_PLATFORM_DEFINES "/DWIN32")
set(_FLAGS_C " /DUNICODE /D_UNICODE")
- set(_FLAGS_CXX " /DUNICODE /D_UNICODE /GR /EHsc")
+ set(_FLAGS_CXX " /DUNICODE /D_UNICODE${_GR} /EHsc")
if(WINDOWS_STORE AND MSVC_VERSION GREATER 1899)
set(CMAKE_C_STANDARD_LIBRARIES_INIT "WindowsApp.lib")
elseif(WINDOWS_PHONE)
@@ -216,7 +226,9 @@ elseif(WINDOWS_PHONE OR WINDOWS_STORE)
endif()
else()
set(_PLATFORM_DEFINES "/DWIN32")
-
+ if((_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64EC") OR (_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64EC"))
+ set(_PLATFORM_DEFINES "${_PLATFORM_DEFINES} /D_AMD64_ /DAMD64 /D_ARM64EC_ /DARM64EC /D_ARM64EC_WORKAROUND_")
+ endif()
if(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM")
set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib")
elseif(MSVC_VERSION GREATER 1310)
@@ -226,12 +238,12 @@ else()
set(_FLAGS_CXX " -frtti -fexceptions")
else()
set(_RTC1 "/RTC1")
- set(_FLAGS_CXX " /GR /EHsc")
+ set(_FLAGS_CXX "${_GR} /EHsc")
endif()
set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")
else()
set(_RTC1 "/GZ")
- set(_FLAGS_CXX " /GR /GX")
+ set(_FLAGS_CXX "${_GR} /GX")
set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib")
endif()
@@ -241,6 +253,8 @@ else()
endif()
endif()
+unset(_GR)
+
set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}")
# executable linker flags
@@ -251,6 +265,8 @@ if(MSVC_C_ARCHITECTURE_ID)
set(_MACHINE_ARCH_FLAG "/machine:THUMB")
elseif(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64")
set(_MACHINE_ARCH_FLAG "/machine:ARM64")
+ elseif(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64EC")
+ set(_MACHINE_ARCH_FLAG "/machine:ARM64EC")
elseif(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM")
set(_MACHINE_ARCH_FLAG "/machine:ARM")
else()
@@ -261,6 +277,8 @@ elseif(MSVC_CXX_ARCHITECTURE_ID)
set(_MACHINE_ARCH_FLAG "/machine:THUMB")
elseif(_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64")
set(_MACHINE_ARCH_FLAG "/machine:ARM64")
+ elseif(_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64EC")
+ set(_MACHINE_ARCH_FLAG "/machine:ARM64EC")
elseif(_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM")
set(_MACHINE_ARCH_FLAG "/machine:ARM")
else()
@@ -295,7 +313,11 @@ foreach(t EXE SHARED MODULE)
string(APPEND CMAKE_${t}_LINKER_FLAGS_RELEASE_INIT " /INCREMENTAL:NO")
endforeach()
-string(APPEND CMAKE_STATIC_LINKER_FLAGS_INIT " ${_MACHINE_ARCH_FLAG}")
+if((_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64EC") OR (_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64EC"))
+ string(APPEND CMAKE_STATIC_LINKER_FLAGS_INIT " /machine:ARM64X")
+else()
+ string(APPEND CMAKE_STATIC_LINKER_FLAGS_INIT " ${_MACHINE_ARCH_FLAG}")
+endif()
unset(_MACHINE_ARCH_FLAG)
cmake_policy(GET CMP0091 __WINDOWS_MSVC_CMP0091)
@@ -425,8 +447,14 @@ macro(__windows_compiler_msvc lang)
set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -MDd)
endif()
set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON)
- set(CMAKE_NINJA_DEPTYPE_${lang} msvc)
+
__windows_compiler_msvc_enable_rc("${_PLATFORM_DEFINES} ${_PLATFORM_DEFINES_${lang}}")
+
+ # define generic information about compiler dependencies
+ if (MSVC_VERSION GREATER 1300)
+ set(CMAKE_DEPFILE_FLAGS_${lang} "/showIncludes")
+ set(CMAKE_${lang}_DEPFILE_FORMAT msvc)
+ endif()
endmacro()
macro(__windows_compiler_msvc_enable_rc flags)
diff --git a/Modules/ProcessorCount.cmake b/Modules/ProcessorCount.cmake
index 43ec889b6..bda23ab68 100644
--- a/Modules/ProcessorCount.cmake
+++ b/Modules/ProcessorCount.cmake
@@ -15,6 +15,9 @@ Otherwise it is set to 0. Currently this functionality is implemented
for AIX, cygwin, FreeBSD, HPUX, Linux, macOS, QNX, Sun and
Windows.
+.. versionchanged:: 3.15
+ On Linux, returns the container CPU count instead of the host CPU count.
+
This function is guaranteed to return a positive integer (>=1) if it
succeeds. It returns 0 if there's a problem determining the processor
count.
diff --git a/Modules/TestBigEndian.cmake b/Modules/TestBigEndian.cmake
index 8a769b7e2..ea8ca73b3 100644
--- a/Modules/TestBigEndian.cmake
+++ b/Modules/TestBigEndian.cmake
@@ -5,19 +5,41 @@
TestBigEndian
-------------
-Define macro to determine endian type
+.. deprecated:: 3.20
-Check if the system is big endian or little endian
+ Supserseded by the :variable:`CMAKE_<LANG>_BYTE_ORDER` variable.
-::
+Check if the target architecture is big endian or little endian.
+
+.. command:: test_big_endian
+
+ .. code-block:: cmake
+
+ test_big_endian(<var>)
+
+ Stores in variable ``<var>`` either 1 or 0 indicating whether the
+ target architecture is big or little endian.
- TEST_BIG_ENDIAN(VARIABLE)
- VARIABLE - variable to store the result to
#]=======================================================================]
+include_guard()
include(CheckTypeSize)
-macro(TEST_BIG_ENDIAN VARIABLE)
+function(TEST_BIG_ENDIAN VARIABLE)
+ if(";${CMAKE_C_BYTE_ORDER};${CMAKE_CXX_BYTE_ORDER};${CMAKE_CUDA_BYTE_ORDER};${CMAKE_OBJC_BYTE_ORDER};${CMAKE_OBJCXX_BYTE_ORDER};" MATCHES ";(BIG_ENDIAN|LITTLE_ENDIAN);")
+ set(order "${CMAKE_MATCH_1}")
+ if(order STREQUAL "BIG_ENDIAN")
+ set("${VARIABLE}" 1 PARENT_SCOPE)
+ else()
+ set("${VARIABLE}" 0 PARENT_SCOPE)
+ endif()
+ else()
+ __TEST_BIG_ENDIAN_LEGACY_IMPL(is_big)
+ set("${VARIABLE}" "${is_big}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+macro(__TEST_BIG_ENDIAN_LEGACY_IMPL VARIABLE)
if(NOT DEFINED HAVE_${VARIABLE})
message(CHECK_START "Check if the system is big endian")
message(CHECK_START "Searching 16 bit integer")
@@ -119,5 +141,3 @@ macro(TEST_BIG_ENDIAN VARIABLE)
endif()
endif()
endmacro()
-
-
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index db3fb953a..120a54c84 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -23,7 +23,8 @@ Creating And Installing JARs
[VERSION <version>]
[OUTPUT_NAME <name>]
[OUTPUT_DIR <dir>]
- [GENERATE_NATIVE_HEADERS <target> [DESTINATION <dir>]]
+ [GENERATE_NATIVE_HEADERS <target>
+ [DESTINATION (<dir>|INSTALL <dir> [BUILD <dir>])]]
)
This command creates a ``<target_name>.jar``. It compiles the given
@@ -36,17 +37,27 @@ compiling the java sources and also to the dependencies of the target.
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``.
-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.
+.. 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.
-``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>``:
@@ -62,6 +73,11 @@ The ``add_jar()`` function sets the following target properties on
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>)
@@ -77,6 +93,9 @@ 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>)
@@ -86,6 +105,14 @@ 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.
+
+Exporting JAR Targets
+^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.7
+
.. code-block:: cmake
install_jar_exports(TARGETS <jars>...
@@ -97,6 +124,9 @@ 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)`.
+.. versionadded:: 3.9
+ The ``NAMESPACE`` option.
+
.. code-block:: cmake
export_jars(TARGETS <jars>...
@@ -106,6 +136,9 @@ that of :command:`install(EXPORTS)`.
This command writes a target export file ``<filename>`` for the named ``<jars>``
targets. Its function is similar to that of :command:`export`.
+.. versionadded:: 3.9
+ The ``NAMESPACE`` option.
+
Examples
""""""""
@@ -196,6 +229,18 @@ native headers can then be used to compile C/C++ sources with the
add_library(bar bar.cpp)
target_link_libraries(bar PRIVATE foo-native)
+.. versionadded:: 3.20
+ It is now possible to export the target generated by
+ ``GENERATE_NATIVE_HEADERS`` option.
+
+ .. 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)
Finding JARs
^^^^^^^^^^^^
@@ -316,17 +361,16 @@ Header Generation
[OUTPUT_NAME <path>|OUTPUT_DIR <path>]
)
-Create C header files from java classes. These files provide the connective glue
-that allow your Java and C code to interact.
+.. versionadded:: 3.4
.. deprecated:: 3.11
-
-.. note::
-
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.
+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:
@@ -406,8 +450,8 @@ function(__java_export_jar VAR TARGET PATH)
endfunction()
# define helper scripts
-set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/javaTargets.cmake.in)
-set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake)
+set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/javaTargets.cmake.in)
+set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJava/Symlinks.cmake)
if (CMAKE_HOST_WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
set(_UseJava_PATH_SEP "$<SEMICOLON>")
@@ -473,7 +517,10 @@ function(add_jar _TARGET_NAME)
if (Java_VERSION VERSION_LESS 1.8)
message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS is not supported with this version of Java.")
endif()
- cmake_parse_arguments (_add_jar_GENERATE_NATIVE_HEADERS "" "DESTINATION" "" ${_add_jar_GENERATE_NATIVE_HEADERS})
+
+ unset (_GENERATE_NATIVE_HEADERS_OUTPUT_DESC)
+
+ cmake_parse_arguments (_add_jar_GENERATE_NATIVE_HEADERS "" "" "DESTINATION" ${_add_jar_GENERATE_NATIVE_HEADERS})
if (NOT _add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS)
message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: missing required argument.")
endif()
@@ -484,11 +531,30 @@ function(add_jar _TARGET_NAME)
endif()
if (NOT _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION)
set (_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir/native_headers")
+ else()
+ list (LENGTH _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION length)
+ if (NOT length EQUAL 1)
+ cmake_parse_arguments (_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION "" "BUILD;INSTALL" "" "${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION}")
+ if (_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_UNPARSED_ARGUMENTS)
+ message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: DESTINATION: ${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_UNPARSED_ARGUMENTS}: unexpected argument(s).")
+ endif()
+ if (NOT _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_INSTALL)
+ message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: DESTINATION: INSTALL sub-option is required.")
+ endif()
+ if (NOT _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD)
+ set(_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir/native_headers")
+ endif()
+ set(_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION "${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD}")
+ set(_GENERATE_NATIVE_HEADERS_OUTPUT_DESC "$<BUILD_INTERFACE:${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_BUILD}>" "$<INSTALL_INTERFACE:${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION_INSTALL}>")
+ endif()
endif()
set (_GENERATE_NATIVE_HEADERS_TARGET ${_add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS})
set (_GENERATE_NATIVE_HEADERS_OUTPUT_DIR "${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION}")
set (_GENERATE_NATIVE_HEADERS -h "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}")
+ if(NOT _GENERATE_NATIVE_HEADERS_OUTPUT_DESC)
+ set(_GENERATE_NATIVE_HEADERS_OUTPUT_DESC "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}")
+ endif()
endif()
if (LIBRARY_OUTPUT_PATH)
@@ -636,7 +702,7 @@ function(add_jar _TARGET_NAME)
COMMAND ${CMAKE_COMMAND}
-DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH}
-DCMAKE_JAR_CLASSES_PREFIX=${CMAKE_JAR_CLASSES_PREFIX}
- -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UseJavaClassFilelist.cmake
+ -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UseJava/ClassFilelist.cmake
DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM
@@ -742,8 +808,9 @@ function(add_jar _TARGET_NAME)
# create an INTERFACE library encapsulating include directory for generated headers
add_library (${_GENERATE_NATIVE_HEADERS_TARGET} INTERFACE)
target_include_directories (${_GENERATE_NATIVE_HEADERS_TARGET} INTERFACE
- "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}"
+ "${_GENERATE_NATIVE_HEADERS_OUTPUT_DESC}"
${JNI_INCLUDE_DIRS})
+ set_property(TARGET ${_GENERATE_NATIVE_HEADERS_TARGET} PROPERTY NATIVE_HEADERS_DIRECTORY "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}")
# this INTERFACE library depends on jar generation
add_dependencies (${_GENERATE_NATIVE_HEADERS_TARGET} ${_TARGET_NAME})
diff --git a/Modules/UseJavaClassFilelist.cmake b/Modules/UseJava/ClassFilelist.cmake
index 1c4baa9d4..aa9e35da8 100644
--- a/Modules/UseJavaClassFilelist.cmake
+++ b/Modules/UseJava/ClassFilelist.cmake
@@ -1,18 +1,9 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#[=======================================================================[.rst:
-UseJavaClassFilelist
---------------------
-
-
-
-
-
-This script create a list of compiled Java class files to be added to
-a jar file. This avoids including cmake files which get created in
-the binary directory.
-#]=======================================================================]
+# This script creates a list of compiled Java class files to be added to
+# a jar file. This avoids including cmake files which get created in
+# the binary directory.
if (CMAKE_JAVA_CLASS_OUTPUT_PATH)
if (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}")
diff --git a/Modules/UseJavaSymlinks.cmake b/Modules/UseJava/Symlinks.cmake
index 3969f54fa..2788195c9 100644
--- a/Modules/UseJavaSymlinks.cmake
+++ b/Modules/UseJava/Symlinks.cmake
@@ -1,16 +1,7 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#[=======================================================================[.rst:
-UseJavaSymlinks
----------------
-
-
-
-
-
-Helper script for UseJava.cmake
-#]=======================================================================]
+# Helper script for UseJava.cmake
if (UNIX AND _JAVA_TARGET_OUTPUT_LINK)
if (_JAVA_TARGET_OUTPUT_NAME)
diff --git a/Modules/javaTargets.cmake.in b/Modules/UseJava/javaTargets.cmake.in
index c5f9c7835..6e14256a1 100644
--- a/Modules/javaTargets.cmake.in
+++ b/Modules/UseJava/javaTargets.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
cmake_policy(PUSH)
cmake_policy(VERSION 2.8)
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index 757e5392b..7d7f7377c 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -12,6 +12,8 @@ Defines the following command for use with ``SWIG``:
.. command:: swig_add_library
+ .. versionadded:: 3.8
+
Define swig module with given name and specified language::
swig_add_library(<name>
@@ -28,13 +30,16 @@ Defines the following command for use with ``SWIG``:
those targets can be used with any command expecting a target (e.g.
:command:`target_link_libraries`).
- .. note::
-
+ .. versionchanged:: 3.13
This command creates a target with the specified ``<name>`` when
policy :policy:`CMP0078` is set to ``NEW``. Otherwise, the legacy
behavior will choose a different target name and store it in the
``SWIG_MODULE_<name>_REAL_NAME`` variable.
+ .. 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.
+
.. note::
For multi-config generators, this module does not support
@@ -43,11 +48,12 @@ Defines the following command for use with ``SWIG``:
.. note::
- For Make-based generators, ``swig_add_library`` does not track file
- dependencies, so depending on the ``<name>_swig_compilation`` custom target
- is required for targets which require the ``swig``-generated files to
- exist. Other generators may depend on the source files that would be
- generated by SWIG.
+ For :ref:`Makefile Generators`, if, for some sources, the
+ ``USE_SWIG_DEPENDENCIES`` property is ``FALSE``, ``swig_add_library`` does
+ not track file dependencies, so depending on the ``<name>_swig_compilation``
+ custom target is required for targets which require the ``swig``-generated
+ files to exist. Other generators may depend on the source files that would
+ be generated by SWIG.
``TYPE``
``SHARED``, ``MODULE`` and ``STATIC`` have the same semantic as for the
@@ -59,10 +65,23 @@ Defines the following command for use with ``SWIG``:
``LANGUAGE``
Specify the target language.
+ .. versionadded:: 3.1
+ Go and Lua language support.
+
+ .. versionadded:: 3.2
+ R language support.
+
+ .. versionadded:: 3.18
+ Fortran language support.
+
``NO_PROXY``
+ .. versionadded:: 3.12
+
Prevent the generation of the wrapper layer (swig ``-noproxy`` option).
``OUTPUT_DIR``
+ .. versionadded:: 3.12
+
Specify where to write the language specific files (swig ``-outdir``
option). If not given, the ``CMAKE_SWIG_OUTDIR`` variable will be used.
If neither is specified, the default depends on the value of the
@@ -75,6 +94,8 @@ Defines the following command for use with ``SWIG``:
``SWIG_SUPPORT_FILES_DIRECTORY`` target property.
``OUTFILE_DIR``
+ .. versionadded:: 3.12
+
Specify an output directory name where the generated source file will be
placed (swig ``-o`` option). If not specified, the ``SWIG_OUTFILE_DIR``
variable will be used. If neither is specified, ``OUTPUT_DIR`` or
@@ -83,8 +104,11 @@ Defines the following command for use with ``SWIG``:
``SOURCES``
List of sources for the library. Files with extension ``.i`` will be
identified as sources for the ``SWIG`` tool. Other files will be handled in
- the standard way. This behavior can be overridden by specifying the variable
- ``SWIG_SOURCE_FILE_EXTENSIONS``.
+ the standard way.
+
+ .. versionadded:: 3.14
+ This behavior can be overridden by specifying the variable
+ ``SWIG_SOURCE_FILE_EXTENSIONS``.
.. note::
@@ -122,12 +146,22 @@ ensure generated files will receive the required settings.
set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON)
swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
+``SWIG_FLAGS``
+ .. deprecated:: 3.12
+ Replaced with the fine-grained properties that follow.
+
+ Pass custom flags to the SWIG executable.
+
``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` and ``COMPILE_OPTIONS``
+ .. versionadded:: 3.12
+
Add custom flags to SWIG compiler and have same semantic as properties
:prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
:prop_sf:`COMPILE_OPTIONS`.
``USE_TARGET_INCLUDE_DIRECTORIES``
+ .. versionadded:: 3.13
+
If set to ``TRUE``, contents of target property
:prop_tgt:`INCLUDE_DIRECTORIES` will be forwarded to ``SWIG`` compiler.
If set to ``FALSE`` target property :prop_tgt:`INCLUDE_DIRECTORIES` will be
@@ -135,13 +169,25 @@ ensure generated files will receive the required settings.
will be considered.
``GENERATED_INCLUDE_DIRECTORIES``, ``GENERATED_COMPILE_DEFINITIONS`` and ``GENERATED_COMPILE_OPTIONS``
+ .. versionadded:: 3.12
+
Add custom flags to the C/C++ generated source. They will fill, respectively,
properties :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
:prop_sf:`COMPILE_OPTIONS` of generated C/C++ file.
``DEPENDS``
+ .. versionadded:: 3.12
+
Specify additional dependencies to the source file.
+``USE_SWIG_DEPENDENCIES``
+ .. 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``.
+
``SWIG_MODULE_NAME``
Specify the actual import name of the module in the target language.
This is required if it cannot be scanned automatically from source
@@ -151,18 +197,21 @@ ensure generated files will receive the required settings.
set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname)
- .. note::
-
+ .. versionchanged:: 3.14
If policy :policy:`CMP0086` is set to ``NEW``, ``-module <module_name>``
is passed to ``SWIG`` compiler.
``OUTPUT_DIR``
+ .. versionadded:: 3.19
+
Specify where to write the language specific files (swig ``-outdir`` option)
for the considered source file. If not specified, the other ways to define
the output directory applies (see ``OUTPUT_DIR`` option of
``swig_add_library()`` command).
``OUTFILE_DIR``
+ .. versionadded:: 3.19
+
Specify an output directory where the generated source file will be placed
(swig ``-o`` option) for the considered source file. If not specified,
``OUTPUT_DIR`` source property will be used. If neither are specified, the
@@ -173,6 +222,8 @@ Target library properties can be set to apply same configuration to all SWIG
input files.
``SWIG_INCLUDE_DIRECTORIES``, ``SWIG_COMPILE_DEFINITIONS`` and ``SWIG_COMPILE_OPTIONS``
+ .. versionadded:: 3.12
+
These properties will be applied to all SWIG input files and have same
semantic as target properties :prop_tgt:`INCLUDE_DIRECTORIES`,
:prop_tgt:`COMPILE_DEFINITIONS` and :prop_tgt:`COMPILE_OPTIONS`.
@@ -185,6 +236,8 @@ input files.
set_property(TARGET mymod PROPERTY SWIG_COMPILE_OPTIONS -bla -blb)
``SWIG_USE_TARGET_INCLUDE_DIRECTORIES``
+ .. versionadded:: 3.13
+
If set to ``TRUE``, contents of target property
:prop_tgt:`INCLUDE_DIRECTORIES` will be forwarded to ``SWIG`` compiler.
If set to ``FALSE`` or not defined, target property
@@ -192,17 +245,23 @@ input files.
overridden by specifying source property ``USE_TARGET_INCLUDE_DIRECTORIES``.
``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS``
+ .. versionadded:: 3.12
+
These properties will populate, respectively, properties
:prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
:prop_sf:`COMPILE_FLAGS` of all generated C/C++ files.
``SWIG_DEPENDS``
+ .. versionadded:: 3.12
+
Add dependencies to all SWIG input files.
The following target properties are output properties and can be used to get
information about support files generated by ``SWIG`` interface compilation.
``SWIG_SUPPORT_FILES``
+ .. versionadded:: 3.12
+
This output property list of wrapper files generated during SWIG compilation.
.. code-block:: cmake
@@ -219,6 +278,8 @@ information about support files generated by ``SWIG`` interface compilation.
``SWIG_SUPPORT_FILES_DIRECTORY`` property to handle support files.
``SWIG_SUPPORT_FILES_DIRECTORY``
+ .. versionadded:: 3.12
+
This output property specifies the directory where support files will be
generated.
@@ -231,6 +292,8 @@ Some variables can be set to customize the behavior of ``swig_add_library``
as well as ``SWIG``:
``UseSWIG_MODULE_VERSION``
+ .. versionadded:: 3.12
+
Specify different behaviors for ``UseSWIG`` module.
* Set to 1 or undefined: Legacy behavior is applied.
@@ -244,6 +307,8 @@ as well as ``SWIG``:
Specify where to write the language specific files (swig ``-outdir`` option).
``SWIG_OUTFILE_DIR``
+ .. versionadded:: 3.8
+
Specify an output directory name where the generated source file will be
placed. If not specified, ``CMAKE_SWIG_OUTDIR`` is used.
@@ -251,6 +316,8 @@ as well as ``SWIG``:
Specify extra dependencies for the generated module for ``<name>``.
``SWIG_SOURCE_FILE_EXTENSIONS``
+ .. versionadded:: 3.14
+
Specify a list of source file extensions to override the default
behavior of considering only ``.i`` files as sources for the ``SWIG``
tool. For example:
@@ -258,6 +325,17 @@ as well as ``SWIG``:
.. code-block:: cmake
set(SWIG_SOURCE_FILE_EXTENSIONS ".i" ".swg")
+
+``SWIG_USE_SWIG_DEPENDENCIES``
+ .. 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``.
+
+ Source file property ``USE_SWIG_DEPENDENCIES``, if not defined, will be
+ initialized with the value of this variable.
#]=======================================================================]
cmake_policy(GET CMP0078 target_name_policy)
@@ -428,6 +506,14 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
set(target_name ${name})
endif()
+ set (use_swig_dependencies ${SWIG_USE_SWIG_DEPENDENCIES})
+ if (CMAKE_GENERATOR MATCHES "Make|Ninja")
+ 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)
+ endif()
+ endif()
+
set (swig_source_file_flags ${CMAKE_SWIG_FLAGS})
# handle various swig compile flags properties
get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES)
@@ -533,7 +619,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})
# dependencies
- set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${target_name},SWIG_DEPENDS>)
+ set (swig_dependencies DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${target_name},SWIG_DEPENDS>)
get_source_file_property(file_depends "${infile}" DEPENDS)
if (file_depends)
list (APPEND swig_dependencies ${file_depends})
@@ -551,10 +637,11 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
unset (swig_copy_command)
endif()
- # IMPLICIT_DEPENDS below can not handle situations where a dependent file is
- # removed. We need an extra step with timestamp and custom target, see #16830
- # As this is needed only for Makefile generator do it conditionally
- if(CMAKE_GENERATOR MATCHES "Make")
+ set(swig_depends_flags)
+ if(NOT use_swig_dependencies AND CMAKE_GENERATOR MATCHES "Make")
+ # IMPLICIT_DEPENDS can not handle situations where a dependent file is
+ # removed. We need an extra step with timestamp and custom target, see #16830
+ # As this is needed only for Makefile generator do it conditionally
__swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE}
"${infile}" "${workingdir}" swig_generated_timestamp)
set(swig_custom_output "${swig_generated_timestamp}")
@@ -562,11 +649,19 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
set(swig_timestamp_command
COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
+ list(APPEND swig_dependencies IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}")
else()
+ set(swig_generated_timestamp)
set(swig_custom_output
"${swig_generated_file_fullname}" ${swig_extra_generated_files})
set(swig_custom_products)
set(swig_timestamp_command)
+ if (use_swig_dependencies)
+ cmake_path(GET infile FILENAME swig_depends_filename)
+ set(swig_depends_filename "${workingdir}/${swig_depends_filename}.d")
+ list(APPEND swig_dependencies DEPFILE "${swig_depends_filename}")
+ set(swig_depends_flags -MF "${swig_depends_filename}" -MD)
+ endif()
endif()
add_custom_command(
OUTPUT ${swig_custom_output}
@@ -581,13 +676,13 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
-outdir "${swig_file_outdir}"
${swig_special_flags}
${swig_extra_flags}
+ ${swig_depends_flags}
"${swig_include_dirs}"
-o "${swig_generated_file_fullname}"
"${swig_source_file_fullname}"
${swig_copy_command}
MAIN_DEPENDENCY "${swig_source_file_fullname}"
- DEPENDS ${swig_dependencies}
- IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
+ ${swig_dependencies}
COMMENT "Swig compile ${infile} for ${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
COMMAND_EXPAND_LISTS)
set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
@@ -608,6 +703,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
endif()
set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE)
+ set(swig_timestamp "${swig_generated_timestamp}" PARENT_SCOPE)
# legacy support
set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
@@ -736,6 +832,15 @@ function(SWIG_ADD_LIBRARY name)
set(SWIG_SOURCE_FILE_EXTENSIONS ".i")
endif()
+ if (CMAKE_GENERATOR MATCHES "Make|Ninja")
+ # For Makefiles and Ninja generators, use SWIG generated dependencies
+ if (NOT DEFINED SWIG_USE_SWIG_DEPENDENCIES)
+ set (SWIG_USE_SWIG_DEPENDENCIES OFF)
+ endif()
+ else()
+ set (SWIG_USE_SWIG_DEPENDENCIES OFF)
+ endif()
+
# Generate a regex out of file extensions.
string(REGEX REPLACE "([$^.*+?|()-])" "\\\\\\1" swig_source_ext_regex "${SWIG_SOURCE_FILE_EXTENSIONS}")
list (JOIN swig_source_ext_regex "|" swig_source_ext_regex)
@@ -763,9 +868,7 @@ function(SWIG_ADD_LIBRARY name)
foreach(swig_it IN LISTS swig_dot_i_sources)
SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}")
list (APPEND swig_generated_sources "${swig_generated_source}")
- if(CMAKE_GENERATOR MATCHES "Make")
- __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} "${swig_it}"
- "${workingdir}" swig_timestamp)
+ if(swig_timestamp)
list (APPEND swig_generated_timestamps "${swig_timestamp}")
endif()
get_source_file_property(swig_source_file_outdir "${swig_it}" OUTPUT_DIR)
@@ -784,7 +887,7 @@ function(SWIG_ADD_LIBRARY name)
${_SAM_TYPE}
${swig_generated_sources}
${swig_other_sources})
- if(CMAKE_GENERATOR MATCHES "Make")
+ if(swig_generated_timestamps)
# see IMPLICIT_DEPENDS above
add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
add_dependencies(${target_name} ${name}_swig_compilation)
diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake
index 5100035b3..5e6828f3b 100644
--- a/Modules/WriteCompilerDetectionHeader.cmake
+++ b/Modules/WriteCompilerDetectionHeader.cmake
@@ -5,6 +5,10 @@
WriteCompilerDetectionHeader
----------------------------
+.. deprecated:: 3.20
+ This module is available only if policy :policy:`CMP0120`
+ is not set to ``NEW``. Do not use it in new code.
+
.. versionadded:: 3.1
This module provides the function ``write_compiler_detection_header()``.
@@ -80,19 +84,28 @@ Possible compiler identifiers are documented with the
Available features in this version of CMake are listed in the
:prop_gbl:`CMAKE_C_KNOWN_FEATURES` and
:prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties.
-The ``{c,cxx}_std_*`` meta-features are ignored if requested.
-
See the :manual:`cmake-compile-features(7)` manual for information on
compile features.
-``BARE_FEATURES`` will define the compatibility macros with the name used in
-newer versions of the language standard, so the code can use the new feature
-name unconditionally.
+.. versionadded:: 3.2
+ Added ``MSVC`` and ``AppleClang`` compiler support.
+
+.. versionadded:: 3.6
+ Added ``Intel`` compiler support.
+
+.. versionchanged:: 3.8
+ The ``{c,cxx}_std_*`` meta-features are ignored if requested.
-``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` cause
-the module to generate conditions that treat unknown compilers as simply
-lacking all features. Without these options the default behavior is to
-generate a ``#error`` for unknown compilers and versions.
+.. versionadded:: 3.8
+ ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` cause
+ the module to generate conditions that treat unknown compilers as simply
+ lacking all features. Without these options the default behavior is to
+ generate a ``#error`` for unknown compilers and versions.
+
+.. versionadded:: 3.12
+ ``BARE_FEATURES`` will define the compatibility macros with the name used in
+ newer versions of the language standard, so the code can use the new feature
+ name unconditionally.
Feature Test Macros
===================
@@ -234,6 +247,18 @@ library:
)
#]=======================================================================]
+# Guard against inclusion by absolute path.
+cmake_policy(GET CMP0120 _WCDH_policy)
+if(_WCDH_policy STREQUAL "NEW")
+ message(FATAL_ERROR "The WriteCompilerDetectionHeader module has been removed by policy CMP0120.")
+elseif(_WCDH_policy STREQUAL "")
+ message(AUTHOR_WARNING
+ "The WriteCompilerDetectionHeader module will be removed by policy CMP0120. "
+ "Projects should be ported away from the module, perhaps by bundling a copy "
+ "of the generated header or using a third-party alternative."
+ )
+endif()
+
include(${CMAKE_CURRENT_LIST_DIR}/CMakeCompilerIdDetection.cmake)
function(_load_compiler_variables CompilerId lang)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index ca56d3af9..6adc9cf6a 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -19,7 +19,7 @@ else()
CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H)
endif()
if(HAVE_ELF_H)
- set(CMAKE_USE_ELF_PARSER 1)
+ set(CMake_USE_ELF_PARSER 1)
elseif(HAIKU)
# On Haiku, we need to include elf32.h from the private headers
set(CMake_HAIKU_INCLUDE_DIRS
@@ -32,13 +32,13 @@ elseif(HAIKU)
unset(CMAKE_REQUIRED_INCLUDES)
if(HAVE_ELF32_H)
- set(CMAKE_USE_ELF_PARSER 1)
+ set(CMake_USE_ELF_PARSER 1)
else()
unset(CMake_HAIKU_INCLUDE_DIRS)
- set(CMAKE_USE_ELF_PARSER)
+ set(CMake_USE_ELF_PARSER)
endif()
else()
- set(CMAKE_USE_ELF_PARSER)
+ set(CMake_USE_ELF_PARSER)
endif()
if(NOT CMake_DEFAULT_RECURSION_LIMIT)
@@ -46,13 +46,19 @@ if(NOT CMake_DEFAULT_RECURSION_LIMIT)
set(CMake_DEFAULT_RECURSION_LIMIT 100)
elseif(MINGW)
set(CMake_DEFAULT_RECURSION_LIMIT 400)
+ elseif(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
+ set(CMake_DEFAULT_RECURSION_LIMIT 600)
else()
set(CMake_DEFAULT_RECURSION_LIMIT 1000)
endif()
endif()
if(APPLE)
- set(CMAKE_USE_MACH_PARSER 1)
+ set(CMake_USE_MACH_PARSER 1)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+ set(CMake_USE_XCOFF_PARSER 1)
endif()
set(EXECUTABLE_OUTPUT_PATH ${CMake_BIN_DIR})
@@ -106,15 +112,20 @@ include_directories(
)
# Check if we can build the ELF parser.
-if(CMAKE_USE_ELF_PARSER)
+if(CMake_USE_ELF_PARSER)
set(ELF_SRCS cmELF.h cmELF.cxx)
endif()
# Check if we can build the Mach-O parser.
-if(CMAKE_USE_MACH_PARSER)
+if(CMake_USE_MACH_PARSER)
set(MACH_SRCS cmMachO.h cmMachO.cxx)
endif()
+# Check if we can build the XCOFF parser.
+if(CMake_USE_XCOFF_PARSER)
+ set(XCOFF_SRCS cmXCOFF.h cmXCOFF.cxx)
+endif()
+
#
# Sources for CMakeLib
#
@@ -181,8 +192,6 @@ set(SRCS
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
cmCacheManager.cxx
cmCacheManager.h
- cmCheckCustomOutputs.h
- cmCheckCustomOutputs.cxx
cmCLocaleEnvironmentScope.h
cmCLocaleEnvironmentScope.cxx
cmCMakePath.h
@@ -227,6 +236,8 @@ set(SRCS
cmDependsJava.h
cmDependsJavaParserHelper.cxx
cmDependsJavaParserHelper.h
+ cmDependsCompiler.cxx
+ cmDependsCompiler.h
cmDocumentation.cxx
cmDocumentationFormatter.cxx
cmDocumentationSection.cxx
@@ -268,6 +279,8 @@ set(SRCS
cmFileAPICodemodel.h
cmFileAPICMakeFiles.cxx
cmFileAPICMakeFiles.h
+ cmFileAPIToolchains.cxx
+ cmFileAPIToolchains.h
cmFileCopier.cxx
cmFileCopier.h
cmFileInstaller.cxx
@@ -444,6 +457,8 @@ set(SRCS
cmTest.h
cmTestGenerator.cxx
cmTestGenerator.h
+ cmTransformDepfile.cxx
+ cmTransformDepfile.h
cmUuid.cxx
cmUVHandlePtr.cxx
cmUVHandlePtr.h
@@ -459,6 +474,7 @@ set(SRCS
cmWorkerPool.h
cmWorkingDirectory.cxx
cmWorkingDirectory.h
+ ${XCOFF_SRCS}
cmXMLParser.cxx
cmXMLParser.h
cmXMLSafe.cxx
@@ -508,6 +524,8 @@ set(SRCS
cmCMakeLanguageCommand.h
cmCMakeMinimumRequired.cxx
cmCMakeMinimumRequired.h
+ cmCMakePathCommand.h
+ cmCMakePathCommand.cxx
cmCMakePolicyCommand.cxx
cmCMakePolicyCommand.h
cmConditionEvaluator.cxx
@@ -833,6 +851,7 @@ endif()
# Ninja support
set(SRCS ${SRCS}
+ cmScanDepFormat.cxx
cmGlobalNinjaGenerator.cxx
cmGlobalNinjaGenerator.h
cmNinjaTypes.h
@@ -1157,20 +1176,6 @@ add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE})
list(APPEND _tools cmake)
target_link_libraries(cmake CMakeLib)
-add_library(CMakeServerLib
- cmConnection.h cmConnection.cxx
- cmFileMonitor.cxx cmFileMonitor.h
- cmJsonObjectDictionary.h
- cmJsonObjects.h
- cmJsonObjects.cxx
- cmPipeConnection.cxx cmPipeConnection.h
- cmServer.cxx cmServer.h
- cmServerConnection.cxx cmServerConnection.h
- cmServerProtocol.cxx cmServerProtocol.h
- )
-target_link_libraries(CMakeServerLib CMakeLib)
-target_link_libraries(cmake CMakeServerLib)
-
# Build CTest executable
add_executable(ctest ctest.cxx ${MANIFEST_FILE})
list(APPEND _tools ctest)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index c1db62b8d..a0713baf7 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 19)
-set(CMake_VERSION_PATCH 8)
+set(CMake_VERSION_MINOR 20)
+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 [==[c9b27dace7 CMake 3.19.8]==])
+ set(git_info [==[b7b0fb4303 CMake 3.20.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/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx
index 20d392d21..87ebbfeb9 100644
--- a/Source/CPack/IFW/cmCPackIFWCommon.cxx
+++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx
@@ -44,7 +44,7 @@ bool cmCPackIFWCommon::IsSetToEmpty(const std::string& op) const
: false;
}
-bool cmCPackIFWCommon::IsVersionLess(const char* version)
+bool cmCPackIFWCommon::IsVersionLess(const char* version) const
{
if (!this->Generator) {
return false;
@@ -54,7 +54,7 @@ bool cmCPackIFWCommon::IsVersionLess(const char* version)
cmSystemTools::OP_LESS, this->Generator->FrameworkVersion.data(), version);
}
-bool cmCPackIFWCommon::IsVersionGreater(const char* version)
+bool cmCPackIFWCommon::IsVersionGreater(const char* version) const
{
if (!this->Generator) {
return false;
@@ -65,7 +65,7 @@ bool cmCPackIFWCommon::IsVersionGreater(const char* version)
version);
}
-bool cmCPackIFWCommon::IsVersionEqual(const char* version)
+bool cmCPackIFWCommon::IsVersionEqual(const char* version) const
{
if (!this->Generator) {
return false;
@@ -118,7 +118,7 @@ void cmCPackIFWCommon::ExpandListArgument(
}
}
-void cmCPackIFWCommon::WriteGeneratedByToStrim(cmXMLWriter& xout)
+void cmCPackIFWCommon::WriteGeneratedByToStrim(cmXMLWriter& xout) const
{
if (!this->Generator) {
return;
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h
index 95ed21370..42deda4ea 100644
--- a/Source/CPack/IFW/cmCPackIFWCommon.h
+++ b/Source/CPack/IFW/cmCPackIFWCommon.h
@@ -34,17 +34,17 @@ public:
/**
* Compare \a version with QtIFW framework version
*/
- bool IsVersionLess(const char* version);
+ bool IsVersionLess(const char* version) const;
/**
* Compare \a version with QtIFW framework version
*/
- bool IsVersionGreater(const char* version);
+ bool IsVersionGreater(const char* version) const;
/**
* Compare \a version with QtIFW framework version
*/
- bool IsVersionEqual(const char* version);
+ bool IsVersionEqual(const char* version) const;
/** Expand the list argument containing the map of the key-value pairs.
* If the number of elements is odd, then the first value is used as the
@@ -64,7 +64,7 @@ public:
cmCPackIFWGenerator* Generator;
protected:
- void WriteGeneratedByToStrim(cmXMLWriter& xout);
+ void WriteGeneratedByToStrim(cmXMLWriter& xout) const;
};
#define cmCPackIFWLogger(logType, msg) \
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index 4bad598e9..bf8b457b4 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -66,7 +66,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
this->Publisher = optIFW_PACKAGE_PUBLISHER;
} else if (const char* optPACKAGE_VENDOR =
- GetOption("CPACK_PACKAGE_VENDOR")) {
+ this->GetOption("CPACK_PACKAGE_VENDOR")) {
this->Publisher = optPACKAGE_VENDOR;
}
@@ -174,6 +174,35 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
this->WizardDefaultHeight = option;
}
+ // WizardShowPageList
+ if (const char* option =
+ this->GetOption("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) {
+ if (!this->IsVersionLess("4.0")) {
+ if (this->IsSetToOff("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) {
+ this->WizardShowPageList = "false";
+ } else if (this->IsOn("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) {
+ this->WizardShowPageList = "true";
+ } else {
+ this->WizardShowPageList.clear();
+ }
+ } else {
+ std::string currentVersionMsg;
+ if (this->Generator) {
+ currentVersionMsg =
+ "QtIFW version " + this->Generator->FrameworkVersion;
+ } else {
+ currentVersionMsg = "an older QtIFW version";
+ }
+ cmCPackIFWLogger(
+ WARNING,
+ "Option CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST is set to \""
+ << option
+ << "\", but it is only supported with QtIFW version 4.0 or later. "
+ "It is being ignored because you are using "
+ << currentVersionMsg << std::endl);
+ }
+ }
+
// TitleColor
if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
this->TitleColor = option;
@@ -184,7 +213,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
this->StartMenuDir = optIFW_START_MENU_DIR;
} else {
- this->StartMenuDir = Name;
+ this->StartMenuDir = this->Name;
}
// Default target directory for installation
@@ -255,9 +284,8 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
class cmCPackIFWResourcesParser : public cmXMLParser
{
public:
- cmCPackIFWResourcesParser(cmCPackIFWInstaller* i)
+ explicit cmCPackIFWResourcesParser(cmCPackIFWInstaller* i)
: installer(i)
- , file(false)
{
this->path = i->Directory + "/resources";
}
@@ -276,14 +304,16 @@ public:
}
cmCPackIFWInstaller* installer;
- bool file, hasFiles, hasErrors;
+ bool file = false;
+ bool hasFiles = false;
+ bool hasErrors = false;
std::string path, basePath;
protected:
void StartElement(const std::string& name, const char** /*atts*/) override
{
this->file = name == "file";
- if (file) {
+ if (this->file) {
this->hasFiles = true;
}
}
@@ -317,7 +347,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
xout.StartDocument();
- WriteGeneratedByToStrim(xout);
+ this->WriteGeneratedByToStrim(xout);
xout.StartElement("Installer");
@@ -408,6 +438,11 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
xout.Element("WizardDefaultHeight", this->WizardDefaultHeight);
}
+ // WizardShowPageList
+ if (!this->IsVersionLess("4.0") && !this->WizardShowPageList.empty()) {
+ xout.Element("WizardShowPageList", this->WizardShowPageList);
+ }
+
// TitleColor
if (!this->TitleColor.empty()) {
xout.Element("TitleColor", this->TitleColor);
@@ -510,7 +545,7 @@ void cmCPackIFWInstaller::GeneratePackageFiles()
package.ConfigureFromGroup(option);
std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
- if (!GetOption(forcedOption)) {
+ if (!this->GetOption(forcedOption)) {
package.ForcedInstallation = "true";
}
} else {
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
index 6f398e308..a031fc268 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.h
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -80,6 +80,10 @@ public:
/// Wizard height
std::string WizardDefaultHeight;
+ /// Set to false if the widget listing installer pages on the left side
+ /// of the wizard should not be shown
+ std::string WizardShowPageList;
+
/// Title color
std::string TitleColor;
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
index 56a74c58b..c4bd7f115 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -337,7 +337,7 @@ int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName)
group.Name = groupName;
- if (Generator) {
+ if (this->Generator) {
this->Name = this->Generator->GetGroupPackageName(&group);
} else {
this->Name = group.Name;
@@ -530,7 +530,7 @@ void cmCPackIFWPackage::GeneratePackageFile()
xout.StartDocument();
- WriteGeneratedByToStrim(xout);
+ this->WriteGeneratedByToStrim(xout);
xout.StartElement("Package");
@@ -577,7 +577,7 @@ void cmCPackIFWPackage::GeneratePackageFile()
}
// User Interfaces (copy to meta dir)
- std::vector<std::string> userInterfaces = UserInterfaces;
+ std::vector<std::string> userInterfaces = this->UserInterfaces;
for (std::string& userInterface : userInterfaces) {
std::string name = cmSystemTools::GetFilenameName(userInterface);
std::string path = this->Directory + "/meta/" + name;
@@ -593,7 +593,7 @@ void cmCPackIFWPackage::GeneratePackageFile()
}
// Translations (copy to meta dir)
- std::vector<std::string> translations = Translations;
+ std::vector<std::string> translations = this->Translations;
for (std::string& translation : translations) {
std::string name = cmSystemTools::GetFilenameName(translation);
std::string path = this->Directory + "/meta/" + name;
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h
index dbd554054..0cc6f2fdf 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.h
+++ b/Source/CPack/IFW/cmCPackIFWPackage.h
@@ -53,7 +53,7 @@ public:
bool operator<(const DependenceStruct& other) const
{
- return Name < other.Name;
+ return this->Name < other.Name;
}
};
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx
index f5e87443b..7ec225686 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.cxx
+++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx
@@ -46,9 +46,9 @@ bool cmCPackIFWRepository::ConfigureFromOptions()
// Update
if (this->IsOn(prefix + "ADD")) {
this->Update = cmCPackIFWRepository::Add;
- } else if (IsOn(prefix + "REMOVE")) {
+ } else if (this->IsOn(prefix + "REMOVE")) {
this->Update = cmCPackIFWRepository::Remove;
- } else if (IsOn(prefix + "REPLACE")) {
+ } else if (this->IsOn(prefix + "REPLACE")) {
this->Update = cmCPackIFWRepository::Replace;
} else {
this->Update = cmCPackIFWRepository::None;
@@ -199,7 +199,7 @@ bool cmCPackIFWRepository::PatchUpdatesXml()
return cmSystemTools::RenameFile(updatesPatchXml, updatesXml);
}
-void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout)
+void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout) const
{
xout.StartElement("Repository");
@@ -225,7 +225,7 @@ void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout)
xout.EndElement();
}
-void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout)
+void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout) const
{
xout.StartElement("Repository");
@@ -247,7 +247,7 @@ void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout)
if (this->Update == cmCPackIFWRepository::Add ||
this->Update == cmCPackIFWRepository::Remove) {
xout.Attribute("url", this->Url);
- } else if (Update == cmCPackIFWRepository::Replace) {
+ } else if (this->Update == cmCPackIFWRepository::Replace) {
xout.Attribute("oldUrl", this->OldUrl);
xout.Attribute("newUrl", this->NewUrl);
}
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h
index 21afd8bdb..015345240 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.h
+++ b/Source/CPack/IFW/cmCPackIFWRepository.h
@@ -76,8 +76,8 @@ public:
bool PatchUpdatesXml();
- void WriteRepositoryConfig(cmXMLWriter& xout);
- void WriteRepositoryUpdate(cmXMLWriter& xout);
+ void WriteRepositoryConfig(cmXMLWriter& xout) const;
+ void WriteRepositoryUpdate(cmXMLWriter& xout) const;
void WriteRepositoryUpdates(cmXMLWriter& xout);
RepositoriesVector RepositoryUpdate;
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 967cc6060..7fd12dd4c 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -80,10 +80,10 @@ std::string cmCPackArchiveGenerator::GetArchiveComponentFileName(
packageFileName +=
this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME");
} else if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
- packageFileName += GetComponentPackageFileName(
+ packageFileName += this->GetComponentPackageFileName(
this->GetOption("CPACK_ARCHIVE_FILE_NAME"), component, isGroupName);
} else {
- packageFileName += GetComponentPackageFileName(
+ packageFileName += this->GetComponentPackageFileName(
this->GetOption("CPACK_PACKAGE_FILE_NAME"), component, isGroupName);
}
@@ -181,7 +181,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
{
- packageFileNames.clear();
+ this->packageFileNames.clear();
// The default behavior is to have one package by component group
// unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
if (!ignoreGroup) {
@@ -189,7 +189,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging component group: " << compG.first << std::endl);
// Begin the archive for this group
- std::string packageFileName = std::string(toplevel) + "/" +
+ std::string packageFileName = std::string(this->toplevel) + "/" +
this->GetArchiveComponentFileName(compG.first, true);
// open a block in order to automatically close archive
@@ -199,11 +199,11 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
// now iterate over the component of this group
for (cmCPackComponent* comp : (compG.second).Components) {
// Add the files of this component to the archive
- addOneComponentToArchive(archive, comp);
+ this->addOneComponentToArchive(archive, comp);
}
}
// add the generated package to package file names list
- packageFileNames.push_back(std::move(packageFileName));
+ this->packageFileNames.push_back(std::move(packageFileName));
}
// Handle Orphan components (components not belonging to any groups)
for (auto& comp : this->Components) {
@@ -217,7 +217,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
<< std::endl);
std::string localToplevel(
this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
- std::string packageFileName = std::string(toplevel);
+ std::string packageFileName = std::string(this->toplevel);
localToplevel += "/" + comp.first;
packageFileName +=
@@ -226,10 +226,10 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
{
DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
// Add the files of this component to the archive
- addOneComponentToArchive(archive, &(comp.second));
+ this->addOneComponentToArchive(archive, &(comp.second));
}
// add the generated package to package file names list
- packageFileNames.push_back(std::move(packageFileName));
+ this->packageFileNames.push_back(std::move(packageFileName));
}
}
}
@@ -238,7 +238,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
else {
for (auto& comp : this->Components) {
std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
- std::string packageFileName = std::string(toplevel);
+ std::string packageFileName = std::string(this->toplevel);
localToplevel += "/" + comp.first;
packageFileName +=
@@ -247,10 +247,10 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
{
DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
// Add the files of this component to the archive
- addOneComponentToArchive(archive, &(comp.second));
+ this->addOneComponentToArchive(archive, &(comp.second));
}
// add the generated package to package file names list
- packageFileNames.push_back(std::move(packageFileName));
+ this->packageFileNames.push_back(std::move(packageFileName));
}
}
return 1;
@@ -259,17 +259,17 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
int cmCPackArchiveGenerator::PackageComponentsAllInOne()
{
// reset the package file names
- packageFileNames.clear();
- packageFileNames.emplace_back(toplevel);
- packageFileNames[0] += "/";
+ this->packageFileNames.clear();
+ this->packageFileNames.emplace_back(this->toplevel);
+ this->packageFileNames[0] += "/";
if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
- packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME");
+ this->packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME");
} else {
- packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ this->packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME");
}
- packageFileNames[0] += this->GetOutputExtension();
+ this->packageFileNames[0] += this->GetOutputExtension();
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging all groups in one package..."
@@ -280,7 +280,7 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne()
// The ALL COMPONENTS in ONE package case
for (auto& comp : this->Components) {
// Add the files of this component to the archive
- addOneComponentToArchive(archive, &(comp.second));
+ this->addOneComponentToArchive(archive, &(comp.second));
}
// archive goes out of scope so it will finalized and closed.
@@ -289,41 +289,42 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne()
int cmCPackArchiveGenerator::PackageFiles()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Toplevel: " << this->toplevel << std::endl);
- if (WantsComponentInstallation()) {
+ if (this->WantsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL COMPONENTS in ONE package has been requested
// then the package file is unique and should be open here.
- if (componentPackageMethod == ONE_PACKAGE) {
- return PackageComponentsAllInOne();
+ if (this->componentPackageMethod == ONE_PACKAGE) {
+ return this->PackageComponentsAllInOne();
}
// CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
// There will be 1 package for each component group
// however one may require to ignore component group and
// in this case you'll get 1 package for each component.
- return PackageComponents(componentPackageMethod ==
- ONE_PACKAGE_PER_COMPONENT);
+ return this->PackageComponents(this->componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
}
// CASE 3 : NON COMPONENT package.
DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
- cmWorkingDirectory workdir(toplevel);
+ cmWorkingDirectory workdir(this->toplevel);
if (workdir.Failed()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Failed to change working directory to "
- << toplevel << " : "
+ << this->toplevel << " : "
<< std::strerror(workdir.GetLastResult()) << std::endl);
return 0;
}
- for (std::string const& file : files) {
+ for (std::string const& file : this->files) {
// Get the relative path to the file
- std::string rp = cmSystemTools::RelativePath(toplevel, file);
+ std::string rp = cmSystemTools::RelativePath(this->toplevel, file);
archive.Add(rp, 0, nullptr, false);
if (!archive) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem while adding file <"
- << file << "> to archive <" << packageFileNames[0]
+ << file << "> to archive <" << this->packageFileNames[0]
<< ">, ERROR = " << archive.GetError() << std::endl);
return 0;
}
@@ -342,7 +343,7 @@ bool cmCPackArchiveGenerator::SupportsComponentInstallation() const
// The Component installation support should only
// be activated if explicitly requested by the user
// (for backward compatibility reason)
- return IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL");
+ return this->IsOn("CPACK_ARCHIVE_COMPONENT_INSTALL");
}
bool cmCPackArchiveGenerator::SetArchiveOptions(cmArchiveWrite* archive)
@@ -352,8 +353,12 @@ bool cmCPackArchiveGenerator::SetArchiveOptions(cmArchiveWrite* archive)
// 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");
}
if (!archive->SetFilterOption("xz", "threads", threads)) {
diff --git a/Source/CPack/cmCPackComponentGroup.cxx b/Source/CPack/cmCPackComponentGroup.cxx
index d40e5fcf8..4305c7eb2 100644
--- a/Source/CPack/cmCPackComponentGroup.cxx
+++ b/Source/CPack/cmCPackComponentGroup.cxx
@@ -25,6 +25,6 @@ unsigned long cmCPackComponent::GetInstalledSize(
unsigned long cmCPackComponent::GetInstalledSizeInKbytes(
const std::string& installDir) const
{
- unsigned long result = (GetInstalledSize(installDir) + 512) / 1024;
+ unsigned long result = (this->GetInstalledSize(installDir) + 512) / 1024;
return result ? result : 1;
}
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 560e5c1dc..e7bcfaca4 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackDebGenerator.h"
+#include <cstdlib>
#include <cstring>
#include <map>
#include <ostream>
@@ -28,7 +29,7 @@ class DebGenerator
public:
DebGenerator(cmCPackLog* logger, std::string outputName, std::string workDir,
std::string topLevelDir, std::string temporaryDir,
- const char* debianCompressionType,
+ const char* debianCompressionType, const char* numThreads,
const char* debianArchiveType,
std::map<std::string, std::string> controlValues,
bool genShLibs, std::string shLibsFilename, bool genPostInst,
@@ -53,6 +54,7 @@ private:
const std::string TopLevelDir;
const std::string TemporaryDir;
const char* DebianArchiveType;
+ int NumThreads;
const std::map<std::string, std::string> ControlValues;
const bool GenShLibs;
const std::string ShLibsFilename;
@@ -69,7 +71,8 @@ private:
DebGenerator::DebGenerator(
cmCPackLog* logger, std::string outputName, std::string workDir,
std::string topLevelDir, std::string temporaryDir,
- const char* debianCompressionType, const char* debianArchiveType,
+ const char* debianCompressionType, const char* numThreads,
+ const char* debianArchiveType,
std::map<std::string, std::string> controlValues, bool genShLibs,
std::string shLibsFilename, bool genPostInst, std::string postInst,
bool genPostRm, std::string postRm, const char* controlExtra,
@@ -96,45 +99,62 @@ DebGenerator::DebGenerator(
}
if (!strcmp(debianCompressionType, "lzma")) {
- CompressionSuffix = ".lzma";
- TarCompressionType = cmArchiveWrite::CompressLZMA;
+ this->CompressionSuffix = ".lzma";
+ this->TarCompressionType = cmArchiveWrite::CompressLZMA;
} else if (!strcmp(debianCompressionType, "xz")) {
- CompressionSuffix = ".xz";
- TarCompressionType = cmArchiveWrite::CompressXZ;
+ this->CompressionSuffix = ".xz";
+ this->TarCompressionType = cmArchiveWrite::CompressXZ;
} else if (!strcmp(debianCompressionType, "bzip2")) {
- CompressionSuffix = ".bz2";
- TarCompressionType = cmArchiveWrite::CompressBZip2;
+ this->CompressionSuffix = ".bz2";
+ this->TarCompressionType = cmArchiveWrite::CompressBZip2;
} else if (!strcmp(debianCompressionType, "gzip")) {
- CompressionSuffix = ".gz";
- TarCompressionType = cmArchiveWrite::CompressGZip;
+ this->CompressionSuffix = ".gz";
+ this->TarCompressionType = cmArchiveWrite::CompressGZip;
} else if (!strcmp(debianCompressionType, "none")) {
- CompressionSuffix.clear();
- TarCompressionType = cmArchiveWrite::CompressNone;
+ this->CompressionSuffix.clear();
+ this->TarCompressionType = cmArchiveWrite::CompressNone;
} else {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error unrecognized compression type: "
<< debianCompressionType << std::endl);
}
+
+ if (numThreads == nullptr) {
+ numThreads = "1";
+ }
+
+ char* endptr;
+ this->NumThreads = static_cast<int>(strtol(numThreads, &endptr, 10));
+ if (numThreads != endptr && *endptr != '\0') {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "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
{
- generateDebianBinaryFile();
- generateControlFile();
- if (!generateDataTar()) {
+ this->generateDebianBinaryFile();
+ this->generateControlFile();
+ if (!this->generateDataTar()) {
return false;
}
- std::string md5Filename = generateMD5File();
- if (!generateControlTar(md5Filename)) {
+ std::string md5Filename = this->generateMD5File();
+ if (!this->generateControlTar(md5Filename)) {
return false;
}
- return generateDeb();
+ return this->generateDeb();
}
void DebGenerator::generateDebianBinaryFile() const
{
// debian-binary file
- const std::string dbfilename = WorkDir + "/debian-binary";
+ const std::string dbfilename = this->WorkDir + "/debian-binary";
cmGeneratedFileStream out;
out.Open(dbfilename, false, true);
out << "2.0\n"; // required for valid debian package
@@ -142,18 +162,18 @@ void DebGenerator::generateDebianBinaryFile() const
void DebGenerator::generateControlFile() const
{
- std::string ctlfilename = WorkDir + "/control";
+ std::string ctlfilename = this->WorkDir + "/control";
cmGeneratedFileStream out;
out.Open(ctlfilename, false, true);
- for (auto const& kv : ControlValues) {
+ for (auto const& kv : this->ControlValues) {
out << kv.first << ": " << kv.second << "\n";
}
unsigned long totalSize = 0;
{
- std::string dirName = cmStrCat(TemporaryDir, '/');
- for (std::string const& file : PackageFiles) {
+ std::string dirName = cmStrCat(this->TemporaryDir, '/');
+ for (std::string const& file : this->PackageFiles) {
totalSize += cmSystemTools::FileLength(file);
}
}
@@ -162,7 +182,8 @@ void DebGenerator::generateControlFile() const
bool DebGenerator::generateDataTar() const
{
- std::string filename_data_tar = WorkDir + "/data.tar" + CompressionSuffix;
+ std::string filename_data_tar =
+ this->WorkDir + "/data.tar" + this->CompressionSuffix;
cmGeneratedFileStream fileStream_data_tar;
fileStream_data_tar.Open(filename_data_tar, false, true);
if (!fileStream_data_tar) {
@@ -171,8 +192,8 @@ bool DebGenerator::generateDataTar() const
<< filename_data_tar << "\" for writing" << std::endl);
return false;
}
- cmArchiveWrite data_tar(fileStream_data_tar, TarCompressionType,
- DebianArchiveType);
+ cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType,
+ this->DebianArchiveType, 0, this->NumThreads);
data_tar.Open();
// uid/gid should be the one of the root user, and this root user has
@@ -184,16 +205,16 @@ bool DebGenerator::generateDataTar() const
// collect all top level install dirs for that
// e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would
// give /usr and /opt
- size_t topLevelLength = WorkDir.length();
+ size_t topLevelLength = this->WorkDir.length();
cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "WDIR: \"" << WorkDir << "\", length = " << topLevelLength
- << std::endl);
+ "WDIR: \"" << this->WorkDir
+ << "\", length = " << topLevelLength << std::endl);
std::set<std::string> orderedFiles;
// we have to reconstruct the parent folders as well
- for (std::string currentPath : PackageFiles) {
- while (currentPath != WorkDir) {
+ for (std::string currentPath : this->PackageFiles) {
+ while (currentPath != this->WorkDir) {
// the last one IS WorkDir, but we do not want this one:
// XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application
// should not add XXX/application
@@ -235,7 +256,7 @@ bool DebGenerator::generateDataTar() const
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem adding file to tar:"
<< std::endl
- << "#top level directory: " << WorkDir << std::endl
+ << "#top level directory: " << this->WorkDir << std::endl
<< "#file: " << file << std::endl
<< "#error:" << data_tar.GetError() << std::endl);
return false;
@@ -246,13 +267,13 @@ bool DebGenerator::generateDataTar() const
std::string DebGenerator::generateMD5File() const
{
- std::string md5filename = WorkDir + "/md5sums";
+ std::string md5filename = this->WorkDir + "/md5sums";
cmGeneratedFileStream out;
out.Open(md5filename, false, true);
- std::string topLevelWithTrailingSlash = cmStrCat(TemporaryDir, '/');
- for (std::string const& file : PackageFiles) {
+ std::string topLevelWithTrailingSlash = cmStrCat(this->TemporaryDir, '/');
+ for (std::string const& file : this->PackageFiles) {
// hash only regular files
if (cmSystemTools::FileIsDirectory(file) ||
cmSystemTools::FileIsSymlink(file)) {
@@ -281,7 +302,7 @@ std::string DebGenerator::generateMD5File() const
bool DebGenerator::generateControlTar(std::string const& md5Filename) const
{
- std::string filename_control_tar = WorkDir + "/control.tar.gz";
+ std::string filename_control_tar = this->WorkDir + "/control.tar.gz";
cmGeneratedFileStream fileStream_control_tar;
fileStream_control_tar.Open(filename_control_tar, false, true);
@@ -292,7 +313,8 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
return false;
}
cmArchiveWrite control_tar(fileStream_control_tar,
- cmArchiveWrite::CompressGZip, DebianArchiveType);
+ cmArchiveWrite::CompressGZip,
+ this->DebianArchiveType);
control_tar.Open();
// sets permissions and uid/gid for the files
@@ -314,24 +336,25 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
control_tar.SetPermissions(permission644);
// adds control and md5sums
- if (!control_tar.Add(md5Filename, WorkDir.length(), ".") ||
- !control_tar.Add(WorkDir + "/control", WorkDir.length(), ".")) {
+ if (!control_tar.Add(md5Filename, this->WorkDir.length(), ".") ||
+ !control_tar.Add(this->WorkDir + "/control", this->WorkDir.length(),
+ ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error adding file to tar:"
<< std::endl
- << "#top level directory: " << WorkDir << std::endl
+ << "#top level directory: " << this->WorkDir << std::endl
<< "#file: \"control\" or \"md5sums\"" << std::endl
<< "#error:" << control_tar.GetError() << std::endl);
return false;
}
// adds generated shlibs file
- if (GenShLibs) {
- if (!control_tar.Add(ShLibsFilename, WorkDir.length(), ".")) {
+ if (this->GenShLibs) {
+ if (!control_tar.Add(this->ShLibsFilename, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error adding file to tar:"
<< std::endl
- << "#top level directory: " << WorkDir << std::endl
+ << "#top level directory: " << this->WorkDir << std::endl
<< "#file: \"shlibs\"" << std::endl
<< "#error:" << control_tar.GetError() << std::endl);
return false;
@@ -339,13 +362,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
}
// adds LDCONFIG related files
- if (GenPostInst) {
+ if (this->GenPostInst) {
control_tar.SetPermissions(permission755);
- if (!control_tar.Add(PostInst, WorkDir.length(), ".")) {
+ if (!control_tar.Add(this->PostInst, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error adding file to tar:"
<< std::endl
- << "#top level directory: " << WorkDir << std::endl
+ << "#top level directory: " << this->WorkDir << std::endl
<< "#file: \"postinst\"" << std::endl
<< "#error:" << control_tar.GetError() << std::endl);
return false;
@@ -353,13 +376,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
control_tar.SetPermissions(permission644);
}
- if (GenPostRm) {
+ if (this->GenPostRm) {
control_tar.SetPermissions(permission755);
- if (!control_tar.Add(PostRm, WorkDir.length(), ".")) {
+ if (!control_tar.Add(this->PostRm, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error adding file to tar:"
<< std::endl
- << "#top level directory: " << WorkDir << std::endl
+ << "#top level directory: " << this->WorkDir << std::endl
<< "#file: \"postinst\"" << std::endl
<< "#error:" << control_tar.GetError() << std::endl);
return false;
@@ -370,7 +393,7 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
// for the other files, we use
// -either the original permission on the files
// -either a permission strictly defined by the Debian policies
- if (ControlExtra) {
+ if (this->ControlExtra) {
// permissions are now controlled by the original file permissions
static const char* strictFiles[] = { "config", "postinst", "postrm",
@@ -381,19 +404,29 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
// default
control_tar.ClearPermissions();
- std::vector<std::string> controlExtraList = cmExpandedList(ControlExtra);
+ std::vector<std::string> controlExtraList =
+ cmExpandedList(this->ControlExtra);
for (std::string const& i : controlExtraList) {
std::string filenamename = cmsys::SystemTools::GetFilenameName(i);
- std::string localcopy = WorkDir + "/" + filenamename;
+ std::string localcopy = this->WorkDir + "/" + filenamename;
- if (PermissionStrictPolicy) {
+ if (this->PermissionStrictPolicy) {
control_tar.SetPermissions(
setStrictFiles.count(filenamename) ? permission755 : permission644);
}
// if we can copy the file, it means it does exist, let's add it:
+ if (!cmsys::SystemTools::FileExists(i)) {
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "Adding file to tar:" << std::endl
+ << "#top level directory: "
+ << this->WorkDir << std::endl
+ << "#missing file: " << i
+ << std::endl);
+ }
+
if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) {
- control_tar.Add(localcopy, WorkDir.length(), ".");
+ control_tar.Add(localcopy, this->WorkDir.length(), ".");
}
}
}
@@ -408,8 +441,8 @@ bool DebGenerator::generateDeb() const
// difference is that debian uses the BSD ar style archive whereas most
// Linux distro have a GNU ar.
// See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info
- std::string const outputPath = TopLevelDir + "/" + OutputName;
- std::string const tlDir = WorkDir + "/";
+ std::string const outputPath = this->TopLevelDir + "/" + this->OutputName;
+ std::string const tlDir = this->WorkDir + "/";
cmGeneratedFileStream debStream;
debStream.Open(outputPath, false, true);
cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd");
@@ -422,12 +455,13 @@ bool DebGenerator::generateDeb() const
if (!deb.Add(tlDir + "debian-binary", tlDir.length()) ||
!deb.Add(tlDir + "control.tar.gz", tlDir.length()) ||
- !deb.Add(tlDir + "data.tar" + CompressionSuffix, tlDir.length())) {
+ !deb.Add(tlDir + "data.tar" + this->CompressionSuffix, tlDir.length())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error creating debian package:"
<< std::endl
- << "#top level directory: " << TopLevelDir << std::endl
- << "#file: " << OutputName << std::endl
+ << "#top level directory: " << this->TopLevelDir
+ << std::endl
+ << "#file: " << this->OutputName << std::endl
<< "#error:" << deb.GetError() << std::endl);
return false;
}
@@ -455,7 +489,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
int retval = 1;
// Begin the archive for this pack
std::string localToplevel(initialTopLevel);
- std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
+ std::string packageFileName(
+ cmSystemTools::GetParentDirectory(this->toplevel));
std::string outputFileName(
std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + "-" +
packageName + this->GetOutputExtension());
@@ -495,19 +530,20 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
<< std::endl);
return 0;
}
- packageFiles = gl.GetFiles();
+ this->packageFiles = gl.GetFiles();
}
- int res = createDeb();
+ int res = this->createDeb();
if (res != 1) {
retval = 0;
}
// add the generated package to package file names list
packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
- packageFileNames.push_back(std::move(packageFileName));
+ this->packageFileNames.push_back(std::move(packageFileName));
- if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE")) {
+ if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") &&
+ this->GetOption("GEN_DBGSYMDIR")) {
cmsys::Glob gl;
std::string findExpr(this->GetOption("GEN_DBGSYMDIR"));
findExpr += "/*";
@@ -520,9 +556,9 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
<< std::endl);
return 0;
}
- packageFiles = gl.GetFiles();
+ this->packageFiles = gl.GetFiles();
- res = createDbgsymDDeb();
+ res = this->createDbgsymDDeb();
if (res != 1) {
retval = 0;
}
@@ -530,7 +566,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
packageFileName =
cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"));
- packageFileNames.push_back(std::move(packageFileName));
+ this->packageFileNames.push_back(std::move(packageFileName));
}
return retval;
@@ -541,7 +577,7 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
int retval = 1;
/* Reset package file name list it will be populated during the
* component packaging run*/
- packageFileNames.clear();
+ this->packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
// The default behavior is to have one package by component group
@@ -551,7 +587,7 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging component group: " << compG.first << std::endl);
// Begin the archive for this group
- retval &= PackageOnePack(initialTopLevel, compG.first);
+ retval &= this->PackageOnePack(initialTopLevel, compG.first);
}
// Handle Orphan components (components not belonging to any groups)
for (auto const& comp : this->Components) {
@@ -564,7 +600,7 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
<< "> does not belong to any group, package it separately."
<< std::endl);
// Begin the archive for this orphan component
- retval &= PackageOnePack(initialTopLevel, comp.first);
+ retval &= this->PackageOnePack(initialTopLevel, comp.first);
}
}
}
@@ -572,7 +608,7 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
// We build 1 package per component
else {
for (auto const& comp : this->Components) {
- retval &= PackageOnePack(initialTopLevel, comp.first);
+ retval &= this->PackageOnePack(initialTopLevel, comp.first);
}
}
return retval;
@@ -585,7 +621,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
int retval = 1;
/* Reset package file name list it will be populated during the
* component packaging run*/
- packageFileNames.clear();
+ this->packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
@@ -595,7 +631,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
// The ALL GROUPS in ONE package case
std::string localToplevel(initialTopLevel);
- std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
+ std::string packageFileName(
+ cmSystemTools::GetParentDirectory(this->toplevel));
std::string outputFileName(
std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) +
this->GetOutputExtension());
@@ -640,38 +677,38 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
<< std::endl);
return 0;
}
- packageFiles = gl.GetFiles();
+ this->packageFiles = gl.GetFiles();
- int res = createDeb();
+ int res = this->createDeb();
if (res != 1) {
retval = 0;
}
// add the generated package to package file names list
packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
- packageFileNames.push_back(std::move(packageFileName));
+ this->packageFileNames.push_back(std::move(packageFileName));
return retval;
}
int cmCPackDebGenerator::PackageFiles()
{
/* Are we in the component packaging case */
- if (WantsComponentInstallation()) {
+ if (this->WantsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL GROUPS or ALL COMPONENTS in ONE package has been requested
// then the package file is unique and should be open here.
- if (componentPackageMethod == ONE_PACKAGE) {
- return PackageComponentsAllInOne("ALL_COMPONENTS_IN_ONE");
+ if (this->componentPackageMethod == ONE_PACKAGE) {
+ return this->PackageComponentsAllInOne("ALL_COMPONENTS_IN_ONE");
}
// CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
// There will be 1 package for each component group
// however one may require to ignore component group and
// in this case you'll get 1 package for each component.
- return PackageComponents(componentPackageMethod ==
- ONE_PACKAGE_PER_COMPONENT);
+ return this->PackageComponents(this->componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
}
// CASE 3 : NON COMPONENT package.
- return PackageComponentsAllInOne("");
+ return this->PackageComponentsAllInOne("");
}
int cmCPackDebGenerator::createDeb()
@@ -786,16 +823,17 @@ int cmCPackDebGenerator::createDeb()
}
DebGenerator gen(
- Logger, this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"), strGenWDIR,
+ this->Logger, this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"), strGenWDIR,
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
+ this->GetOption("CPACK_THREADS"),
this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, gen_shibs,
shlibsfilename, this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST"), postinst,
this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM"), postrm,
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA"),
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
- packageFiles);
+ this->packageFiles);
if (!gen.generate()) {
return 0;
@@ -841,16 +879,17 @@ int cmCPackDebGenerator::createDbgsymDDeb()
}
DebGenerator gen(
- Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"),
+ this->Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"),
this->GetOption("GEN_DBGSYMDIR"),
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
+ this->GetOption("CPACK_THREADS"),
this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, false, "",
false, "", false, "", nullptr,
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
- packageFiles);
+ this->packageFiles);
if (!gen.generate()) {
return 0;
@@ -860,25 +899,25 @@ int cmCPackDebGenerator::createDbgsymDDeb()
bool cmCPackDebGenerator::SupportsComponentInstallation() const
{
- return IsOn("CPACK_DEB_COMPONENT_INSTALL");
+ return this->IsOn("CPACK_DEB_COMPONENT_INSTALL");
}
std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix(
const std::string& componentName)
{
- if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
+ if (this->componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
return componentName;
}
- if (componentPackageMethod == ONE_PACKAGE) {
+ if (this->componentPackageMethod == ONE_PACKAGE) {
return std::string("ALL_COMPONENTS_IN_ONE");
}
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
std::string groupVar =
"CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
- if (nullptr != GetOption(groupVar)) {
- return std::string(GetOption(groupVar));
+ if (nullptr != this->GetOption(groupVar)) {
+ return std::string(this->GetOption(groupVar));
}
return componentName;
}
diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx
index 0bc845671..e3521a0e5 100644
--- a/Source/CPack/cmCPackExternalGenerator.cxx
+++ b/Source/CPack/cmCPackExternalGenerator.cxx
@@ -95,7 +95,7 @@ int cmCPackExternalGenerator::InstallProjectViaInstallCommands(
bool setDestDir, const std::string& tempInstallDirectory)
{
if (this->StagingEnabled()) {
- return cmCPackGenerator::InstallProjectViaInstallCommands(
+ return this->cmCPackGenerator::InstallProjectViaInstallCommands(
setDestDir, tempInstallDirectory);
}
@@ -106,7 +106,7 @@ int cmCPackExternalGenerator::InstallProjectViaInstallScript(
bool setDestDir, const std::string& tempInstallDirectory)
{
if (this->StagingEnabled()) {
- return cmCPackGenerator::InstallProjectViaInstallScript(
+ return this->cmCPackGenerator::InstallProjectViaInstallScript(
setDestDir, tempInstallDirectory);
}
@@ -118,7 +118,7 @@ int cmCPackExternalGenerator::InstallProjectViaInstalledDirectories(
const mode_t* default_dir_mode)
{
if (this->StagingEnabled()) {
- return cmCPackGenerator::InstallProjectViaInstalledDirectories(
+ return this->cmCPackGenerator::InstallProjectViaInstalledDirectories(
setDestDir, tempInstallDirectory, default_dir_mode);
}
@@ -130,7 +130,7 @@ int cmCPackExternalGenerator::RunPreinstallTarget(
cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
{
if (this->StagingEnabled()) {
- return cmCPackGenerator::RunPreinstallTarget(
+ return this->cmCPackGenerator::RunPreinstallTarget(
installProjectName, installDirectory, globalGenerator, buildConfig);
}
@@ -145,7 +145,7 @@ int cmCPackExternalGenerator::InstallCMakeProject(
std::string& absoluteDestFiles)
{
if (this->StagingEnabled()) {
- return cmCPackGenerator::InstallCMakeProject(
+ return this->cmCPackGenerator::InstallCMakeProject(
setDestDir, installDirectory, baseTempInstallDirectory, default_dir_mode,
component, componentInstall, installSubDirectory, buildConfig,
absoluteDestFiles);
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index a9fe91cd1..3db4162c9 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -60,18 +60,18 @@ int cmCPackGenerator::PrepareNames()
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Create temp directory." << std::endl);
// checks CPACK_SET_DESTDIR support
- if (IsOn("CPACK_SET_DESTDIR")) {
- if (SETDESTDIR_UNSUPPORTED == SupportsSetDestdir()) {
+ if (this->IsOn("CPACK_SET_DESTDIR")) {
+ if (SETDESTDIR_UNSUPPORTED == this->SupportsSetDestdir()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_SET_DESTDIR is set to ON but the '"
- << Name << "' generator does NOT support it."
+ << this->Name << "' generator does NOT support it."
<< std::endl);
return 0;
}
- if (SETDESTDIR_SHOULD_NOT_BE_USED == SupportsSetDestdir()) {
+ if (SETDESTDIR_SHOULD_NOT_BE_USED == this->SupportsSetDestdir()) {
cmCPackLogger(cmCPackLog::LOG_WARNING,
"CPACK_SET_DESTDIR is set to ON but it is "
- << "usually a bad idea to do that with '" << Name
+ << "usually a bad idea to do that with '" << this->Name
<< "' generator. Use at your own risk." << std::endl);
}
}
@@ -380,8 +380,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
<< std::endl);
return 0;
}
- files = gl.GetFiles();
- for (std::string const& gf : files) {
+ this->files = gl.GetFiles();
+ for (std::string const& gf : this->files) {
bool skip = false;
std::string inFile = gf;
if (cmSystemTools::FileIsDirectory(gf)) {
@@ -763,7 +763,7 @@ int cmCPackGenerator::InstallCMakeProject(
// one install directory for each component **GROUP**
// instead of the default
// one install directory for each component.
- tempInstallDirectory += GetComponentInstallDirNameSuffix(component);
+ tempInstallDirectory += this->GetComponentInstallDirNameSuffix(component);
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
tempInstallDirectory += "/";
tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
@@ -897,7 +897,7 @@ int cmCPackGenerator::InstallCMakeProject(
// ABSOLUTE INSTALL DESTINATION or CPack has been asked for
// then ask cmake_install.cmake script to error out
// as soon as it occurs (before installing file)
- if (!SupportsAbsoluteDestination() ||
+ if (!this->SupportsAbsoluteDestination() ||
this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
}
@@ -933,7 +933,7 @@ int cmCPackGenerator::InstallCMakeProject(
localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit);
localFileName =
localFileName.substr(localFileName.find_first_not_of('/'));
- Components[component].Files.push_back(localFileName);
+ this->Components[component].Files.push_back(localFileName);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Adding file <" << localFileName << "> to component <"
<< component << ">" << std::endl);
@@ -952,7 +952,7 @@ int cmCPackGenerator::InstallCMakeProject(
if (componentInstall) {
std::string absoluteDestFileComponent =
std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" +
- GetComponentInstallDirNameSuffix(component);
+ this->GetComponentInstallDirNameSuffix(component);
if (nullptr != this->GetOption(absoluteDestFileComponent)) {
std::string absoluteDestFilesListComponent =
cmStrCat(this->GetOption(absoluteDestFileComponent), ';', *d);
@@ -1073,17 +1073,17 @@ int cmCPackGenerator::DoPackage()
}
// The files to be installed
- files = gl.GetFiles();
+ this->files = gl.GetFiles();
- packageFileNames.clear();
+ this->packageFileNames.clear();
/* Put at least one file name into the list of
* wanted packageFileNames. The specific generator
* may update this during PackageFiles.
* (either putting several names or updating the provided one)
*/
- packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName
- : "");
- toplevel = tempDirectory;
+ this->packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName
+ : "");
+ this->toplevel = tempDirectory;
{ // scope that enables package generators to run internal scripts with
// latest CMake policies enabled
cmMakefile::ScopePushPop pp{ this->MakefileMap };
@@ -1127,10 +1127,10 @@ int cmCPackGenerator::DoPackage()
* (because the specific generator did 'normalize' it)
*/
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Copying final package(s) [" << packageFileNames.size()
+ "Copying final package(s) [" << this->packageFileNames.size()
<< "]:" << std::endl);
/* now copy package one by one */
- for (std::string const& pkgFileName : packageFileNames) {
+ for (std::string const& pkgFileName : this->packageFileNames) {
std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
std::string filename(cmSystemTools::GetFilenameName(pkgFileName));
tempPackageFileName = pkgFileName.c_str();
@@ -1211,7 +1211,7 @@ bool cmCPackGenerator::IsSet(const std::string& name) const
bool cmCPackGenerator::IsOn(const std::string& name) const
{
- return cmIsOn(GetOption(name));
+ return cmIsOn(this->GetOption(name));
}
bool cmCPackGenerator::IsSetToOff(const std::string& op) const
@@ -1329,7 +1329,7 @@ bool cmCPackGenerator::ConfigureFile(const std::string& inName,
bool copyOnly /* = false */)
{
return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
- false, true) == 1;
+ false) == 1;
}
int cmCPackGenerator::CleanTemporaryDirectory()
@@ -1405,7 +1405,7 @@ int cmCPackGenerator::PrepareGroupingKind()
// fallback to default if not group based
if (method == ONE_PACKAGE_PER_GROUP && this->ComponentGroups.empty() &&
!this->Components.empty()) {
- if (componentPackageMethod == ONE_PACKAGE) {
+ if (this->componentPackageMethod == ONE_PACKAGE) {
method = ONE_PACKAGE;
} else {
method = ONE_PACKAGE_PER_COMPONENT;
@@ -1421,7 +1421,7 @@ int cmCPackGenerator::PrepareGroupingKind()
// if user specified packaging method, override the default packaging
// method
if (method != UNKNOWN_COMPONENT_PACKAGE_METHOD) {
- componentPackageMethod = method;
+ this->componentPackageMethod = method;
}
const char* method_names[] = { "ALL_COMPONENTS_IN_ONE", "IGNORE_GROUPS",
@@ -1430,7 +1430,8 @@ int cmCPackGenerator::PrepareGroupingKind()
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"[" << this->Name << "]"
<< " requested component grouping = "
- << method_names[componentPackageMethod] << std::endl);
+ << method_names[this->componentPackageMethod]
+ << std::endl);
return 1;
}
@@ -1451,13 +1452,14 @@ std::string cmCPackGenerator::GetComponentPackageFileName(
*/
std::string suffix = "-" + groupOrComponentName;
/* check if we should use DISPLAY name */
- std::string dispNameVar = "CPACK_" + Name + "_USE_DISPLAY_NAME_IN_FILENAME";
- if (IsOn(dispNameVar)) {
+ std::string dispNameVar =
+ "CPACK_" + this->Name + "_USE_DISPLAY_NAME_IN_FILENAME";
+ if (this->IsOn(dispNameVar)) {
/* the component Group case */
if (isGroupName) {
std::string groupDispVar = "CPACK_COMPONENT_GROUP_" +
cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
- const char* groupDispName = GetOption(groupDispVar);
+ const char* groupDispName = this->GetOption(groupDispVar);
if (groupDispName) {
suffix = "-" + std::string(groupDispName);
}
@@ -1466,7 +1468,7 @@ std::string cmCPackGenerator::GetComponentPackageFileName(
else {
std::string dispVar = "CPACK_COMPONENT_" +
cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
- const char* dispName = GetOption(dispVar);
+ const char* dispName = this->GetOption(dispVar);
if (dispName) {
suffix = "-" + std::string(dispName);
}
@@ -1493,8 +1495,8 @@ bool cmCPackGenerator::SupportsComponentInstallation() const
bool cmCPackGenerator::WantsComponentInstallation() const
{
- return (!IsOn("CPACK_MONOLITHIC_INSTALL") &&
- SupportsComponentInstallation()
+ return (!this->IsOn("CPACK_MONOLITHIC_INSTALL") &&
+ this->SupportsComponentInstallation()
// check that we have at least one group or component
&& (!this->ComponentGroups.empty() || !this->Components.empty()));
}
@@ -1557,7 +1559,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
const char* groupName = this->GetOption(macroPrefix + "_GROUP");
if (cmNonempty(groupName)) {
- component->Group = GetComponentGroup(projectName, groupName);
+ component->Group = this->GetComponentGroup(projectName, groupName);
component->Group->Components.push_back(component);
} else {
component->Group = nullptr;
@@ -1584,7 +1586,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
if (cmNonempty(depends)) {
std::vector<std::string> dependsVector = cmExpandedList(depends);
for (std::string const& depend : dependsVector) {
- cmCPackComponent* child = GetComponent(projectName, depend);
+ cmCPackComponent* child = this->GetComponent(projectName, depend);
component->Dependencies.push_back(child);
child->ReverseDependencies.push_back(component);
}
@@ -1620,7 +1622,8 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup(
const char* parentGroupName =
this->GetOption(macroPrefix + "_PARENT_GROUP");
if (cmNonempty(parentGroupName)) {
- group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
+ group->ParentGroup =
+ this->GetComponentGroup(projectName, parentGroupName);
group->ParentGroup->Subgroups.push_back(group);
} else {
group->ParentGroup = nullptr;
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 2109b4e34..263adfdf7 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -31,7 +31,7 @@
cmCPackNSISGenerator::cmCPackNSISGenerator(bool nsis64)
{
- Nsis64 = nsis64;
+ this->Nsis64 = nsis64;
}
cmCPackNSISGenerator::~cmCPackNSISGenerator() = default;
@@ -61,18 +61,18 @@ int cmCPackNSISGenerator::PackageFiles()
std::string nsisInstallOptions = nsisFileName + "/NSIS.InstallOptions.ini";
nsisFileName += "/project.nsi";
std::ostringstream str;
- for (std::string const& file : files) {
+ for (std::string const& file : this->files) {
std::string outputDir = "$INSTDIR";
- std::string fileN = cmSystemTools::RelativePath(toplevel, file);
+ std::string fileN = cmSystemTools::RelativePath(this->toplevel, file);
if (!this->Components.empty()) {
const std::string::size_type pos = fileN.find('/');
// Use the custom component install directory if we have one
if (pos != std::string::npos) {
auto componentName = cm::string_view(fileN).substr(0, pos);
- outputDir = CustomComponentInstallDirectory(componentName);
+ outputDir = this->CustomComponentInstallDirectory(componentName);
} else {
- outputDir = CustomComponentInstallDirectory(fileN);
+ outputDir = this->CustomComponentInstallDirectory(fileN);
}
// Strip off the component part of the path.
@@ -86,15 +86,15 @@ int cmCPackNSISGenerator::PackageFiles()
"Uninstall Files: " << str.str() << std::endl);
this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str().c_str());
std::vector<std::string> dirs;
- this->GetListOfSubdirectories(toplevel.c_str(), dirs);
+ this->GetListOfSubdirectories(this->toplevel.c_str(), dirs);
std::ostringstream dstr;
for (std::string const& dir : dirs) {
std::string componentName;
- std::string fileN = cmSystemTools::RelativePath(toplevel, dir);
+ std::string fileN = cmSystemTools::RelativePath(this->toplevel, dir);
if (fileN.empty()) {
continue;
}
- if (!Components.empty()) {
+ if (!this->Components.empty()) {
// If this is a component installation, strip off the component
// part of the path.
std::string::size_type slash = fileN.find('/');
@@ -110,7 +110,7 @@ int cmCPackNSISGenerator::PackageFiles()
std::replace(fileN.begin(), fileN.end(), '/', '\\');
const std::string componentOutputDir =
- CustomComponentInstallDirectory(componentName);
+ this->CustomComponentInstallDirectory(componentName);
dstr << " RMDir \"" << componentOutputDir << "\\" << fileN << "\""
<< std::endl;
@@ -209,6 +209,25 @@ int cmCPackNSISGenerator::PackageFiles()
"ManifestDPIAware true");
}
+ if (this->IsSet("CPACK_NSIS_BRANDING_TEXT")) {
+ // Default position to LEFT
+ std::string brandingTextPosition = "LEFT";
+ if (this->IsSet("CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION")) {
+ std::string wantedPosition =
+ this->GetOption("CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION");
+ const std::set<std::string> possiblePositions{ "CENTER", "LEFT",
+ "RIGHT" };
+ if (possiblePositions.find(wantedPosition) != possiblePositions.end()) {
+ brandingTextPosition = wantedPosition;
+ }
+ }
+ std::string brandingTextCode =
+ cmStrCat("BrandingText /TRIM", brandingTextPosition, " \"",
+ this->GetOption("CPACK_NSIS_BRANDING_TEXT"), "\"\n");
+ this->SetOptionIfNotSet("CPACK_NSIS_BRANDING_TEXT_CODE",
+ brandingTextCode.c_str());
+ }
+
// Setup all of the component sections
if (this->Components.empty()) {
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", "");
@@ -677,7 +696,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
}
const std::string componentOutputDir =
- CustomComponentInstallDirectory(component->Name);
+ this->CustomComponentInstallDirectory(component->Name);
componentCode += cmStrCat(" SetOutPath \"", componentOutputDir, "\"\n");
// Create the actual installation commands
@@ -833,14 +852,16 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
// depends on.
std::set<cmCPackComponent*> visited;
macrosOut << "!macro Select_" << component->Name << "_depends\n";
- macrosOut << CreateSelectionDependenciesDescription(component, visited);
+ macrosOut << this->CreateSelectionDependenciesDescription(component,
+ visited);
macrosOut << "!macroend\n";
// Macro used to deselect each of the components that depend on this
// component.
visited.clear();
macrosOut << "!macro Deselect_required_by_" << component->Name << "\n";
- macrosOut << CreateDeselectionDependenciesDescription(component, visited);
+ macrosOut << this->CreateDeselectionDependenciesDescription(component,
+ visited);
macrosOut << "!macroend\n";
return componentCode;
}
@@ -862,7 +883,8 @@ std::string cmCPackNSISGenerator::CreateSelectionDependenciesDescription(
out << " SectionSetFlags ${" << depend->Name << "} $0\n";
out << " IntOp $" << depend->Name << "_selected 0 + ${SF_SELECTED}\n";
// Recurse
- out << CreateSelectionDependenciesDescription(depend, visited).c_str();
+ out
+ << this->CreateSelectionDependenciesDescription(depend, visited).c_str();
}
return out.str();
@@ -887,7 +909,8 @@ std::string cmCPackNSISGenerator::CreateDeselectionDependenciesDescription(
out << " IntOp $" << depend->Name << "_selected 0 + 0\n";
// Recurse
- out << CreateDeselectionDependenciesDescription(depend, visited).c_str();
+ out << this->CreateDeselectionDependenciesDescription(depend, visited)
+ .c_str();
}
return out.str();
diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx
index 60faecd0b..98dc8906f 100644
--- a/Source/CPack/cmCPackNuGetGenerator.cxx
+++ b/Source/CPack/cmCPackNuGetGenerator.cxx
@@ -17,32 +17,33 @@
bool cmCPackNuGetGenerator::SupportsComponentInstallation() const
{
- return IsOn("CPACK_NUGET_COMPONENT_INSTALL");
+ return this->IsOn("CPACK_NUGET_COMPONENT_INSTALL");
}
int cmCPackNuGetGenerator::PackageFiles()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Toplevel: " << this->toplevel << std::endl);
/* Reset package file name list it will be populated after the
* `CPackNuGet.cmake` run */
- packageFileNames.clear();
+ this->packageFileNames.clear();
/* Are we in the component packaging case */
- if (WantsComponentInstallation()) {
- if (componentPackageMethod == ONE_PACKAGE) {
+ if (this->WantsComponentInstallation()) {
+ if (this->componentPackageMethod == ONE_PACKAGE) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// Meaning that all per-component pre-installed files
// goes into the single package.
this->SetOption("CPACK_NUGET_ALL_IN_ONE", "TRUE");
- SetupGroupComponentVariables(true);
+ this->SetupGroupComponentVariables(true);
} else {
// CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
// There will be 1 package for each component group
// however one may require to ignore component group and
// in this case you'll get 1 package for each component.
- SetupGroupComponentVariables(componentPackageMethod ==
- ONE_PACKAGE_PER_COMPONENT);
+ this->SetupGroupComponentVariables(this->componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
}
} else {
// CASE 3 : NON COMPONENT package.
@@ -51,7 +52,7 @@ int cmCPackNuGetGenerator::PackageFiles()
auto retval = this->ReadListFile("Internal/CPack/CPackNuGet.cmake");
if (retval) {
- AddGeneratedPackageNames();
+ this->AddGeneratedPackageNames();
} else {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackNuGet.cmake" << std::endl);
@@ -133,9 +134,9 @@ void cmCPackNuGetGenerator::AddGeneratedPackageNames()
std::string::size_type pos1 = 0;
std::string::size_type pos2 = fileNames.find(sep, pos1 + 1);
while (pos2 != std::string::npos) {
- packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+ this->packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
pos1 = pos2 + 1;
pos2 = fileNames.find(sep, pos1 + 1);
}
- packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+ this->packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
}
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 0c1cecf39..c3f6d594b 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -51,11 +51,11 @@ void cmCPackRPMGenerator::AddGeneratedPackageNames()
std::string::size_type pos1 = 0;
std::string::size_type pos2 = fileNames.find(sep, pos1 + 1);
while (pos2 != std::string::npos) {
- packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+ this->packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
pos1 = pos2 + 1;
pos2 = fileNames.find(sep, pos1 + 1);
}
- packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+ this->packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
}
int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
@@ -64,10 +64,11 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
int retval = 1;
// Begin the archive for this pack
std::string localToplevel(initialToplevel);
- std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
+ std::string packageFileName(
+ cmSystemTools::GetParentDirectory(this->toplevel));
std::string outputFileName(
- GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
- packageName, true) +
+ this->GetComponentPackageFileName(
+ this->GetOption("CPACK_PACKAGE_FILE_NAME"), packageName, true) +
this->GetOutputExtension());
localToplevel += "/" + packageName;
@@ -99,7 +100,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
int retval = 1;
/* Reset package file name list it will be populated during the
* component packaging run*/
- packageFileNames.clear();
+ this->packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT");
@@ -202,7 +203,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging component group: " << compGIt->first
<< std::endl);
- retval &= PackageOnePack(initialTopLevel, compGIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, compGIt->first);
}
// Handle Orphan components (components not belonging to any groups)
auto mainCompIt = this->Components.end();
@@ -227,7 +228,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
<< compIt->second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
- retval &= PackageOnePack(initialTopLevel, compIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, compIt->first);
}
}
@@ -235,9 +236,9 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
this->SetOption("GENERATE_SPEC_PARTS", "OFF");
if (mainCompGIt != this->ComponentGroups.end()) {
- retval &= PackageOnePack(initialTopLevel, mainCompGIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, mainCompGIt->first);
} else if (mainCompIt != this->Components.end()) {
- retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, mainCompIt->first);
} else {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_RPM_MAIN_COMPONENT set"
@@ -264,14 +265,14 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
continue;
}
- retval &= PackageOnePack(initialTopLevel, compIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, compIt->first);
}
if (retval) {
this->SetOption("GENERATE_SPEC_PARTS", "OFF");
if (mainCompIt != this->Components.end()) {
- retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, mainCompIt->first);
} else {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_RPM_MAIN_COMPONENT set"
@@ -291,7 +292,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Packaging component group: " << compGIt->first
<< std::endl);
- retval &= PackageOnePack(initialTopLevel, compGIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, compGIt->first);
}
// Handle Orphan components (components not belonging to any groups)
std::map<std::string, cmCPackComponent>::iterator compIt;
@@ -305,7 +306,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
<< compIt->second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
- retval &= PackageOnePack(initialTopLevel, compIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, compIt->first);
}
}
}
@@ -315,7 +316,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
std::map<std::string, cmCPackComponent>::iterator compIt;
for (compIt = this->Components.begin(); compIt != this->Components.end();
++compIt) {
- retval &= PackageOnePack(initialTopLevel, compIt->first);
+ retval &= this->PackageOnePack(initialTopLevel, compIt->first);
}
}
} else {
@@ -328,7 +329,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
}
if (retval) {
- AddGeneratedPackageNames();
+ this->AddGeneratedPackageNames();
}
return retval;
@@ -340,7 +341,7 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
int retval = 1;
/* Reset package file name list it will be populated during the
* component packaging run*/
- packageFileNames.clear();
+ this->packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE")) {
@@ -354,7 +355,8 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
// The ALL GROUPS in ONE package case
std::string localToplevel(initialTopLevel);
- std::string packageFileName(cmSystemTools::GetParentDirectory(toplevel));
+ std::string packageFileName(
+ cmSystemTools::GetParentDirectory(this->toplevel));
std::string outputFileName(
std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) +
this->GetOutputExtension());
@@ -378,7 +380,7 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
}
if (this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
- AddGeneratedPackageNames();
+ this->AddGeneratedPackageNames();
} else {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackRPM.cmake" << std::endl);
@@ -390,48 +392,49 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
int cmCPackRPMGenerator::PackageFiles()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Toplevel: " << this->toplevel << std::endl);
/* Are we in the component packaging case */
- if (WantsComponentInstallation()) {
+ if (this->WantsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL COMPONENTS in ONE package has been requested
// then the package file is unique and should be open here.
- if (componentPackageMethod == ONE_PACKAGE) {
- return PackageComponentsAllInOne("ALL_COMPONENTS_IN_ONE");
+ if (this->componentPackageMethod == ONE_PACKAGE) {
+ return this->PackageComponentsAllInOne("ALL_COMPONENTS_IN_ONE");
}
// CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
// There will be 1 package for each component group
// however one may require to ignore component group and
// in this case you'll get 1 package for each component.
- return PackageComponents(componentPackageMethod ==
- ONE_PACKAGE_PER_COMPONENT);
+ return this->PackageComponents(this->componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
}
// CASE 3 : NON COMPONENT package.
- return PackageComponentsAllInOne("");
+ return this->PackageComponentsAllInOne("");
}
bool cmCPackRPMGenerator::SupportsComponentInstallation() const
{
- return IsOn("CPACK_RPM_COMPONENT_INSTALL");
+ return this->IsOn("CPACK_RPM_COMPONENT_INSTALL");
}
std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix(
const std::string& componentName)
{
- if (componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
+ if (this->componentPackageMethod == ONE_PACKAGE_PER_COMPONENT) {
return componentName;
}
- if (componentPackageMethod == ONE_PACKAGE) {
+ if (this->componentPackageMethod == ONE_PACKAGE) {
return std::string("ALL_COMPONENTS_IN_ONE");
}
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
std::string groupVar =
"CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
- if (nullptr != GetOption(groupVar)) {
- return std::string(GetOption(groupVar));
+ if (nullptr != this->GetOption(groupVar)) {
+ return std::string(this->GetOption(groupVar));
}
return componentName;
}
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index a4a5e6fcd..3e36e8cc1 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -50,7 +50,7 @@ int cmCPackSTGZGenerator::PackageFiles()
* have generated several packages (component packaging)
* so we must iterate over generated packages.
*/
- for (std::string const& pfn : packageFileNames) {
+ for (std::string const& pfn : this->packageFileNames) {
retval &= cmSystemTools::SetPermissions(pfn.c_str(),
#if defined(_MSC_VER) || defined(__MINGW32__)
S_IREAD | S_IWRITE | S_IEXEC
diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx
index c533cd7f9..a35343549 100644
--- a/Source/CTest/cmCTestBZR.cxx
+++ b/Source/CTest/cmCTestBZR.cxx
@@ -104,8 +104,8 @@ private:
{
if (this->RegexCheckOut.find(this->Line)) {
this->BZR->URL = this->RegexCheckOut.match(1);
- CheckOutFound = true;
- } else if (!CheckOutFound && this->RegexParent.find(this->Line)) {
+ this->CheckOutFound = true;
+ } else if (!this->CheckOutFound && this->RegexParent.find(this->Line)) {
this->BZR->URL = this->RegexParent.match(1);
}
return true;
@@ -191,7 +191,7 @@ public:
int InitializeParser() override
{
- int res = cmXMLParser::InitializeParser();
+ int res = this->cmXMLParser::InitializeParser();
if (res) {
XML_SetUnknownEncodingHandler(static_cast<XML_Parser>(this->Parser),
cmBZRXMLParserUnknownEncodingHandler,
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 1cc267e95..88e287160 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -54,22 +54,21 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
//
cmProp ctestBuildConfiguration =
this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
- const std::string* cmakeBuildConfiguration = !this->Configuration.empty()
- ? &this->Configuration
- : (cmNonempty(ctestBuildConfiguration) ? ctestBuildConfiguration
- : &this->CTest->GetConfigType());
-
- const std::string* cmakeBuildAdditionalFlags = !this->Flags.empty()
- ? &this->Flags
- : this->Makefile->GetDefinition("CTEST_BUILD_FLAGS");
- const std::string* cmakeBuildTarget = !this->Target.empty()
- ? &this->Target
- : this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
+ std::string cmakeBuildConfiguration = cmNonempty(this->Configuration)
+ ? this->Configuration
+ : cmNonempty(ctestBuildConfiguration) ? *ctestBuildConfiguration
+ : this->CTest->GetConfigType();
+
+ const std::string& cmakeBuildAdditionalFlags = cmNonempty(this->Flags)
+ ? this->Flags
+ : this->Makefile->GetSafeDefinition("CTEST_BUILD_FLAGS");
+ const std::string& cmakeBuildTarget = cmNonempty(this->Target)
+ ? this->Target
+ : this->Makefile->GetSafeDefinition("CTEST_BUILD_TARGET");
if (cmNonempty(cmakeGeneratorName)) {
- if (!cmakeBuildConfiguration) {
- static const std::string sRelease = "Release";
- cmakeBuildConfiguration = &sRelease;
+ if (cmakeBuildConfiguration.empty()) {
+ cmakeBuildConfiguration = "Release";
}
if (this->GlobalGenerator) {
if (this->GlobalGenerator->GetName() != *cmakeGeneratorName) {
@@ -88,24 +87,18 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
return nullptr;
}
}
- if (cmakeBuildConfiguration->empty()) {
- const std::string* config = nullptr;
+ if (cmakeBuildConfiguration.empty()) {
#ifdef CMAKE_INTDIR
- static const std::string sIntDir = CMAKE_INTDIR;
- config = &sIntDir;
+ cmakeBuildConfiguration = CMAKE_INTDIR;
+#else
+ cmakeBuildConfiguration = "Debug";
#endif
- if (!config) {
- static const std::string sDebug = "Debug";
- config = &sDebug;
- }
- cmakeBuildConfiguration = config;
}
std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory");
std::string buildCommand =
this->GlobalGenerator->GenerateCMakeBuildCommand(
- cmakeBuildTarget ? *cmakeBuildTarget : "", *cmakeBuildConfiguration,
- cmakeBuildAdditionalFlags ? *cmakeBuildAdditionalFlags : "",
+ cmakeBuildTarget, cmakeBuildConfiguration, cmakeBuildAdditionalFlags,
this->Makefile->IgnoreErrorsCMP0061());
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"SetMakeCommand:" << buildCommand << "\n",
@@ -144,7 +137,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- bool ret = cmCTestHandlerCommand::InitialPass(args, status);
+ bool ret = this->cmCTestHandlerCommand::InitialPass(args, status);
if (!this->NumberErrors.empty()) {
this->Makefile->AddDefinition(
this->NumberErrors, std::to_string(this->Handler->GetTotalErrors()));
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 093b2d16d..3d7d0312b 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -107,7 +107,7 @@ public:
this->PipeState = cmsysProcess_WaitForExit(this->Process, timeout);
return this->PipeState;
}
- int GetProcessState() { return this->PipeState; }
+ int GetProcessState() const { return this->PipeState; }
private:
int PipeState;
@@ -778,16 +778,16 @@ struct cmCTestCoverageHandlerLocale
{
std::string l;
if (cmSystemTools::GetEnv("LC_ALL", l)) {
- lc_all = l;
+ this->lc_all = l;
}
- if (lc_all != "C") {
+ if (this->lc_all != "C") {
cmSystemTools::PutEnv("LC_ALL=C");
}
}
~cmCTestCoverageHandlerLocale()
{
- if (!lc_all.empty()) {
- cmSystemTools::PutEnv("LC_ALL=" + lc_all);
+ if (!this->lc_all.empty()) {
+ cmSystemTools::PutEnv("LC_ALL=" + this->lc_all);
} else {
cmSystemTools::UnsetEnv("LC_ALL");
}
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index b9ed03355..15c443a4c 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -265,7 +265,7 @@ void cmCTestLaunch::LoadScrapeRules()
}
void cmCTestLaunch::LoadScrapeRules(
- const char* purpose, std::vector<cmsys::RegularExpression>& regexps)
+ const char* purpose, std::vector<cmsys::RegularExpression>& regexps) const
{
std::string fname =
cmStrCat(this->Reporter.LogDir, "Custom", purpose, ".txt");
diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h
index d18f66d6a..eabb60815 100644
--- a/Source/CTest/cmCTestLaunch.h
+++ b/Source/CTest/cmCTestLaunch.h
@@ -60,7 +60,7 @@ private:
bool ScrapeRulesLoaded;
void LoadScrapeRules();
void LoadScrapeRules(const char* purpose,
- std::vector<cmsys::RegularExpression>& regexps);
+ std::vector<cmsys::RegularExpression>& regexps) const;
bool ScrapeLog(std::string const& fname);
// Helper class to generate the xml fragment.
diff --git a/Source/CTest/cmCTestLaunchReporter.cxx b/Source/CTest/cmCTestLaunchReporter.cxx
index 6ec7d0e39..5334a930e 100644
--- a/Source/CTest/cmCTestLaunchReporter.cxx
+++ b/Source/CTest/cmCTestLaunchReporter.cxx
@@ -150,7 +150,7 @@ void cmCTestLaunchReporter::WriteXML()
this->WriteXMLLabels(e2);
}
-void cmCTestLaunchReporter::WriteXMLAction(cmXMLElement& e2)
+void cmCTestLaunchReporter::WriteXMLAction(cmXMLElement& e2) const
{
e2.Comment("Meta-information about the build action");
cmXMLElement e3(e2, "Action");
@@ -284,7 +284,7 @@ void cmCTestLaunchReporter::DumpFileToXML(cmXMLElement& e3, const char* tag,
cmXMLElement e4(e3, tag);
while (cmSystemTools::GetLineFromStream(fin, line)) {
- if (MatchesFilterPrefix(line)) {
+ if (this->MatchesFilterPrefix(line)) {
continue;
}
if (this->Match(line, this->RegexWarningSuppress)) {
diff --git a/Source/CTest/cmCTestLaunchReporter.h b/Source/CTest/cmCTestLaunchReporter.h
index 675a8787e..4be0d9beb 100644
--- a/Source/CTest/cmCTestLaunchReporter.h
+++ b/Source/CTest/cmCTestLaunchReporter.h
@@ -70,7 +70,7 @@ public:
// Methods to generate the xml fragment.
void WriteXML();
- void WriteXMLAction(cmXMLElement&);
+ void WriteXMLAction(cmXMLElement&) const;
void WriteXMLCommand(cmXMLElement&);
void WriteXMLResult(cmXMLElement&);
void WriteXMLLabels(cmXMLElement&);
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 8a30dc014..125d0034d 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -300,7 +300,7 @@ void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile* mf)
this->CustomTestsIgnore);
}
-int cmCTestMemCheckHandler::GetDefectCount()
+int cmCTestMemCheckHandler::GetDefectCount() const
{
return this->DefectCount;
}
@@ -1364,9 +1364,15 @@ void cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res,
}
}
if (this->LogWithPID) {
- cmSystemTools::RemoveFile(ofile);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Remove: " << ofile << "\n", this->Quiet);
+ auto pos = ofile.find_last_of('.');
+ if (pos != std::string::npos) {
+ auto ofileWithoutPid = ofile.substr(0, pos);
+ cmSystemTools::RenameFile(ofile, ofileWithoutPid);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Renaming: " << ofile << " to: " << ofileWithoutPid
+ << "\n",
+ this->Quiet);
+ }
}
}
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 7ab00dbd7..b200c4394 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -29,7 +29,7 @@ public:
void Initialize() override;
- int GetDefectCount();
+ int GetDefectCount() const;
protected:
int PreProcessHandler() override;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index a08cb3480..852f9d91d 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -56,8 +56,8 @@ public:
// Sorts tests in descending order of cost
bool operator()(int index1, int index2) const
{
- return Handler->Properties[index1]->Cost >
- Handler->Properties[index2]->Cost;
+ return this->Handler->Properties[index1]->Cost >
+ this->Handler->Properties[index2]->Cost;
}
private:
@@ -169,7 +169,7 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
this->TestRunningMap[test] = true; // mark the test as running
// now remove the test itself
this->EraseTest(test);
- this->RunningCount += GetProcessorsUsed(test);
+ this->RunningCount += this->GetProcessorsUsed(test);
auto testRun = cm::make_unique<cmCTestRunTest>(*this);
@@ -552,12 +552,12 @@ void cmCTestMultiProcessHandler::StartNextTests()
continue;
}
- size_t processors = GetProcessorsUsed(test);
+ size_t processors = this->GetProcessorsUsed(test);
bool testLoadOk = true;
if (this->TestLoad > 0) {
if (processors <= spareLoad) {
cmCTestLog(this->CTest, DEBUG,
- "OK to run " << GetName(test) << ", it requires "
+ "OK to run " << this->GetName(test) << ", it requires "
<< processors << " procs & system load is: "
<< systemLoad << std::endl);
allTestsFailedTestLoadCheck = false;
@@ -568,7 +568,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
if (processors <= minProcessorsRequired) {
minProcessorsRequired = processors;
- testWithMinProcessors = GetName(test);
+ testWithMinProcessors = this->GetName(test);
}
if (testLoadOk && processors <= numToStart && this->StartTest(test)) {
@@ -621,7 +621,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
void cmCTestMultiProcessHandler::OnTestLoadRetryCB(uv_timer_t* timer)
{
- auto self = static_cast<cmCTestMultiProcessHandler*>(timer->data);
+ auto* self = static_cast<cmCTestMultiProcessHandler*>(timer->data);
self->StartNextTests();
}
@@ -631,7 +631,7 @@ void cmCTestMultiProcessHandler::FinishTestProcess(
this->Completed++;
int test = runner->GetIndex();
- auto properties = runner->GetTestProperties();
+ auto* properties = runner->GetTestProperties();
bool testResult = runner->EndTest(this->Completed, this->Total, started);
if (runner->TimedOutForStopTime()) {
@@ -660,7 +660,7 @@ void cmCTestMultiProcessHandler::FinishTestProcess(
this->WriteCheckpoint(test);
this->DeallocateResources(test);
this->UnlockResources(test);
- this->RunningCount -= GetProcessorsUsed(test);
+ this->RunningCount -= this->GetProcessorsUsed(test);
for (auto p : properties->Affinity) {
this->ProcessorsAvailable.insert(p);
@@ -793,9 +793,9 @@ int cmCTestMultiProcessHandler::SearchByName(std::string const& name)
void cmCTestMultiProcessHandler::CreateTestCostList()
{
if (this->ParallelLevel > 1) {
- CreateParallelTestCostList();
+ this->CreateParallelTestCostList();
} else {
- CreateSerialTestCostList();
+ this->CreateSerialTestCostList();
}
}
@@ -862,7 +862,7 @@ void cmCTestMultiProcessHandler::GetAllTestDependencies(int test,
{
TestSet const& dependencySet = this->Tests[test];
for (int i : dependencySet) {
- GetAllTestDependencies(i, dependencies);
+ this->GetAllTestDependencies(i, dependencies);
dependencies.push_back(i);
}
}
@@ -886,7 +886,7 @@ void cmCTestMultiProcessHandler::CreateSerialTestCostList()
}
TestList dependencies;
- GetAllTestDependencies(test, dependencies);
+ this->GetAllTestDependencies(test, dependencies);
for (int testDependency : dependencies) {
if (!cm::contains(alreadySortedTests, testDependency)) {
@@ -920,7 +920,7 @@ void cmCTestMultiProcessHandler::MarkFinished()
static Json::Value DumpToJsonArray(const std::set<std::string>& values)
{
Json::Value jsonArray = Json::arrayValue;
- for (auto& it : values) {
+ for (const auto& it : values) {
jsonArray.append(it);
}
return jsonArray;
@@ -929,7 +929,7 @@ static Json::Value DumpToJsonArray(const std::set<std::string>& values)
static Json::Value DumpToJsonArray(const std::vector<std::string>& values)
{
Json::Value jsonArray = Json::arrayValue;
- for (auto& it : values) {
+ for (const auto& it : values) {
jsonArray.append(it);
}
return jsonArray;
@@ -939,7 +939,7 @@ static Json::Value DumpRegExToJsonArray(
const std::vector<std::pair<cmsys::RegularExpression, std::string>>& values)
{
Json::Value jsonArray = Json::arrayValue;
- for (auto& it : values) {
+ for (const auto& it : values) {
jsonArray.append(it.second);
}
return jsonArray;
@@ -949,7 +949,7 @@ static Json::Value DumpMeasurementToJsonArray(
const std::map<std::string, std::string>& values)
{
Json::Value jsonArray = Json::arrayValue;
- for (auto& it : values) {
+ for (const auto& it : values) {
Json::Value measurement = Json::objectValue;
measurement["measurement"] = it.first;
measurement["value"] = it.second;
@@ -1274,7 +1274,7 @@ void cmCTestMultiProcessHandler::PrintOutputAsJson()
void cmCTestMultiProcessHandler::PrintTestList()
{
if (this->CTest->GetOutputAsJson()) {
- PrintOutputAsJson();
+ this->PrintOutputAsJson();
return;
}
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index 1375be406..50c9c16f8 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -56,7 +56,7 @@ public:
ChangesParser(cmCTestP4* p4, const char* prefix)
: P4(p4)
{
- this->SetLog(&P4->Log, prefix);
+ this->SetLog(&this->P4->Log, prefix);
this->RegexIdentify.compile("^Change ([0-9]+) on");
}
@@ -67,7 +67,7 @@ private:
bool ProcessLine() override
{
if (this->RegexIdentify.find(this->Line)) {
- P4->ChangeLists.push_back(this->RegexIdentify.match(1));
+ this->P4->ChangeLists.push_back(this->RegexIdentify.match(1));
}
return true;
}
@@ -79,7 +79,7 @@ public:
UserParser(cmCTestP4* p4, const char* prefix)
: P4(p4)
{
- this->SetLog(&P4->Log, prefix);
+ this->SetLog(&this->P4->Log, prefix);
this->RegexUser.compile("^(.+) <(.*)> \\((.*)\\) accessed (.*)$");
}
@@ -96,7 +96,7 @@ private:
NewUser.EMail = this->RegexUser.match(2);
NewUser.Name = this->RegexUser.match(3);
NewUser.AccessTime = this->RegexUser.match(4);
- P4->Users[this->RegexUser.match(1)] = NewUser;
+ this->P4->Users[this->RegexUser.match(1)] = NewUser;
return false;
}
@@ -120,7 +120,7 @@ public:
: P4(p4)
, AlreadyNotified(false)
{
- this->SetLog(&P4->Log, prefix);
+ this->SetLog(&this->P4->Log, prefix);
this->RegexDiff.compile("^==== (.*)#[0-9]+ - (.*)");
}
@@ -134,12 +134,12 @@ private:
{
if (!this->Line.empty() && this->Line[0] == '=' &&
this->RegexDiff.find(this->Line)) {
- CurrentPath = this->RegexDiff.match(1);
- AlreadyNotified = false;
+ this->CurrentPath = this->RegexDiff.match(1);
+ this->AlreadyNotified = false;
} else {
- if (!AlreadyNotified) {
- P4->DoModification(PathModified, CurrentPath);
- AlreadyNotified = true;
+ if (!this->AlreadyNotified) {
+ this->P4->DoModification(PathModified, this->CurrentPath);
+ this->AlreadyNotified = true;
}
}
return true;
@@ -148,11 +148,11 @@ private:
cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)
{
- auto it = Users.find(username);
+ auto it = this->Users.find(username);
- if (it == Users.end()) {
+ if (it == this->Users.end()) {
std::vector<char const*> p4_users;
- SetP4Options(p4_users);
+ this->SetP4Options(p4_users);
p4_users.push_back("users");
p4_users.push_back("-m");
p4_users.push_back("1");
@@ -161,11 +161,11 @@ cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)
UserParser out(this, "users-out> ");
OutputLogger err(this->Log, "users-err> ");
- RunChild(&p4_users[0], &out, &err);
+ this->RunChild(&p4_users[0], &out, &err);
// The user should now be added to the map. Search again.
- it = Users.find(username);
- if (it == Users.end()) {
+ it = this->Users.find(username);
+ if (it == this->Users.end()) {
return cmCTestP4::User();
}
}
@@ -195,7 +195,7 @@ public:
, P4(p4)
, Section(SectionHeader)
{
- this->SetLog(&P4->Log, prefix);
+ this->SetLog(&this->P4->Log, prefix);
this->RegexHeader.compile("^Change ([0-9]+) by (.+)@(.+) on (.*)$");
this->RegexDiff.compile(R"(^\.\.\. (.*)#[0-9]+ ([^ ]+)$)");
}
@@ -259,7 +259,7 @@ private:
this->Rev.Rev = this->RegexHeader.match(1);
this->Rev.Date = this->RegexHeader.match(4);
- cmCTestP4::User user = P4->GetUserData(this->RegexHeader.match(2));
+ cmCTestP4::User user = this->P4->GetUserData(this->RegexHeader.match(2));
this->Rev.Author = user.Name;
this->Rev.EMail = user.EMail;
@@ -300,38 +300,38 @@ private:
change.Action = 'M';
}
- Changes.push_back(change);
+ this->Changes.push_back(change);
}
}
};
void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions)
{
- if (P4Options.empty()) {
+ if (this->P4Options.empty()) {
const char* p4 = this->CommandLineTool.c_str();
- P4Options.emplace_back(p4);
+ this->P4Options.emplace_back(p4);
// The CTEST_P4_CLIENT variable sets the P4 client used when issuing
// Perforce commands, if it's different from the default one.
std::string client = this->CTest->GetCTestConfiguration("P4Client");
if (!client.empty()) {
- P4Options.emplace_back("-c");
- P4Options.push_back(client);
+ this->P4Options.emplace_back("-c");
+ this->P4Options.push_back(client);
}
// Set the message language to be English, in case the P4 admin
// has localized them
- P4Options.emplace_back("-L");
- P4Options.emplace_back("en");
+ this->P4Options.emplace_back("-L");
+ this->P4Options.emplace_back("en");
// The CTEST_P4_OPTIONS variable adds additional Perforce command line
// options before the main command
std::string opts = this->CTest->GetCTestConfiguration("P4Options");
- cm::append(P4Options, cmSystemTools::ParseArguments(opts));
+ cm::append(this->P4Options, cmSystemTools::ParseArguments(opts));
}
CommandOptions.clear();
- for (std::string const& o : P4Options) {
+ for (std::string const& o : this->P4Options) {
CommandOptions.push_back(o.c_str());
}
}
@@ -339,7 +339,7 @@ void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions)
std::string cmCTestP4::GetWorkingRevision()
{
std::vector<char const*> p4_identify;
- SetP4Options(p4_identify);
+ this->SetP4Options(p4_identify);
p4_identify.push_back("changes");
p4_identify.push_back("-m");
@@ -354,7 +354,7 @@ std::string cmCTestP4::GetWorkingRevision()
IdentifyParser out(this, "p4_changes-out> ", rev);
OutputLogger err(this->Log, "p4_changes-err> ");
- bool result = RunChild(&p4_identify[0], &out, &err);
+ bool result = this->RunChild(&p4_identify[0], &out, &err);
// If there was a problem contacting the server return "<unknown>"
if (!result) {
@@ -391,7 +391,7 @@ bool cmCTestP4::NoteNewRevision()
bool cmCTestP4::LoadRevisions()
{
std::vector<char const*> p4_changes;
- SetP4Options(p4_changes);
+ this->SetP4Options(p4_changes);
// Use 'p4 changes ...@old,new' to get a list of changelists
std::string range = this->SourceDirectory + "/...";
@@ -417,17 +417,17 @@ bool cmCTestP4::LoadRevisions()
ChangesParser out(this, "p4_changes-out> ");
OutputLogger err(this->Log, "p4_changes-err> ");
- ChangeLists.clear();
+ this->ChangeLists.clear();
this->RunChild(&p4_changes[0], &out, &err);
- if (ChangeLists.empty()) {
+ if (this->ChangeLists.empty()) {
return true;
}
// p4 describe -s ...@1111111,2222222
std::vector<char const*> p4_describe;
- for (std::string const& i : cmReverseRange(ChangeLists)) {
- SetP4Options(p4_describe);
+ for (std::string const& i : cmReverseRange(this->ChangeLists)) {
+ this->SetP4Options(p4_describe);
p4_describe.push_back("describe");
p4_describe.push_back("-s");
p4_describe.push_back(i.c_str());
@@ -443,7 +443,7 @@ bool cmCTestP4::LoadRevisions()
bool cmCTestP4::LoadModifications()
{
std::vector<char const*> p4_diff;
- SetP4Options(p4_diff);
+ this->SetP4Options(p4_diff);
p4_diff.push_back("diff");
@@ -491,7 +491,7 @@ bool cmCTestP4::UpdateImpl()
}
std::vector<char const*> p4_sync;
- SetP4Options(p4_sync);
+ this->SetP4Options(p4_sync);
p4_sync.push_back("sync");
diff --git a/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx b/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx
index 072af42f0..4c26b3f09 100644
--- a/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx
+++ b/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx
@@ -17,7 +17,7 @@ bool cmCTestResourceGroupsLexerHelper::ParseString(const std::string& value)
yyscan_t lexer;
cmCTestResourceGroups_yylex_init_extra(this, &lexer);
- auto state = cmCTestResourceGroups_yy_scan_string(value.c_str(), lexer);
+ auto* state = cmCTestResourceGroups_yy_scan_string(value.c_str(), lexer);
int retval = cmCTestResourceGroups_yylex(lexer);
cmCTestResourceGroups_yy_delete_buffer(state, lexer);
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 4d65c9bda..5a6c77539 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -139,7 +139,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode;
}
this->TestResult.CompletionStatus = s.str();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Skipped ");
+ outputStream << "***Skipped ";
skipped = true;
} else if (success != this->TestProperties->WillFail) {
this->TestResult.Status = cmCTestTestHandler::COMPLETED;
@@ -195,10 +195,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count());
outputStream << buf << "\n";
+ bool passedOrSkipped = passed || skipped;
if (this->CTest->GetTestProgressOutput()) {
- if (!passed) {
+ if (!passedOrSkipped) {
// If the test did not pass, reprint test name and error
- std::string output = GetTestPrefix(completed, total);
+ std::string output = this->GetTestPrefix(completed, total);
std::string testName = this->TestProperties->Name;
const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
testName.resize(maxTestNameWidth + 4, '.');
@@ -211,12 +212,12 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, "\n"); // flush
}
if (completed == total) {
- std::string testName =
- GetTestPrefix(completed, total) + this->TestProperties->Name + "\n";
+ std::string testName = this->GetTestPrefix(completed, total) +
+ this->TestProperties->Name + "\n";
cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName);
}
}
- if (!this->CTest->GetTestProgressOutput() || !passed) {
+ if (!this->CTest->GetTestProgressOutput() || !passedOrSkipped) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str());
}
@@ -485,8 +486,8 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
<< this->TestProperties->Index << ": "
<< this->TestProperties->Name << std::endl);
} else {
- std::string testName =
- GetTestPrefix(completed, total) + this->TestProperties->Name + "\n";
+ std::string testName = this->GetTestPrefix(completed, total) +
+ this->TestProperties->Name + "\n";
cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName);
}
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 44dfab2e6..4692dbd51 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -286,9 +286,9 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
args.push_back(nullptr);
if (strcmp(parameters[0], "update") == 0) {
- return RunUpdateCommand(&args[0], out, err);
+ return this->RunUpdateCommand(&args[0], out, err);
}
- return RunChild(&args[0], out, err);
+ return this->RunChild(&args[0], out, err);
}
class cmCTestSVN::LogParser
@@ -328,7 +328,7 @@ private:
this->CData.clear();
if (name == "logentry") {
this->Rev = Revision();
- this->Rev.SVNInfo = &SVNRepo;
+ this->Rev.SVNInfo = &this->SVNRepo;
if (const char* rev =
cmCTestSVN::LogParser::FindAttribute(atts, "revision")) {
this->Rev.Rev = rev;
@@ -354,7 +354,7 @@ private:
this->SVN->DoRevisionSVN(this->Rev, this->Changes);
} else if (!this->CData.empty() && name == "path") {
std::string orig_path(&this->CData[0], this->CData.size());
- std::string new_path = SVNRepo.BuildLocalPath(orig_path);
+ std::string new_path = this->SVNRepo.BuildLocalPath(orig_path);
this->CurChange.Path.assign(new_path);
this->Changes.push_back(this->CurChange);
} else if (!this->CData.empty() && name == "author") {
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 4d1a589dc..1cb5d0090 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -122,7 +122,7 @@ bool cmCTestSubdirCommand(std::vector<std::string> const& args,
readit = status.GetMakefile().ReadDependentFile(fname);
}
if (!readit) {
- status.SetError(cmStrCat("Could not find include file: ", fname));
+ status.SetError(cmStrCat("Could not load include file: ", fname));
return false;
}
}
@@ -340,7 +340,7 @@ void cmCTestTestHandler::Initialize()
this->ExcludeFixtureSetupRegExp.clear();
this->ExcludeFixtureCleanupRegExp.clear();
- TestsToRunString.clear();
+ this->TestsToRunString.clear();
this->UseUnion = false;
this->TestList.clear();
}
@@ -877,7 +877,7 @@ bool cmCTestTestHandler::ComputeTestList()
finalList.push_back(tp);
}
- UpdateForFixtures(finalList);
+ this->UpdateForFixtures(finalList);
// Save the total number of tests before exclusions
this->TotalNumberOfTests = this->TestList.size();
@@ -906,7 +906,7 @@ void cmCTestTestHandler::ComputeTestListForRerunFailed()
finalList.push_back(tp);
}
- UpdateForFixtures(finalList);
+ this->UpdateForFixtures(finalList);
// Save the total number of tests before exclusions
this->TotalNumberOfTests = this->TestList.size();
@@ -1675,7 +1675,7 @@ std::string cmCTestTestHandler::FindExecutable(
// if everything else failed, check the users path, but only if a full path
// wasn't specified
if (fullPath.empty() && filepath.empty()) {
- std::string const path = cmSystemTools::FindProgram(filename.c_str());
+ std::string path = cmSystemTools::FindProgram(filename.c_str());
if (!path.empty()) {
resultingConfig.clear();
return path;
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 6fef90a56..0ba2c417b 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -5,7 +5,6 @@
#include "cmCTest.h"
#include "cmCTestUpdateHandler.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmSystemTools.h"
cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
@@ -18,7 +17,7 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
this->CTest->SetCTestConfiguration(
"SourceDirectory",
cmSystemTools::CollapseFullPath(
- cmToCStrSafe(this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY"))),
+ this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")),
this->Quiet);
}
std::string source_dir =
diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx
index 409025f80..3a6651f8f 100644
--- a/Source/CTest/cmParseBlanketJSCoverage.cxx
+++ b/Source/CTest/cmParseBlanketJSCoverage.cxx
@@ -66,7 +66,7 @@ public:
}
foundFile = true;
inSource = false;
- filename = getValue(line, 0);
+ filename = this->getValue(line, 0);
} else if ((line.find("coverage") != std::string::npos) && foundFile &&
inSource) {
/*
@@ -78,7 +78,7 @@ public:
* FoundFile and foundSource ensure that
* only the value of the line coverage is captured
*/
- std::string result = getValue(line, 1);
+ std::string result = this->getValue(line, 1);
result = result.substr(2);
if (result == "\"\"") {
// Empty quotation marks indicate that the
diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx
index 711a8564b..93117695c 100644
--- a/Source/CTest/cmParseCoberturaCoverage.cxx
+++ b/Source/CTest/cmParseCoberturaCoverage.cxx
@@ -66,7 +66,7 @@ protected:
// Check if this is an absolute path that falls within our
// source or binary directories.
- for (std::string const& filePath : FilePaths) {
+ for (std::string const& filePath : this->FilePaths) {
if (cmHasPrefix(filename, filePath)) {
this->CurFileName = filename;
break;
@@ -76,7 +76,7 @@ protected:
if (this->CurFileName.empty()) {
// Check if this is a path that is relative to our source or
// binary directories.
- for (std::string const& filePath : FilePaths) {
+ for (std::string const& filePath : this->FilePaths) {
finalpath = cmStrCat(filePath, "/", filename);
if (cmSystemTools::FileExists(finalpath)) {
this->CurFileName = finalpath;
diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx
index 016e90c02..640873e2b 100644
--- a/Source/CTest/cmParseDelphiCoverage.cxx
+++ b/Source/CTest/cmParseDelphiCoverage.cxx
@@ -133,7 +133,7 @@ public:
cmsys::Glob gl;
gl.RecurseOn();
gl.RecurseThroughSymlinksOff();
- std::string glob = Coverage.SourceDir + "*/" + filename;
+ std::string glob = this->Coverage.SourceDir + "*/" + filename;
gl.FindFiles(glob);
std::vector<std::string> const& files = gl.GetFiles();
if (files.empty()) {
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 9ee1c170c..16bca01b5 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -152,7 +152,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity)
void cmProcess::StartTimer()
{
- auto properties = this->Runner->GetTestProperties();
+ auto* properties = this->Runner->GetTestProperties();
auto msec =
std::chrono::duration_cast<std::chrono::milliseconds>(this->Timeout);
@@ -177,7 +177,7 @@ bool cmProcess::Buffer::GetLine(std::string& line)
// Start a new range for the next line.
++this->Last;
- this->First = Last;
+ this->First = this->Last;
// Return the line extracted.
return true;
@@ -209,7 +209,7 @@ bool cmProcess::Buffer::GetLast(std::string& line)
void cmProcess::OnReadCB(uv_stream_t* stream, ssize_t nread,
const uv_buf_t* buf)
{
- auto self = static_cast<cmProcess*>(stream->data);
+ auto* self = static_cast<cmProcess*>(stream->data);
self->OnRead(nread, buf);
}
@@ -256,7 +256,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf)
void cmProcess::OnAllocateCB(uv_handle_t* handle, size_t suggested_size,
uv_buf_t* buf)
{
- auto self = static_cast<cmProcess*>(handle->data);
+ auto* self = static_cast<cmProcess*>(handle->data);
self->OnAllocate(suggested_size, buf);
}
@@ -272,7 +272,7 @@ void cmProcess::OnAllocate(size_t /*suggested_size*/, uv_buf_t* buf)
void cmProcess::OnTimeoutCB(uv_timer_t* timer)
{
- auto self = static_cast<cmProcess*>(timer->data);
+ auto* self = static_cast<cmProcess*>(timer->data);
self->OnTimeout();
}
@@ -298,7 +298,7 @@ void cmProcess::OnTimeout()
void cmProcess::OnExitCB(uv_process_t* process, int64_t exit_status,
int term_signal)
{
- auto self = static_cast<cmProcess*>(process->data);
+ auto* self = static_cast<cmProcess*>(process->data);
self->OnExit(exit_status, term_signal);
}
@@ -358,7 +358,7 @@ void cmProcess::ResetStartTime()
this->StartTime = std::chrono::steady_clock::now();
}
-cmProcess::Exception cmProcess::GetExitException()
+cmProcess::Exception cmProcess::GetExitException() const
{
auto exception = Exception::None;
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -430,7 +430,7 @@ cmProcess::Exception cmProcess::GetExitException()
return exception;
}
-std::string cmProcess::GetExitExceptionString()
+std::string cmProcess::GetExitExceptionString() const
{
std::string exception_str;
#if defined(_WIN32)
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 9eec9526f..a44aeb07c 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -67,8 +67,8 @@ public:
Other
};
- Exception GetExitException();
- std::string GetExitExceptionString();
+ Exception GetExitException() const;
+ std::string GetExitExceptionString() const;
std::unique_ptr<cmCTestRunTest> GetRunner()
{
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 6fc556c08..069c02ef8 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -405,7 +405,7 @@ void cmCursesMainForm::UpdateStatusBar(cm::optional<std::string> message)
// Get the help string of the current entry
// and add it to the help string
- auto cmakeState = this->CMakeInstance->GetState();
+ auto* cmakeState = this->CMakeInstance->GetState();
cmProp existingValue = cmakeState->GetCacheEntryValue(labelValue);
if (existingValue) {
cmProp help =
@@ -1000,7 +1000,7 @@ void cmCursesMainForm::DisplayOutputs(std::string const& newOutput)
getmaxyx(stdscr, yi, xi);
if (CurrentForm != this->LogForm.get()) {
- auto newLogForm = new cmCursesLongMessageForm(
+ auto* newLogForm = new cmCursesLongMessageForm(
this->Outputs, this->LastProgress.c_str(),
cmCursesLongMessageForm::ScrollBehavior::ScrollDown);
CurrentForm = newLogForm;
diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt
index 21c499e83..8f26b9aaa 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx
index 34dc8ecfe..b8bc82cd7 100644
--- a/Source/LexerParser/cmCommandArgumentParser.cxx
+++ b/Source/LexerParser/cmCommandArgumentParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -34,6 +34,10 @@
/* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
+
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros.
@@ -41,14 +45,11 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
-
-/* Identify Bison output. */
-#define YYBISON 1
+/* Identify Bison output, and Bison version. */
+#define YYBISON 30704
-/* Bison version. */
-#define YYBISON_VERSION "3.4.2"
+/* Bison version string. */
+#define YYBISON_VERSION "3.7.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -70,7 +71,6 @@
#define yydebug cmCommandArgument_yydebug
#define yynerrs cmCommandArgument_yynerrs
-
/* First part of user prologue. */
#line 1 "cmCommandArgumentParser.y"
@@ -82,10 +82,7 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
-
-Modify cmCommandArgumentParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+ bison --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
*/
@@ -100,6 +97,7 @@ Modify cmCommandArgumentParser.cxx:
# include <malloc.h>
#endif
+#include <stdint.h>
/* Make sure the parser uses standard memory allocation. The default
generated parser malloc/free declarations do not work on all
platforms. */
@@ -110,7 +108,6 @@ Modify cmCommandArgumentParser.cxx:
/*-------------------------------------------------------------------------*/
#include "cmCommandArgumentParserHelper.h" /* Interface to parser object. */
#include "cmCommandArgumentLexer.h" /* Interface to lexer object. */
-#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL. */
/* Forward declare the lexer entry point. */
YY_DECL;
@@ -132,10 +129,20 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
#endif
-#line 138 "cmCommandArgumentParser.cxx"
+#line 136 "cmCommandArgumentParser.cxx"
+# ifndef YY_CAST
+# ifdef __cplusplus
+# define YY_CAST(Type, Val) static_cast<Type> (Val)
+# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
+# else
+# define YY_CAST(Type, Val) ((Type) (Val))
+# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+# endif
+# endif
# ifndef YY_NULLPTR
# if defined __cplusplus
# if 201103L <= __cplusplus
@@ -148,95 +155,115 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
# endif
# endif
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* Use api.header.include to #include this header
- instead of duplicating it here. */
-#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
-# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
-/* Debug traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int cmCommandArgument_yydebug;
-#endif
-
-/* Token type. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- enum yytokentype
- {
- cal_ENVCURLY = 258,
- cal_NCURLY = 259,
- cal_DCURLY = 260,
- cal_DOLLAR = 261,
- cal_LCURLY = 262,
- cal_RCURLY = 263,
- cal_NAME = 264,
- cal_BSLASH = 265,
- cal_SYMBOL = 266,
- cal_AT = 267,
- cal_ERROR = 268,
- cal_ATNAME = 269
- };
-#endif
-/* Tokens. */
-#define cal_ENVCURLY 258
-#define cal_NCURLY 259
-#define cal_DCURLY 260
-#define cal_DOLLAR 261
-#define cal_LCURLY 262
-#define cal_RCURLY 263
-#define cal_NAME 264
-#define cal_BSLASH 265
-#define cal_SYMBOL 266
-#define cal_AT 267
-#define cal_ERROR 268
-#define cal_ATNAME 269
+#include "cmCommandArgumentParserTokens.h"
+/* Symbol kind. */
+enum yysymbol_kind_t
+{
+ YYSYMBOL_YYEMPTY = -2,
+ YYSYMBOL_YYEOF = 0, /* "end of file" */
+ YYSYMBOL_YYerror = 1, /* error */
+ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
+ YYSYMBOL_cal_ENVCURLY = 3, /* cal_ENVCURLY */
+ YYSYMBOL_cal_NCURLY = 4, /* cal_NCURLY */
+ YYSYMBOL_cal_DCURLY = 5, /* cal_DCURLY */
+ YYSYMBOL_cal_DOLLAR = 6, /* "$" */
+ YYSYMBOL_cal_LCURLY = 7, /* "{" */
+ YYSYMBOL_cal_RCURLY = 8, /* "}" */
+ YYSYMBOL_cal_NAME = 9, /* cal_NAME */
+ YYSYMBOL_cal_BSLASH = 10, /* "\\" */
+ YYSYMBOL_cal_SYMBOL = 11, /* cal_SYMBOL */
+ YYSYMBOL_cal_AT = 12, /* "@" */
+ YYSYMBOL_cal_ERROR = 13, /* cal_ERROR */
+ YYSYMBOL_cal_ATNAME = 14, /* cal_ATNAME */
+ YYSYMBOL_YYACCEPT = 15, /* $accept */
+ YYSYMBOL_Start = 16, /* Start */
+ YYSYMBOL_GoalWithOptionalBackSlash = 17, /* GoalWithOptionalBackSlash */
+ YYSYMBOL_Goal = 18, /* Goal */
+ YYSYMBOL_String = 19, /* String */
+ YYSYMBOL_OuterText = 20, /* OuterText */
+ YYSYMBOL_Variable = 21, /* Variable */
+ YYSYMBOL_EnvVarName = 22, /* EnvVarName */
+ YYSYMBOL_MultipleIds = 23, /* MultipleIds */
+ YYSYMBOL_ID = 24 /* ID */
+};
+typedef enum yysymbol_kind_t yysymbol_kind_t;
-/* Value type. */
-int cmCommandArgument_yyparse (yyscan_t yyscanner);
+#ifdef short
+# undef short
+#endif
-#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+ <limits.h> and (if available) <stdint.h> are included
+ so that the code can choose integer types of a good width. */
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_STDINT_H
+# endif
+#endif
+/* Narrow types that promote to a signed type and that can represent a
+ signed or unsigned integer of at least N bits. In tables they can
+ save space and decrease cache pressure. Promoting to a signed type
+ helps avoid bugs in integer arithmetic. */
-#ifdef short
-# undef short
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
+#else
+typedef signed char yytype_int8;
#endif
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
#else
-typedef unsigned char yytype_uint8;
+typedef short yytype_int16;
#endif
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
+#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 \
+ && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
#else
-typedef signed char yytype_int8;
+typedef short yytype_uint8;
#endif
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
#endif
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short yytype_int16;
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+# define YYPTRDIFF_T __PTRDIFF_TYPE__
+# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+# ifndef ptrdiff_t
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# endif
+# define YYPTRDIFF_T ptrdiff_t
+# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+# define YYPTRDIFF_T long
+# define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
#endif
#ifndef YYSIZE_T
@@ -244,7 +271,7 @@ typedef short yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -252,7 +279,20 @@ typedef short yytype_int16;
# endif
#endif
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+#define YYSIZE_MAXIMUM \
+ YY_CAST (YYPTRDIFF_T, \
+ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
+ ? YYPTRDIFF_MAXIMUM \
+ : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_int8 yy_state_t;
+
+/* State numbers in computations. */
+typedef int yy_state_fast_t;
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
@@ -266,22 +306,21 @@ typedef short yytype_int16;
# endif
#endif
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__ \
- && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
- || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
-# else
-# define YY_ATTRIBUTE(Spec) /* empty */
-# endif
-#endif
#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define YY_ATTRIBUTE_PURE
+# endif
#endif
#ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+# define YY_ATTRIBUTE_UNUSED
+# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
@@ -293,11 +332,11 @@ typedef short yytype_int16;
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
@@ -310,10 +349,22 @@ typedef short yytype_int16;
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
+#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END \
+ _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
#define YY_ASSERT(E) ((void) (0 && (E)))
-#if ! defined yyoverflow || YYERROR_VERBOSE
+#if 1
/* The parser invokes alloca or malloc; define the necessary symbols. */
@@ -378,8 +429,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
+#endif /* 1 */
#if (! defined yyoverflow \
&& (! defined __cplusplus \
@@ -388,17 +438,17 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss_alloc;
+ yy_state_t yyss_alloc;
YYSTYPE yyvs_alloc;
};
/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
# define YYCOPY_NEEDED 1
@@ -411,11 +461,11 @@ union yyalloc
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
- YYSIZE_T yynewbytes; \
+ YYPTRDIFF_T yynewbytes; \
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
+ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / YYSIZEOF (*yyptr); \
} \
while (0)
@@ -427,12 +477,12 @@ union yyalloc
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
# else
# define YYCOPY(Dst, Src, Count) \
do \
{ \
- YYSIZE_T yyi; \
+ YYPTRDIFF_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
@@ -455,17 +505,20 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 33
-#define YYUNDEFTOK 2
+/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 269
+
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
-#define YYTRANSLATE(YYX) \
- ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+#define YYTRANSLATE(YYX) \
+ (0 <= (YYX) && (YYX) <= YYMAXUTOK \
+ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
+ : YYSYMBOL_YYUNDEF)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */
-static const yytype_uint8 yytranslate[] =
+static const yytype_int8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -500,43 +553,56 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 99, 99, 105, 108, 113, 116, 121, 124, 129,
- 132, 135, 138, 141, 144, 149, 152, 155, 158, 163,
- 166, 171, 174, 179, 182
+ 0, 97, 97, 103, 106, 111, 114, 119, 122, 127,
+ 130, 133, 136, 139, 142, 147, 150, 153, 156, 161,
+ 164, 169, 172, 177, 180
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 1
+/** Accessing symbol of state STATE. */
+#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
+
+#if 1
+/* The user-facing name of the symbol whose (internal) number is
+ YYSYMBOL. No bounds checking. */
+static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
+
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "cal_ENVCURLY", "cal_NCURLY",
- "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"",
- "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start",
- "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable",
- "EnvVarName", "MultipleIds", "ID", YY_NULLPTR
+ "\"end of file\"", "error", "\"invalid token\"", "cal_ENVCURLY",
+ "cal_NCURLY", "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME",
+ "\"\\\\\"", "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept",
+ "Start", "GoalWithOptionalBackSlash", "Goal", "String", "OuterText",
+ "Variable", "EnvVarName", "MultipleIds", "ID", YY_NULLPTR
};
+
+static const char *
+yysymbol_name (yysymbol_kind_t yysymbol)
+{
+ return yytname[yysymbol];
+}
#endif
-# ifdef YYPRINT
+#ifdef YYPRINT
/* YYTOKNUM[NUM] -- (External) token number corresponding to the
(internal) symbol number NUM (which must be that of a token). */
-static const yytype_uint16 yytoknum[] =
+static const yytype_int16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269
};
-# endif
+#endif
-#define YYPACT_NINF -3
+#define YYPACT_NINF (-3)
-#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-3)))
+#define yypact_value_is_default(Yyn) \
+ ((Yyn) == YYPACT_NINF)
-#define YYTABLE_NINF -1
+#define YYTABLE_NINF (-1)
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(Yyn) \
0
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -552,7 +618,7 @@ static const yytype_int8 yypact[] =
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
Performed when YYTABLE does not specify something else to do. Zero
means the default is an error. */
-static const yytype_uint8 yydefact[] =
+static const yytype_int8 yydefact[] =
{
5, 21, 21, 21, 11, 12, 13, 9, 14, 10,
18, 0, 2, 3, 5, 7, 8, 23, 21, 24,
@@ -575,7 +641,7 @@ static const yytype_int8 yydefgoto[] =
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule whose
number is the opposite. If YYTABLE_NINF, syntax error. */
-static const yytype_uint8 yytable[] =
+static const yytype_int8 yytable[] =
{
23, 24, 16, 1, 2, 3, 4, 5, 6, 7,
25, 8, 9, 26, 10, 29, 16, 1, 2, 3,
@@ -595,7 +661,7 @@ static const yytype_int8 yycheck[] =
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
+static const yytype_int8 yystos[] =
{
0, 3, 4, 5, 6, 7, 8, 9, 11, 12,
14, 16, 17, 18, 19, 20, 21, 9, 11, 21,
@@ -604,7 +670,7 @@ static const yytype_uint8 yystos[] =
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
+static const yytype_int8 yyr1[] =
{
0, 15, 16, 17, 17, 18, 18, 19, 19, 20,
20, 20, 20, 20, 20, 21, 21, 21, 21, 22,
@@ -612,7 +678,7 @@ static const yytype_uint8 yyr1[] =
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yyr2[] =
{
0, 2, 1, 1, 2, 0, 2, 1, 1, 1,
1, 1, 1, 1, 1, 3, 3, 3, 1, 1,
@@ -620,10 +686,10 @@ static const yytype_uint8 yyr2[] =
};
+enum { YYENOMEM = -2 };
+
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
@@ -649,10 +715,9 @@ static const yytype_uint8 yyr2[] =
} \
while (0)
-/* Error token number */
-#define YYTERROR 1
-#define YYERRCODE 256
-
+/* Backward compatibility with an undocumented macro.
+ Use YYerror or YYUNDEF. */
+#define YYERRCODE YYUNDEF
/* Enable debugging if requested. */
@@ -670,18 +735,18 @@ do { \
} while (0)
/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+# ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
do { \
if (yydebug) \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
- Type, Value, yyscanner); \
+ Kind, Value, yyscanner); \
YYFPRINTF (stderr, "\n"); \
} \
} while (0)
@@ -692,7 +757,8 @@ do { \
`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
YYUSE (yyoutput);
@@ -700,11 +766,11 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
if (!yyvaluep)
return;
# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
+ if (yykind < YYNTOKENS)
+ YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -714,12 +780,13 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
`---------------------------*/
static void
-yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
YYFPRINTF (yyo, "%s %s (",
- yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+ yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));
- yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ yy_symbol_value_print (yyo, yykind, yyvaluep, yyscanner);
YYFPRINTF (yyo, ")");
}
@@ -729,7 +796,7 @@ yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t
`------------------------------------------------------------------*/
static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -752,21 +819,21 @@ do { \
`------------------------------------------------*/
static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
+ int yyrule, yyscan_t yyscanner)
{
- unsigned long yylno = yyrline[yyrule];
+ int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
- yystos[yyssp[yyi + 1 - yynrhs]],
- &yyvsp[(yyi + 1) - (yynrhs)]
- , yyscanner);
+ YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
+ &yyvsp[(yyi + 1) - (yynrhs)], yyscanner);
YYFPRINTF (stderr, "\n");
}
}
@@ -781,8 +848,8 @@ do { \
multiple parsers can coexist. */
int yydebug;
#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YYDPRINTF(Args) ((void) 0)
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
@@ -805,28 +872,76 @@ int yydebug;
#endif
-#if YYERROR_VERBOSE
+/* Context of a parse error. */
+typedef struct
+{
+ yy_state_t *yyssp;
+ yysymbol_kind_t yytoken;
+} yypcontext_t;
+
+/* Put in YYARG at most YYARGN of the expected tokens given the
+ current YYCTX, and return the number of tokens stored in YYARG. If
+ YYARG is null, return the number of expected tokens (guaranteed to
+ be less than YYNTOKENS). Return YYENOMEM on memory exhaustion.
+ Return 0 if there are more than YYARGN expected tokens, yet fill
+ YYARG up to YYARGN. */
+static int
+yypcontext_expected_tokens (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
+{
+ /* Actual size of YYARG. */
+ int yycount = 0;
+ int yyn = yypact[+*yyctx->yyssp];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (!yyarg)
+ ++yycount;
+ else if (yycount == yyargn)
+ return 0;
+ else
+ yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx);
+ }
+ }
+ if (yyarg && yycount == 0 && 0 < yyargn)
+ yyarg[0] = YYSYMBOL_YYEMPTY;
+ return yycount;
+}
+
+
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
+
+#ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
+# else
/* Return the length of YYSTR. */
-static YYSIZE_T
+static YYPTRDIFF_T
yystrlen (const char *yystr)
{
- YYSIZE_T yylen;
+ YYPTRDIFF_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
continue;
return yylen;
}
-# endif
# endif
+#endif
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
+#ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
static char *
@@ -840,10 +955,10 @@ yystpcpy (char *yydest, const char *yysrc)
return yyd - 1;
}
-# endif
# endif
+#endif
-# ifndef yytnamerr
+#ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
quotes and backslashes, so that it's suitable for yyerror. The
heuristic is that double-quoting is unnecessary unless the string
@@ -851,14 +966,13 @@ yystpcpy (char *yydest, const char *yysrc)
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
-static YYSIZE_T
+static YYPTRDIFF_T
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
- YYSIZE_T yyn = 0;
+ YYPTRDIFF_T yyn = 0;
char const *yyp = yystr;
-
for (;;)
switch (*++yyp)
{
@@ -887,36 +1001,20 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ;
}
- if (! yyres)
+ if (yyres)
+ return yystpcpy (yyres, yystr) - yyres;
+ else
return yystrlen (yystr);
-
- return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
-# endif
+#endif
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
+yy_syntax_error_arguments (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULLPTR;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
+ /* Actual size of YYARG. */
int yycount = 0;
-
/* There are many possibilities here to consider:
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
@@ -940,49 +1038,54 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
one exception: it will still contain any token that will not be
accepted due to an error action in a later state.
*/
- if (yytoken != YYEMPTY)
+ if (yyctx->yytoken != YYSYMBOL_YYEMPTY)
{
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- {
- YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
- }
- }
- }
+ int yyn;
+ if (yyarg)
+ yyarg[yycount] = yyctx->yytoken;
+ ++yycount;
+ yyn = yypcontext_expected_tokens (yyctx,
+ yyarg ? yyarg + 1 : yyarg, yyargn - 1);
+ if (yyn == YYENOMEM)
+ return YYENOMEM;
+ else
+ yycount += yyn;
}
+ return yycount;
+}
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
+ const yypcontext_t *yyctx)
+{
+ enum { YYARGS_MAX = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat: reported tokens (one for the "unexpected",
+ one per "expected"). */
+ yysymbol_kind_t yyarg[YYARGS_MAX];
+ /* Cumulated lengths of YYARG. */
+ YYPTRDIFF_T yysize = 0;
+
+ /* Actual size of YYARG. */
+ int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX);
+ if (yycount == YYENOMEM)
+ return YYENOMEM;
switch (yycount)
{
-# define YYCASE_(N, S) \
+#define YYCASE_(N, S) \
case N: \
yyformat = S; \
- break
+ break
default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
@@ -990,15 +1093,23 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
+#undef YYCASE_
}
+ /* Compute error message size. Don't count the "%s"s, but reserve
+ room for the terminator. */
+ yysize = yystrlen (yyformat) - 2 * yycount + 1;
{
- YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
+ int yyi;
+ for (yyi = 0; yyi < yycount; ++yyi)
+ {
+ YYPTRDIFF_T yysize1
+ = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]);
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
+ return YYENOMEM;
+ }
}
if (*yymsg_alloc < yysize)
@@ -1007,7 +1118,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
if (! (yysize <= *yymsg_alloc
&& *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
*yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
+ return -1;
}
/* Avoid sprintf, as that infringes on the user's name space.
@@ -1019,40 +1130,43 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
while ((*yyp = *yyformat) != '\0')
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
- yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);
yyformat += 2;
}
else
{
- yyp++;
- yyformat++;
+ ++yyp;
+ ++yyformat;
}
}
return 0;
}
-#endif /* YYERROR_VERBOSE */
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+yydestruct (const char *yymsg,
+ yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
YYUSE (yyvaluep);
YYUSE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
+
+
/*----------.
| yyparse. |
`----------*/
@@ -1060,7 +1174,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner
int
yyparse (yyscan_t yyscanner)
{
-/* The lookahead symbol. */
+/* Lookahead token kind. */
int yychar;
@@ -1071,45 +1185,41 @@ YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
/* Number of syntax errors so far. */
- int yynerrs;
+ int yynerrs = 0;
- int yystate;
+ yy_state_fast_t yystate = 0;
/* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
+ int yyerrstatus = 0;
- /* The stacks and their tools:
- 'yyss': related to states.
- 'yyvs': related to semantic values.
-
- Refer to the stacks through separate pointers, to allow yyoverflow
+ /* Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss;
- yytype_int16 *yyssp;
+ /* Their size. */
+ YYPTRDIFF_T yystacksize = YYINITDEPTH;
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs;
- YYSTYPE *yyvsp;
+ /* The state stack: array, bottom, top. */
+ yy_state_t yyssa[YYINITDEPTH];
+ yy_state_t *yyss = yyssa;
+ yy_state_t *yyssp = yyss;
- YYSIZE_T yystacksize;
+ /* The semantic value stack: array, bottom, top. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp = yyvs;
int yyn;
+ /* The return value of yyparse. */
int yyresult;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
+ /* Lookahead symbol kind. */
+ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
-#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
+ YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
@@ -1117,15 +1227,8 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;
- yystacksize = YYINITDEPTH;
-
YYDPRINTF ((stderr, "Starting parse\n"));
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
@@ -1140,12 +1243,15 @@ yynewstate:
/*--------------------------------------------------------------------.
-| yynewstate -- set current state (the top of the stack) to yystate. |
+| yysetstate -- set current state (the top of the stack) to yystate. |
`--------------------------------------------------------------------*/
yysetstate:
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
- *yyssp = (yytype_int16) yystate;
+ YY_IGNORE_USELESS_CAST_BEGIN
+ *yyssp = YY_CAST (yy_state_t, yystate);
+ YY_IGNORE_USELESS_CAST_END
+ YY_STACK_PRINT (yyss, yyssp);
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
@@ -1153,23 +1259,23 @@ yysetstate:
#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
+ YYPTRDIFF_T yysize = yyssp - yyss + 1;
# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
+ yy_state_t *yyss1 = yyss;
YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
+ &yyss1, yysize * YYSIZEOF (*yyssp),
+ &yyvs1, yysize * YYSIZEOF (*yyvsp),
&yystacksize);
yyss = yyss1;
yyvs = yyvs1;
@@ -1183,14 +1289,15 @@ yysetstate:
yystacksize = YYMAXDEPTH;
{
- yytype_int16 *yyss1 = yyss;
+ yy_state_t *yyss1 = yyss;
union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ YY_CAST (union yyalloc *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
@@ -1199,8 +1306,10 @@ yysetstate:
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long) yystacksize));
+ YY_IGNORE_USELESS_CAST_BEGIN
+ YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+ YY_CAST (long, yystacksize)));
+ YY_IGNORE_USELESS_CAST_END
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
@@ -1227,18 +1336,29 @@ yybackup:
/* Not known => get a lookahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
if (yychar == YYEMPTY)
{
- YYDPRINTF ((stderr, "Reading a token: "));
+ YYDPRINTF ((stderr, "Reading a token\n"));
yychar = yylex (&yylval, yyscanner);
}
if (yychar <= YYEOF)
{
- yychar = yytoken = YYEOF;
+ yychar = YYEOF;
+ yytoken = YYSYMBOL_YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n"));
}
+ else if (yychar == YYerror)
+ {
+ /* The scanner already issued an error message, process directly
+ to error recovery. But do not keep the error token as
+ lookahead, it is too special and may lead us to an endless
+ loop in error recovery. */
+ yychar = YYUNDEF;
+ yytoken = YYSYMBOL_YYerror;
+ goto yyerrlab1;
+ }
else
{
yytoken = YYTRANSLATE (yychar);
@@ -1266,14 +1386,13 @@ yybackup:
/* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token. */
- yychar = YYEMPTY;
-
yystate = yyn;
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
goto yynewstate;
@@ -1308,193 +1427,193 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 2:
-#line 99 "cmCommandArgumentParser.y"
- {
+ case 2: /* Start: GoalWithOptionalBackSlash */
+#line 97 "cmCommandArgumentParser.y"
+ {
(yyval.str) = 0;
yyGetParser->SetResult((yyvsp[0].str));
}
-#line 1318 "cmCommandArgumentParser.cxx"
+#line 1437 "cmCommandArgumentParser.cxx"
break;
- case 3:
-#line 105 "cmCommandArgumentParser.y"
- {
+ case 3: /* GoalWithOptionalBackSlash: Goal */
+#line 103 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1326 "cmCommandArgumentParser.cxx"
+#line 1445 "cmCommandArgumentParser.cxx"
break;
- case 4:
-#line 108 "cmCommandArgumentParser.y"
- {
+ case 4: /* GoalWithOptionalBackSlash: Goal "\\" */
+#line 106 "cmCommandArgumentParser.y"
+ {
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1334 "cmCommandArgumentParser.cxx"
+#line 1453 "cmCommandArgumentParser.cxx"
break;
- case 5:
-#line 113 "cmCommandArgumentParser.y"
- {
+ case 5: /* Goal: %empty */
+#line 111 "cmCommandArgumentParser.y"
+ {
(yyval.str) = 0;
}
-#line 1342 "cmCommandArgumentParser.cxx"
+#line 1461 "cmCommandArgumentParser.cxx"
break;
- case 6:
-#line 116 "cmCommandArgumentParser.y"
- {
+ case 6: /* Goal: String Goal */
+#line 114 "cmCommandArgumentParser.y"
+ {
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1350 "cmCommandArgumentParser.cxx"
+#line 1469 "cmCommandArgumentParser.cxx"
break;
- case 7:
-#line 121 "cmCommandArgumentParser.y"
- {
+ case 7: /* String: OuterText */
+#line 119 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1358 "cmCommandArgumentParser.cxx"
+#line 1477 "cmCommandArgumentParser.cxx"
break;
- case 8:
-#line 124 "cmCommandArgumentParser.y"
- {
+ case 8: /* String: Variable */
+#line 122 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1366 "cmCommandArgumentParser.cxx"
+#line 1485 "cmCommandArgumentParser.cxx"
break;
- case 9:
-#line 129 "cmCommandArgumentParser.y"
- {
+ case 9: /* OuterText: cal_NAME */
+#line 127 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1374 "cmCommandArgumentParser.cxx"
+#line 1493 "cmCommandArgumentParser.cxx"
break;
- case 10:
-#line 132 "cmCommandArgumentParser.y"
- {
+ case 10: /* OuterText: "@" */
+#line 130 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1382 "cmCommandArgumentParser.cxx"
+#line 1501 "cmCommandArgumentParser.cxx"
break;
- case 11:
-#line 135 "cmCommandArgumentParser.y"
- {
+ case 11: /* OuterText: "$" */
+#line 133 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1390 "cmCommandArgumentParser.cxx"
+#line 1509 "cmCommandArgumentParser.cxx"
break;
- case 12:
-#line 138 "cmCommandArgumentParser.y"
- {
+ case 12: /* OuterText: "{" */
+#line 136 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1398 "cmCommandArgumentParser.cxx"
+#line 1517 "cmCommandArgumentParser.cxx"
break;
- case 13:
-#line 141 "cmCommandArgumentParser.y"
- {
+ case 13: /* OuterText: "}" */
+#line 139 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1406 "cmCommandArgumentParser.cxx"
+#line 1525 "cmCommandArgumentParser.cxx"
break;
- case 14:
-#line 144 "cmCommandArgumentParser.y"
- {
+ case 14: /* OuterText: cal_SYMBOL */
+#line 142 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1414 "cmCommandArgumentParser.cxx"
+#line 1533 "cmCommandArgumentParser.cxx"
break;
- case 15:
-#line 149 "cmCommandArgumentParser.y"
- {
+ case 15: /* Variable: cal_ENVCURLY EnvVarName "}" */
+#line 147 "cmCommandArgumentParser.y"
+ {
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1422 "cmCommandArgumentParser.cxx"
+#line 1541 "cmCommandArgumentParser.cxx"
break;
- case 16:
-#line 152 "cmCommandArgumentParser.y"
- {
+ case 16: /* Variable: cal_NCURLY MultipleIds "}" */
+#line 150 "cmCommandArgumentParser.y"
+ {
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1430 "cmCommandArgumentParser.cxx"
+#line 1549 "cmCommandArgumentParser.cxx"
break;
- case 17:
-#line 155 "cmCommandArgumentParser.y"
- {
+ case 17: /* Variable: cal_DCURLY MultipleIds "}" */
+#line 153 "cmCommandArgumentParser.y"
+ {
(yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
}
-#line 1438 "cmCommandArgumentParser.cxx"
+#line 1557 "cmCommandArgumentParser.cxx"
break;
- case 18:
-#line 158 "cmCommandArgumentParser.y"
- {
+ case 18: /* Variable: cal_ATNAME */
+#line 156 "cmCommandArgumentParser.y"
+ {
(yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
}
-#line 1446 "cmCommandArgumentParser.cxx"
+#line 1565 "cmCommandArgumentParser.cxx"
break;
- case 19:
-#line 163 "cmCommandArgumentParser.y"
- {
+ case 19: /* EnvVarName: MultipleIds */
+#line 161 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1454 "cmCommandArgumentParser.cxx"
+#line 1573 "cmCommandArgumentParser.cxx"
break;
- case 20:
-#line 166 "cmCommandArgumentParser.y"
- {
+ case 20: /* EnvVarName: cal_SYMBOL EnvVarName */
+#line 164 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[-1].str);
}
-#line 1462 "cmCommandArgumentParser.cxx"
+#line 1581 "cmCommandArgumentParser.cxx"
break;
- case 21:
-#line 171 "cmCommandArgumentParser.y"
- {
+ case 21: /* MultipleIds: %empty */
+#line 169 "cmCommandArgumentParser.y"
+ {
(yyval.str) = 0;
}
-#line 1470 "cmCommandArgumentParser.cxx"
+#line 1589 "cmCommandArgumentParser.cxx"
break;
- case 22:
-#line 174 "cmCommandArgumentParser.y"
- {
+ case 22: /* MultipleIds: ID MultipleIds */
+#line 172 "cmCommandArgumentParser.y"
+ {
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1478 "cmCommandArgumentParser.cxx"
+#line 1597 "cmCommandArgumentParser.cxx"
break;
- case 23:
-#line 179 "cmCommandArgumentParser.y"
- {
+ case 23: /* ID: cal_NAME */
+#line 177 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1486 "cmCommandArgumentParser.cxx"
+#line 1605 "cmCommandArgumentParser.cxx"
break;
- case 24:
-#line 182 "cmCommandArgumentParser.y"
- {
+ case 24: /* ID: Variable */
+#line 180 "cmCommandArgumentParser.y"
+ {
(yyval.str) = (yyvsp[0].str);
}
-#line 1494 "cmCommandArgumentParser.cxx"
+#line 1613 "cmCommandArgumentParser.cxx"
break;
-#line 1498 "cmCommandArgumentParser.cxx"
+#line 1617 "cmCommandArgumentParser.cxx"
default: break;
}
@@ -1509,11 +1628,10 @@ yyreduce:
case of YYERROR or YYBACKUP, subsequent parser actions might lead
to an incorrect destructor call or verbose syntax error message
before the lookahead is translated. */
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);
YYPOPSTACK (yylen);
yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
@@ -1537,50 +1655,44 @@ yyreduce:
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
+ yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (yyscanner, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
{
+ yypcontext_t yyctx
+ = {yyssp, yytoken};
char const *yymsgp = YY_("syntax error");
int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
+ yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
if (yysyntax_error_status == 0)
yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
+ else if (yysyntax_error_status == -1)
{
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
+ yymsg = YY_CAST (char *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc)));
+ if (yymsg)
{
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
+ yysyntax_error_status
+ = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
+ yymsgp = yymsg;
}
else
{
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = YYENOMEM;
}
}
yyerror (yyscanner, yymsgp);
- if (yysyntax_error_status == 2)
+ if (yysyntax_error_status == YYENOMEM)
goto yyexhaustedlab;
}
-# undef YYSYNTAX_ERROR
-#endif
}
-
-
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
@@ -1600,7 +1712,6 @@ yyerrlab:
}
}
-#if 0
/* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -1628,16 +1739,16 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
-#endif
yyerrstatus = 3; /* Each real token shifted decrements this. */
+ /* Pop stack until we find a state that shifts the error token. */
for (;;)
{
yyn = yypact[yystate];
if (!yypact_value_is_default (yyn))
{
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ yyn += YYSYMBOL_YYerror;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
{
yyn = yytable[yyn];
if (0 < yyn)
@@ -1651,7 +1762,7 @@ yyerrlab1:
yydestruct ("Error: popping",
- yystos[yystate], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (yystate), yyvsp, yyscanner);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
@@ -1663,7 +1774,7 @@ yyerrlab1:
/* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
yystate = yyn;
goto yynewstate;
@@ -1685,20 +1796,20 @@ yyabortlab:
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if 1
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
yyerror (yyscanner, YY_("memory exhausted"));
yyresult = 2;
- /* Fall through. */
+ goto yyreturn;
#endif
-/*-----------------------------------------------------.
-| yyreturn -- parsing is finished, return the result. |
-`-----------------------------------------------------*/
+/*-------------------------------------------------------.
+| yyreturn -- parsing is finished, clean up and return. |
+`-------------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -1715,20 +1826,19 @@ yyreturn:
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yyscanner);
YYPOPSTACK (1);
}
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
-#if YYERROR_VERBOSE
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
-#endif
return yyresult;
}
-#line 187 "cmCommandArgumentParser.y"
+
+#line 185 "cmCommandArgumentParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmCommandArgumentParser.y b/Source/LexerParser/cmCommandArgumentParser.y
index 0c6aad547..26894158f 100644
--- a/Source/LexerParser/cmCommandArgumentParser.y
+++ b/Source/LexerParser/cmCommandArgumentParser.y
@@ -7,10 +7,7 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
-
-Modify cmCommandArgumentParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+ bison --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
*/
@@ -25,6 +22,7 @@ Modify cmCommandArgumentParser.cxx:
# include <malloc.h>
#endif
+#include <stdint.h>
/* Make sure the parser uses standard memory allocation. The default
generated parser malloc/free declarations do not work on all
platforms. */
@@ -35,7 +33,6 @@ Modify cmCommandArgumentParser.cxx:
/*-------------------------------------------------------------------------*/
#include "cmCommandArgumentParserHelper.h" /* Interface to parser object. */
#include "cmCommandArgumentLexer.h" /* Interface to lexer object. */
-#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL. */
/* Forward declare the lexer entry point. */
YY_DECL;
@@ -57,6 +54,7 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
#endif
%}
diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h
index 033b8994d..578f7937c 100644
--- a/Source/LexerParser/cmCommandArgumentParserTokens.h
+++ b/Source/LexerParser/cmCommandArgumentParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -31,8 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
@@ -44,38 +45,30 @@
extern int cmCommandArgument_yydebug;
#endif
-/* Token type. */
+/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
- cal_ENVCURLY = 258,
- cal_NCURLY = 259,
- cal_DCURLY = 260,
- cal_DOLLAR = 261,
- cal_LCURLY = 262,
- cal_RCURLY = 263,
- cal_NAME = 264,
- cal_BSLASH = 265,
- cal_SYMBOL = 266,
- cal_AT = 267,
- cal_ERROR = 268,
- cal_ATNAME = 269
+ YYEMPTY = -2,
+ YYEOF = 0, /* "end of file" */
+ YYerror = 256, /* error */
+ YYUNDEF = 257, /* "invalid token" */
+ cal_ENVCURLY = 258, /* cal_ENVCURLY */
+ cal_NCURLY = 259, /* cal_NCURLY */
+ cal_DCURLY = 260, /* cal_DCURLY */
+ cal_DOLLAR = 261, /* "$" */
+ cal_LCURLY = 262, /* "{" */
+ cal_RCURLY = 263, /* "}" */
+ cal_NAME = 264, /* cal_NAME */
+ cal_BSLASH = 265, /* "\\" */
+ cal_SYMBOL = 266, /* cal_SYMBOL */
+ cal_AT = 267, /* "@" */
+ cal_ERROR = 268, /* cal_ERROR */
+ cal_ATNAME = 269 /* cal_ATNAME */
};
+ typedef enum yytokentype yytoken_kind_t;
#endif
-/* Tokens. */
-#define cal_ENVCURLY 258
-#define cal_NCURLY 259
-#define cal_DCURLY 260
-#define cal_DOLLAR 261
-#define cal_LCURLY 262
-#define cal_RCURLY 263
-#define cal_NAME 264
-#define cal_BSLASH 265
-#define cal_SYMBOL 266
-#define cal_AT 267
-#define cal_ERROR 268
-#define cal_ATNAME 269
/* Value type. */
diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx
index b15082ddb..27cc177e6 100644
--- a/Source/LexerParser/cmDependsJavaParser.cxx
+++ b/Source/LexerParser/cmDependsJavaParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -34,6 +34,10 @@
/* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
+
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros.
@@ -41,14 +45,11 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
-
-/* Identify Bison output. */
-#define YYBISON 1
+/* Identify Bison output, and Bison version. */
+#define YYBISON 30704
-/* Bison version. */
-#define YYBISON_VERSION "3.4.2"
+/* Bison version string. */
+#define YYBISON_VERSION "3.7.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -70,7 +71,6 @@
#define yydebug cmDependsJava_yydebug
#define yynerrs cmDependsJava_yynerrs
-
/* First part of user prologue. */
#line 1 "cmDependsJavaParser.y"
@@ -82,15 +82,13 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
-
-Modify cmDependsJavaParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+ bison --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
*/
#include "cmConfigure.h" // IWYU pragma: keep
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <string>
@@ -100,7 +98,6 @@ Modify cmDependsJavaParser.cxx:
/*-------------------------------------------------------------------------*/
#include "cmDependsJavaParserHelper.h" /* Interface to parser object. */
#include "cmDependsJavaLexer.h" /* Interface to lexer object. */
-#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL. */
/* Forward declare the lexer entry point. */
YY_DECL;
@@ -121,10 +118,20 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
#endif
-#line 127 "cmDependsJavaParser.cxx"
+#line 125 "cmDependsJavaParser.cxx"
+# ifndef YY_CAST
+# ifdef __cplusplus
+# define YY_CAST(Type, Val) static_cast<Type> (Val)
+# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
+# else
+# define YY_CAST(Type, Val) ((Type) (Val))
+# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+# endif
+# endif
# ifndef YY_NULLPTR
# if defined __cplusplus
# if 201103L <= __cplusplus
@@ -137,248 +144,278 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
# endif
# endif
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* Use api.header.include to #include this header
- instead of duplicating it here. */
-#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
-# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
-/* Debug traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int cmDependsJava_yydebug;
-#endif
+#include "cmDependsJavaParserTokens.h"
+/* Symbol kind. */
+enum yysymbol_kind_t
+{
+ YYSYMBOL_YYEMPTY = -2,
+ YYSYMBOL_YYEOF = 0, /* "end of file" */
+ YYSYMBOL_YYerror = 1, /* error */
+ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
+ YYSYMBOL_jp_ABSTRACT = 3, /* jp_ABSTRACT */
+ YYSYMBOL_jp_ASSERT = 4, /* jp_ASSERT */
+ YYSYMBOL_jp_BOOLEAN_TYPE = 5, /* jp_BOOLEAN_TYPE */
+ YYSYMBOL_jp_BREAK = 6, /* jp_BREAK */
+ YYSYMBOL_jp_BYTE_TYPE = 7, /* jp_BYTE_TYPE */
+ YYSYMBOL_jp_CASE = 8, /* jp_CASE */
+ YYSYMBOL_jp_CATCH = 9, /* jp_CATCH */
+ YYSYMBOL_jp_CHAR_TYPE = 10, /* jp_CHAR_TYPE */
+ YYSYMBOL_jp_CLASS = 11, /* jp_CLASS */
+ YYSYMBOL_jp_CONTINUE = 12, /* jp_CONTINUE */
+ YYSYMBOL_jp_DEFAULT = 13, /* jp_DEFAULT */
+ YYSYMBOL_jp_DO = 14, /* jp_DO */
+ YYSYMBOL_jp_DOUBLE_TYPE = 15, /* jp_DOUBLE_TYPE */
+ YYSYMBOL_jp_ELSE = 16, /* jp_ELSE */
+ YYSYMBOL_jp_EXTENDS = 17, /* jp_EXTENDS */
+ YYSYMBOL_jp_FINAL = 18, /* jp_FINAL */
+ YYSYMBOL_jp_FINALLY = 19, /* jp_FINALLY */
+ YYSYMBOL_jp_FLOAT_TYPE = 20, /* jp_FLOAT_TYPE */
+ YYSYMBOL_jp_FOR = 21, /* jp_FOR */
+ YYSYMBOL_jp_IF = 22, /* jp_IF */
+ YYSYMBOL_jp_IMPLEMENTS = 23, /* jp_IMPLEMENTS */
+ YYSYMBOL_jp_IMPORT = 24, /* jp_IMPORT */
+ YYSYMBOL_jp_INSTANCEOF = 25, /* jp_INSTANCEOF */
+ YYSYMBOL_jp_INT_TYPE = 26, /* jp_INT_TYPE */
+ YYSYMBOL_jp_INTERFACE = 27, /* jp_INTERFACE */
+ YYSYMBOL_jp_LONG_TYPE = 28, /* jp_LONG_TYPE */
+ YYSYMBOL_jp_NATIVE = 29, /* jp_NATIVE */
+ YYSYMBOL_jp_NEW = 30, /* jp_NEW */
+ YYSYMBOL_jp_PACKAGE = 31, /* jp_PACKAGE */
+ YYSYMBOL_jp_PRIVATE = 32, /* jp_PRIVATE */
+ YYSYMBOL_jp_PROTECTED = 33, /* jp_PROTECTED */
+ YYSYMBOL_jp_PUBLIC = 34, /* jp_PUBLIC */
+ YYSYMBOL_jp_RETURN = 35, /* jp_RETURN */
+ YYSYMBOL_jp_SHORT_TYPE = 36, /* jp_SHORT_TYPE */
+ YYSYMBOL_jp_STATIC = 37, /* jp_STATIC */
+ YYSYMBOL_jp_STRICTFP = 38, /* jp_STRICTFP */
+ YYSYMBOL_jp_SUPER = 39, /* jp_SUPER */
+ YYSYMBOL_jp_SWITCH = 40, /* jp_SWITCH */
+ YYSYMBOL_jp_SYNCHRONIZED = 41, /* jp_SYNCHRONIZED */
+ YYSYMBOL_jp_THIS = 42, /* jp_THIS */
+ YYSYMBOL_jp_THROW = 43, /* jp_THROW */
+ YYSYMBOL_jp_THROWS = 44, /* jp_THROWS */
+ YYSYMBOL_jp_TRANSIENT = 45, /* jp_TRANSIENT */
+ YYSYMBOL_jp_TRY = 46, /* jp_TRY */
+ YYSYMBOL_jp_VOID = 47, /* jp_VOID */
+ YYSYMBOL_jp_VOLATILE = 48, /* jp_VOLATILE */
+ YYSYMBOL_jp_WHILE = 49, /* jp_WHILE */
+ YYSYMBOL_jp_BOOLEANLITERAL = 50, /* jp_BOOLEANLITERAL */
+ YYSYMBOL_jp_CHARACTERLITERAL = 51, /* jp_CHARACTERLITERAL */
+ YYSYMBOL_jp_DECIMALINTEGERLITERAL = 52, /* jp_DECIMALINTEGERLITERAL */
+ YYSYMBOL_jp_FLOATINGPOINTLITERAL = 53, /* jp_FLOATINGPOINTLITERAL */
+ YYSYMBOL_jp_HEXINTEGERLITERAL = 54, /* jp_HEXINTEGERLITERAL */
+ YYSYMBOL_jp_NULLLITERAL = 55, /* jp_NULLLITERAL */
+ YYSYMBOL_jp_STRINGLITERAL = 56, /* jp_STRINGLITERAL */
+ YYSYMBOL_jp_NAME = 57, /* jp_NAME */
+ YYSYMBOL_jp_AND = 58, /* jp_AND */
+ YYSYMBOL_jp_ANDAND = 59, /* jp_ANDAND */
+ YYSYMBOL_jp_ANDEQUALS = 60, /* jp_ANDEQUALS */
+ YYSYMBOL_jp_BRACKETEND = 61, /* jp_BRACKETEND */
+ YYSYMBOL_jp_BRACKETSTART = 62, /* jp_BRACKETSTART */
+ YYSYMBOL_jp_CARROT = 63, /* jp_CARROT */
+ YYSYMBOL_jp_CARROTEQUALS = 64, /* jp_CARROTEQUALS */
+ YYSYMBOL_jp_COLON = 65, /* jp_COLON */
+ YYSYMBOL_jp_COMMA = 66, /* jp_COMMA */
+ YYSYMBOL_jp_CURLYEND = 67, /* jp_CURLYEND */
+ YYSYMBOL_jp_CURLYSTART = 68, /* jp_CURLYSTART */
+ YYSYMBOL_jp_DIVIDE = 69, /* jp_DIVIDE */
+ YYSYMBOL_jp_DIVIDEEQUALS = 70, /* jp_DIVIDEEQUALS */
+ YYSYMBOL_jp_DOLLAR = 71, /* jp_DOLLAR */
+ YYSYMBOL_jp_DOT = 72, /* jp_DOT */
+ YYSYMBOL_jp_EQUALS = 73, /* jp_EQUALS */
+ YYSYMBOL_jp_EQUALSEQUALS = 74, /* jp_EQUALSEQUALS */
+ YYSYMBOL_jp_EXCLAMATION = 75, /* jp_EXCLAMATION */
+ YYSYMBOL_jp_EXCLAMATIONEQUALS = 76, /* jp_EXCLAMATIONEQUALS */
+ YYSYMBOL_jp_GREATER = 77, /* jp_GREATER */
+ YYSYMBOL_jp_GTEQUALS = 78, /* jp_GTEQUALS */
+ YYSYMBOL_jp_GTGT = 79, /* jp_GTGT */
+ YYSYMBOL_jp_GTGTEQUALS = 80, /* jp_GTGTEQUALS */
+ YYSYMBOL_jp_GTGTGT = 81, /* jp_GTGTGT */
+ YYSYMBOL_jp_GTGTGTEQUALS = 82, /* jp_GTGTGTEQUALS */
+ YYSYMBOL_jp_LESLESEQUALS = 83, /* jp_LESLESEQUALS */
+ YYSYMBOL_jp_LESSTHAN = 84, /* jp_LESSTHAN */
+ YYSYMBOL_jp_LTEQUALS = 85, /* jp_LTEQUALS */
+ YYSYMBOL_jp_LTLT = 86, /* jp_LTLT */
+ YYSYMBOL_jp_MINUS = 87, /* jp_MINUS */
+ YYSYMBOL_jp_MINUSEQUALS = 88, /* jp_MINUSEQUALS */
+ YYSYMBOL_jp_MINUSMINUS = 89, /* jp_MINUSMINUS */
+ YYSYMBOL_jp_PAREEND = 90, /* jp_PAREEND */
+ YYSYMBOL_jp_PARESTART = 91, /* jp_PARESTART */
+ YYSYMBOL_jp_PERCENT = 92, /* jp_PERCENT */
+ YYSYMBOL_jp_PERCENTEQUALS = 93, /* jp_PERCENTEQUALS */
+ YYSYMBOL_jp_PIPE = 94, /* jp_PIPE */
+ YYSYMBOL_jp_PIPEEQUALS = 95, /* jp_PIPEEQUALS */
+ YYSYMBOL_jp_PIPEPIPE = 96, /* jp_PIPEPIPE */
+ YYSYMBOL_jp_PLUS = 97, /* jp_PLUS */
+ YYSYMBOL_jp_PLUSEQUALS = 98, /* jp_PLUSEQUALS */
+ YYSYMBOL_jp_PLUSPLUS = 99, /* jp_PLUSPLUS */
+ YYSYMBOL_jp_QUESTION = 100, /* jp_QUESTION */
+ YYSYMBOL_jp_SEMICOL = 101, /* jp_SEMICOL */
+ YYSYMBOL_jp_TILDE = 102, /* jp_TILDE */
+ YYSYMBOL_jp_TIMES = 103, /* jp_TIMES */
+ YYSYMBOL_jp_TIMESEQUALS = 104, /* jp_TIMESEQUALS */
+ YYSYMBOL_jp_ERROR = 105, /* jp_ERROR */
+ YYSYMBOL_YYACCEPT = 106, /* $accept */
+ YYSYMBOL_Goal = 107, /* Goal */
+ YYSYMBOL_Literal = 108, /* Literal */
+ YYSYMBOL_IntegerLiteral = 109, /* IntegerLiteral */
+ YYSYMBOL_Type = 110, /* Type */
+ YYSYMBOL_PrimitiveType = 111, /* PrimitiveType */
+ YYSYMBOL_ReferenceType = 112, /* ReferenceType */
+ YYSYMBOL_ClassOrInterfaceType = 113, /* ClassOrInterfaceType */
+ YYSYMBOL_ClassType = 114, /* ClassType */
+ YYSYMBOL_InterfaceType = 115, /* InterfaceType */
+ YYSYMBOL_ArrayType = 116, /* ArrayType */
+ YYSYMBOL_Name = 117, /* Name */
+ YYSYMBOL_SimpleName = 118, /* SimpleName */
+ YYSYMBOL_Identifier = 119, /* Identifier */
+ YYSYMBOL_QualifiedName = 120, /* QualifiedName */
+ YYSYMBOL_SimpleType = 121, /* SimpleType */
+ YYSYMBOL_CompilationUnit = 122, /* CompilationUnit */
+ YYSYMBOL_PackageDeclarationopt = 123, /* PackageDeclarationopt */
+ YYSYMBOL_ImportDeclarations = 124, /* ImportDeclarations */
+ YYSYMBOL_TypeDeclarations = 125, /* TypeDeclarations */
+ YYSYMBOL_PackageDeclaration = 126, /* PackageDeclaration */
+ YYSYMBOL_ImportDeclaration = 127, /* ImportDeclaration */
+ YYSYMBOL_SingleTypeImportDeclaration = 128, /* SingleTypeImportDeclaration */
+ YYSYMBOL_TypeImportOnDemandDeclaration = 129, /* TypeImportOnDemandDeclaration */
+ YYSYMBOL_TypeDeclaration = 130, /* TypeDeclaration */
+ YYSYMBOL_Modifiers = 131, /* Modifiers */
+ YYSYMBOL_Modifier = 132, /* Modifier */
+ YYSYMBOL_ClassHeader = 133, /* ClassHeader */
+ YYSYMBOL_ClassDeclaration = 134, /* ClassDeclaration */
+ YYSYMBOL_Modifiersopt = 135, /* Modifiersopt */
+ YYSYMBOL_Super = 136, /* Super */
+ YYSYMBOL_Interfaces = 137, /* Interfaces */
+ YYSYMBOL_InterfaceTypeList = 138, /* InterfaceTypeList */
+ YYSYMBOL_ClassBody = 139, /* ClassBody */
+ YYSYMBOL_ClassBodyDeclarations = 140, /* ClassBodyDeclarations */
+ YYSYMBOL_ClassBodyDeclaration = 141, /* ClassBodyDeclaration */
+ YYSYMBOL_ClassMemberDeclaration = 142, /* ClassMemberDeclaration */
+ YYSYMBOL_FieldDeclaration = 143, /* FieldDeclaration */
+ YYSYMBOL_VariableDeclarators = 144, /* VariableDeclarators */
+ YYSYMBOL_VariableDeclarator = 145, /* VariableDeclarator */
+ YYSYMBOL_VariableDeclaratorId = 146, /* VariableDeclaratorId */
+ YYSYMBOL_VariableInitializer = 147, /* VariableInitializer */
+ YYSYMBOL_MethodDeclaration = 148, /* MethodDeclaration */
+ YYSYMBOL_MethodHeader = 149, /* MethodHeader */
+ YYSYMBOL_Throwsopt = 150, /* Throwsopt */
+ YYSYMBOL_MethodDeclarator = 151, /* MethodDeclarator */
+ YYSYMBOL_FormalParameterListopt = 152, /* FormalParameterListopt */
+ YYSYMBOL_FormalParameterList = 153, /* FormalParameterList */
+ YYSYMBOL_FormalParameter = 154, /* FormalParameter */
+ YYSYMBOL_Throws = 155, /* Throws */
+ YYSYMBOL_ClassTypeList = 156, /* ClassTypeList */
+ YYSYMBOL_MethodBody = 157, /* MethodBody */
+ YYSYMBOL_StaticInitializer = 158, /* StaticInitializer */
+ YYSYMBOL_ConstructorDeclaration = 159, /* ConstructorDeclaration */
+ YYSYMBOL_ConstructorDeclarator = 160, /* ConstructorDeclarator */
+ YYSYMBOL_ConstructorBody = 161, /* ConstructorBody */
+ YYSYMBOL_ExplicitConstructorInvocationopt = 162, /* ExplicitConstructorInvocationopt */
+ YYSYMBOL_ExplicitConstructorInvocation = 163, /* ExplicitConstructorInvocation */
+ YYSYMBOL_InterfaceHeader = 164, /* InterfaceHeader */
+ YYSYMBOL_InterfaceDeclaration = 165, /* InterfaceDeclaration */
+ YYSYMBOL_ExtendsInterfacesopt = 166, /* ExtendsInterfacesopt */
+ YYSYMBOL_ExtendsInterfaces = 167, /* ExtendsInterfaces */
+ YYSYMBOL_InterfaceBody = 168, /* InterfaceBody */
+ YYSYMBOL_InterfaceMemberDeclarations = 169, /* InterfaceMemberDeclarations */
+ YYSYMBOL_InterfaceMemberDeclaration = 170, /* InterfaceMemberDeclaration */
+ YYSYMBOL_ConstantDeclaration = 171, /* ConstantDeclaration */
+ YYSYMBOL_AbstractMethodDeclaration = 172, /* AbstractMethodDeclaration */
+ YYSYMBOL_Semicols = 173, /* Semicols */
+ YYSYMBOL_ArrayInitializer = 174, /* ArrayInitializer */
+ YYSYMBOL_VariableInitializersOptional = 175, /* VariableInitializersOptional */
+ YYSYMBOL_VariableInitializers = 176, /* VariableInitializers */
+ YYSYMBOL_Block = 177, /* Block */
+ YYSYMBOL_BlockStatementsopt = 178, /* BlockStatementsopt */
+ YYSYMBOL_BlockStatements = 179, /* BlockStatements */
+ YYSYMBOL_BlockStatement = 180, /* BlockStatement */
+ YYSYMBOL_LocalVariableDeclarationStatement = 181, /* LocalVariableDeclarationStatement */
+ YYSYMBOL_LocalVariableDeclaration = 182, /* LocalVariableDeclaration */
+ YYSYMBOL_Statement = 183, /* Statement */
+ YYSYMBOL_StatementNoShortIf = 184, /* StatementNoShortIf */
+ YYSYMBOL_StatementWithoutTrailingSubstatement = 185, /* StatementWithoutTrailingSubstatement */
+ YYSYMBOL_EmptyStatement = 186, /* EmptyStatement */
+ YYSYMBOL_LabeledStatement = 187, /* LabeledStatement */
+ YYSYMBOL_LabeledStatementNoShortIf = 188, /* LabeledStatementNoShortIf */
+ YYSYMBOL_ExpressionStatement = 189, /* ExpressionStatement */
+ YYSYMBOL_StatementExpression = 190, /* StatementExpression */
+ YYSYMBOL_IfThenStatement = 191, /* IfThenStatement */
+ YYSYMBOL_IfThenElseStatement = 192, /* IfThenElseStatement */
+ YYSYMBOL_IfThenElseStatementNoShortIf = 193, /* IfThenElseStatementNoShortIf */
+ YYSYMBOL_SwitchStatement = 194, /* SwitchStatement */
+ YYSYMBOL_SwitchBlock = 195, /* SwitchBlock */
+ YYSYMBOL_SwitchLabelsopt = 196, /* SwitchLabelsopt */
+ YYSYMBOL_SwitchBlockStatementGroups = 197, /* SwitchBlockStatementGroups */
+ YYSYMBOL_SwitchBlockStatementGroup = 198, /* SwitchBlockStatementGroup */
+ YYSYMBOL_SwitchLabels = 199, /* SwitchLabels */
+ YYSYMBOL_SwitchLabel = 200, /* SwitchLabel */
+ YYSYMBOL_WhileStatement = 201, /* WhileStatement */
+ YYSYMBOL_WhileStatementNoShortIf = 202, /* WhileStatementNoShortIf */
+ YYSYMBOL_DoStatement = 203, /* DoStatement */
+ YYSYMBOL_ForStatement = 204, /* ForStatement */
+ YYSYMBOL_ForUpdateopt = 205, /* ForUpdateopt */
+ YYSYMBOL_ForInitopt = 206, /* ForInitopt */
+ YYSYMBOL_ForStatementNoShortIf = 207, /* ForStatementNoShortIf */
+ YYSYMBOL_Expressionopt = 208, /* Expressionopt */
+ YYSYMBOL_ForInit = 209, /* ForInit */
+ YYSYMBOL_ForUpdate = 210, /* ForUpdate */
+ YYSYMBOL_StatementExpressionList = 211, /* StatementExpressionList */
+ YYSYMBOL_AssertStatement = 212, /* AssertStatement */
+ YYSYMBOL_BreakStatement = 213, /* BreakStatement */
+ YYSYMBOL_Identifieropt = 214, /* Identifieropt */
+ YYSYMBOL_ContinueStatement = 215, /* ContinueStatement */
+ YYSYMBOL_ReturnStatement = 216, /* ReturnStatement */
+ YYSYMBOL_ThrowStatement = 217, /* ThrowStatement */
+ YYSYMBOL_SynchronizedStatement = 218, /* SynchronizedStatement */
+ YYSYMBOL_TryStatement = 219, /* TryStatement */
+ YYSYMBOL_Catchesopt = 220, /* Catchesopt */
+ YYSYMBOL_Catches = 221, /* Catches */
+ YYSYMBOL_CatchClause = 222, /* CatchClause */
+ YYSYMBOL_Finally = 223, /* Finally */
+ YYSYMBOL_Primary = 224, /* Primary */
+ YYSYMBOL_PrimaryNoNewArray = 225, /* PrimaryNoNewArray */
+ YYSYMBOL_ClassInstanceCreationExpression = 226, /* ClassInstanceCreationExpression */
+ YYSYMBOL_ClassBodyOpt = 227, /* ClassBodyOpt */
+ YYSYMBOL_ArgumentListopt = 228, /* ArgumentListopt */
+ YYSYMBOL_ArgumentList = 229, /* ArgumentList */
+ YYSYMBOL_ArrayCreationExpression = 230, /* ArrayCreationExpression */
+ YYSYMBOL_Dimsopt = 231, /* Dimsopt */
+ YYSYMBOL_DimExprs = 232, /* DimExprs */
+ YYSYMBOL_DimExpr = 233, /* DimExpr */
+ YYSYMBOL_Dims = 234, /* Dims */
+ YYSYMBOL_FieldAccess = 235, /* FieldAccess */
+ YYSYMBOL_MethodInvocation = 236, /* MethodInvocation */
+ YYSYMBOL_ArrayAccess = 237, /* ArrayAccess */
+ YYSYMBOL_PostfixExpression = 238, /* PostfixExpression */
+ YYSYMBOL_PostIncrementExpression = 239, /* PostIncrementExpression */
+ YYSYMBOL_PostDecrementExpression = 240, /* PostDecrementExpression */
+ YYSYMBOL_UnaryExpression = 241, /* UnaryExpression */
+ YYSYMBOL_PreIncrementExpression = 242, /* PreIncrementExpression */
+ YYSYMBOL_PreDecrementExpression = 243, /* PreDecrementExpression */
+ YYSYMBOL_UnaryExpressionNotPlusMinus = 244, /* UnaryExpressionNotPlusMinus */
+ YYSYMBOL_CastExpression = 245, /* CastExpression */
+ YYSYMBOL_MultiplicativeExpression = 246, /* MultiplicativeExpression */
+ YYSYMBOL_AdditiveExpression = 247, /* AdditiveExpression */
+ YYSYMBOL_ShiftExpression = 248, /* ShiftExpression */
+ YYSYMBOL_RelationalExpression = 249, /* RelationalExpression */
+ YYSYMBOL_EqualityExpression = 250, /* EqualityExpression */
+ YYSYMBOL_AndExpression = 251, /* AndExpression */
+ YYSYMBOL_ExclusiveOrExpression = 252, /* ExclusiveOrExpression */
+ YYSYMBOL_InclusiveOrExpression = 253, /* InclusiveOrExpression */
+ YYSYMBOL_ConditionalAndExpression = 254, /* ConditionalAndExpression */
+ YYSYMBOL_ConditionalOrExpression = 255, /* ConditionalOrExpression */
+ YYSYMBOL_ConditionalExpression = 256, /* ConditionalExpression */
+ YYSYMBOL_AssignmentExpression = 257, /* AssignmentExpression */
+ YYSYMBOL_Assignment = 258, /* Assignment */
+ YYSYMBOL_LeftHandSide = 259, /* LeftHandSide */
+ YYSYMBOL_AssignmentOperator = 260, /* AssignmentOperator */
+ YYSYMBOL_Expression = 261, /* Expression */
+ YYSYMBOL_ConstantExpression = 262, /* ConstantExpression */
+ YYSYMBOL_New = 263 /* New */
+};
+typedef enum yysymbol_kind_t yysymbol_kind_t;
-/* Token type. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- enum yytokentype
- {
- jp_ABSTRACT = 258,
- jp_ASSERT = 259,
- jp_BOOLEAN_TYPE = 260,
- jp_BREAK = 261,
- jp_BYTE_TYPE = 262,
- jp_CASE = 263,
- jp_CATCH = 264,
- jp_CHAR_TYPE = 265,
- jp_CLASS = 266,
- jp_CONTINUE = 267,
- jp_DEFAULT = 268,
- jp_DO = 269,
- jp_DOUBLE_TYPE = 270,
- jp_ELSE = 271,
- jp_EXTENDS = 272,
- jp_FINAL = 273,
- jp_FINALLY = 274,
- jp_FLOAT_TYPE = 275,
- jp_FOR = 276,
- jp_IF = 277,
- jp_IMPLEMENTS = 278,
- jp_IMPORT = 279,
- jp_INSTANCEOF = 280,
- jp_INT_TYPE = 281,
- jp_INTERFACE = 282,
- jp_LONG_TYPE = 283,
- jp_NATIVE = 284,
- jp_NEW = 285,
- jp_PACKAGE = 286,
- jp_PRIVATE = 287,
- jp_PROTECTED = 288,
- jp_PUBLIC = 289,
- jp_RETURN = 290,
- jp_SHORT_TYPE = 291,
- jp_STATIC = 292,
- jp_STRICTFP = 293,
- jp_SUPER = 294,
- jp_SWITCH = 295,
- jp_SYNCHRONIZED = 296,
- jp_THIS = 297,
- jp_THROW = 298,
- jp_THROWS = 299,
- jp_TRANSIENT = 300,
- jp_TRY = 301,
- jp_VOID = 302,
- jp_VOLATILE = 303,
- jp_WHILE = 304,
- jp_BOOLEANLITERAL = 305,
- jp_CHARACTERLITERAL = 306,
- jp_DECIMALINTEGERLITERAL = 307,
- jp_FLOATINGPOINTLITERAL = 308,
- jp_HEXINTEGERLITERAL = 309,
- jp_NULLLITERAL = 310,
- jp_STRINGLITERAL = 311,
- jp_NAME = 312,
- jp_AND = 313,
- jp_ANDAND = 314,
- jp_ANDEQUALS = 315,
- jp_BRACKETEND = 316,
- jp_BRACKETSTART = 317,
- jp_CARROT = 318,
- jp_CARROTEQUALS = 319,
- jp_COLON = 320,
- jp_COMMA = 321,
- jp_CURLYEND = 322,
- jp_CURLYSTART = 323,
- jp_DIVIDE = 324,
- jp_DIVIDEEQUALS = 325,
- jp_DOLLAR = 326,
- jp_DOT = 327,
- jp_EQUALS = 328,
- jp_EQUALSEQUALS = 329,
- jp_EXCLAMATION = 330,
- jp_EXCLAMATIONEQUALS = 331,
- jp_GREATER = 332,
- jp_GTEQUALS = 333,
- jp_GTGT = 334,
- jp_GTGTEQUALS = 335,
- jp_GTGTGT = 336,
- jp_GTGTGTEQUALS = 337,
- jp_LESLESEQUALS = 338,
- jp_LESSTHAN = 339,
- jp_LTEQUALS = 340,
- jp_LTLT = 341,
- jp_MINUS = 342,
- jp_MINUSEQUALS = 343,
- jp_MINUSMINUS = 344,
- jp_PAREEND = 345,
- jp_PARESTART = 346,
- jp_PERCENT = 347,
- jp_PERCENTEQUALS = 348,
- jp_PIPE = 349,
- jp_PIPEEQUALS = 350,
- jp_PIPEPIPE = 351,
- jp_PLUS = 352,
- jp_PLUSEQUALS = 353,
- jp_PLUSPLUS = 354,
- jp_QUESTION = 355,
- jp_SEMICOL = 356,
- jp_TILDE = 357,
- jp_TIMES = 358,
- jp_TIMESEQUALS = 359,
- jp_ERROR = 360
- };
-#endif
-/* Tokens. */
-#define jp_ABSTRACT 258
-#define jp_ASSERT 259
-#define jp_BOOLEAN_TYPE 260
-#define jp_BREAK 261
-#define jp_BYTE_TYPE 262
-#define jp_CASE 263
-#define jp_CATCH 264
-#define jp_CHAR_TYPE 265
-#define jp_CLASS 266
-#define jp_CONTINUE 267
-#define jp_DEFAULT 268
-#define jp_DO 269
-#define jp_DOUBLE_TYPE 270
-#define jp_ELSE 271
-#define jp_EXTENDS 272
-#define jp_FINAL 273
-#define jp_FINALLY 274
-#define jp_FLOAT_TYPE 275
-#define jp_FOR 276
-#define jp_IF 277
-#define jp_IMPLEMENTS 278
-#define jp_IMPORT 279
-#define jp_INSTANCEOF 280
-#define jp_INT_TYPE 281
-#define jp_INTERFACE 282
-#define jp_LONG_TYPE 283
-#define jp_NATIVE 284
-#define jp_NEW 285
-#define jp_PACKAGE 286
-#define jp_PRIVATE 287
-#define jp_PROTECTED 288
-#define jp_PUBLIC 289
-#define jp_RETURN 290
-#define jp_SHORT_TYPE 291
-#define jp_STATIC 292
-#define jp_STRICTFP 293
-#define jp_SUPER 294
-#define jp_SWITCH 295
-#define jp_SYNCHRONIZED 296
-#define jp_THIS 297
-#define jp_THROW 298
-#define jp_THROWS 299
-#define jp_TRANSIENT 300
-#define jp_TRY 301
-#define jp_VOID 302
-#define jp_VOLATILE 303
-#define jp_WHILE 304
-#define jp_BOOLEANLITERAL 305
-#define jp_CHARACTERLITERAL 306
-#define jp_DECIMALINTEGERLITERAL 307
-#define jp_FLOATINGPOINTLITERAL 308
-#define jp_HEXINTEGERLITERAL 309
-#define jp_NULLLITERAL 310
-#define jp_STRINGLITERAL 311
-#define jp_NAME 312
-#define jp_AND 313
-#define jp_ANDAND 314
-#define jp_ANDEQUALS 315
-#define jp_BRACKETEND 316
-#define jp_BRACKETSTART 317
-#define jp_CARROT 318
-#define jp_CARROTEQUALS 319
-#define jp_COLON 320
-#define jp_COMMA 321
-#define jp_CURLYEND 322
-#define jp_CURLYSTART 323
-#define jp_DIVIDE 324
-#define jp_DIVIDEEQUALS 325
-#define jp_DOLLAR 326
-#define jp_DOT 327
-#define jp_EQUALS 328
-#define jp_EQUALSEQUALS 329
-#define jp_EXCLAMATION 330
-#define jp_EXCLAMATIONEQUALS 331
-#define jp_GREATER 332
-#define jp_GTEQUALS 333
-#define jp_GTGT 334
-#define jp_GTGTEQUALS 335
-#define jp_GTGTGT 336
-#define jp_GTGTGTEQUALS 337
-#define jp_LESLESEQUALS 338
-#define jp_LESSTHAN 339
-#define jp_LTEQUALS 340
-#define jp_LTLT 341
-#define jp_MINUS 342
-#define jp_MINUSEQUALS 343
-#define jp_MINUSMINUS 344
-#define jp_PAREEND 345
-#define jp_PARESTART 346
-#define jp_PERCENT 347
-#define jp_PERCENTEQUALS 348
-#define jp_PIPE 349
-#define jp_PIPEEQUALS 350
-#define jp_PIPEPIPE 351
-#define jp_PLUS 352
-#define jp_PLUSEQUALS 353
-#define jp_PLUSPLUS 354
-#define jp_QUESTION 355
-#define jp_SEMICOL 356
-#define jp_TILDE 357
-#define jp_TIMES 358
-#define jp_TIMESEQUALS 359
-#define jp_ERROR 360
-
-/* Value type. */
-
-
-
-int cmDependsJava_yyparse (yyscan_t yyscanner);
-
-#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */
@@ -386,28 +423,75 @@ int cmDependsJava_yyparse (yyscan_t yyscanner);
# undef short
#endif
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+ <limits.h> and (if available) <stdint.h> are included
+ so that the code can choose integer types of a good width. */
+
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_STDINT_H
+# endif
#endif
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
+/* Narrow types that promote to a signed type and that can represent a
+ signed or unsigned integer of at least N bits. In tables they can
+ save space and decrease cache pressure. Promoting to a signed type
+ helps avoid bugs in integer arithmetic. */
+
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
#else
typedef signed char yytype_int8;
#endif
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
#else
-typedef unsigned short yytype_uint16;
+typedef short yytype_int16;
#endif
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
+#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 \
+ && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
#else
-typedef short yytype_int16;
+typedef short yytype_uint8;
+#endif
+
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
+typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
+#endif
+
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+# define YYPTRDIFF_T __PTRDIFF_TYPE__
+# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+# ifndef ptrdiff_t
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# endif
+# define YYPTRDIFF_T ptrdiff_t
+# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+# define YYPTRDIFF_T long
+# define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
#endif
#ifndef YYSIZE_T
@@ -415,7 +499,7 @@ typedef short yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -423,7 +507,20 @@ typedef short yytype_int16;
# endif
#endif
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+#define YYSIZE_MAXIMUM \
+ YY_CAST (YYPTRDIFF_T, \
+ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
+ ? YYPTRDIFF_MAXIMUM \
+ : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_int16 yy_state_t;
+
+/* State numbers in computations. */
+typedef int yy_state_fast_t;
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
@@ -437,22 +534,21 @@ typedef short yytype_int16;
# endif
#endif
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__ \
- && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
- || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
-# else
-# define YY_ATTRIBUTE(Spec) /* empty */
-# endif
-#endif
#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define YY_ATTRIBUTE_PURE
+# endif
#endif
#ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+# define YY_ATTRIBUTE_UNUSED
+# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
@@ -464,11 +560,11 @@ typedef short yytype_int16;
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
@@ -481,10 +577,22 @@ typedef short yytype_int16;
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
+#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END \
+ _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
#define YY_ASSERT(E) ((void) (0 && (E)))
-#if ! defined yyoverflow || YYERROR_VERBOSE
+#if 1
/* The parser invokes alloca or malloc; define the necessary symbols. */
@@ -549,8 +657,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
+#endif /* 1 */
#if (! defined yyoverflow \
&& (! defined __cplusplus \
@@ -559,17 +666,17 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss_alloc;
+ yy_state_t yyss_alloc;
YYSTYPE yyvs_alloc;
};
/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
# define YYCOPY_NEEDED 1
@@ -582,11 +689,11 @@ union yyalloc
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
- YYSIZE_T yynewbytes; \
+ YYPTRDIFF_T yynewbytes; \
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
+ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / YYSIZEOF (*yyptr); \
} \
while (0)
@@ -598,12 +705,12 @@ union yyalloc
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
# else
# define YYCOPY(Dst, Src, Count) \
do \
{ \
- YYSIZE_T yyi; \
+ YYPTRDIFF_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
@@ -626,17 +733,20 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 575
-#define YYUNDEFTOK 2
+/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 360
+
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
-#define YYTRANSLATE(YYX) \
- ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+#define YYTRANSLATE(YYX) \
+ (0 <= (YYX) && (YYX) <= YYMAXUTOK \
+ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
+ : YYSYMBOL_YYUNDEF)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */
-static const yytype_uint8 yytranslate[] =
+static const yytype_int8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -679,63 +789,70 @@ static const yytype_uint8 yytranslate[] =
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
-{
- 0, 182, 182, 191, 199, 207, 215, 223, 231, 240,
- 248, 257, 265, 274, 279, 284, 289, 294, 299, 304,
- 309, 315, 323, 332, 342, 351, 360, 368, 378, 384,
- 391, 398, 404, 411, 420, 430, 440, 449, 457, 466,
- 475, 481, 490, 496, 505, 511, 520, 532, 540, 549,
- 561, 574, 582, 590, 599, 607, 616, 616, 616, 617,
- 618, 618, 618, 618, 618, 618, 619, 622, 632, 641,
- 650, 659, 669, 675, 684, 693, 702, 710, 719, 728,
- 734, 743, 751, 759, 767, 776, 784, 793, 799, 807,
- 816, 824, 833, 842, 851, 859, 868, 876, 884, 893,
- 902, 912, 919, 929, 939, 946, 953, 956, 962, 972,
- 982, 992, 998, 1008, 1018, 1028, 1037, 1047, 1058, 1068,
- 1075, 1085, 1094, 1104, 1113, 1123, 1129, 1139, 1148, 1158,
- 1168, 1175, 1184, 1193, 1202, 1211, 1219, 1228, 1237, 1247,
- 1257, 1266, 1276, 1286, 1293, 1302, 1312, 1321, 1331, 1340,
- 1347, 1357, 1366, 1376, 1385, 1394, 1404, 1414, 1423, 1433,
- 1442, 1451, 1460, 1469, 1478, 1488, 1497, 1506, 1515, 1524,
- 1534, 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, 1615,
- 1624, 1633, 1643, 1653, 1664, 1674, 1684, 1693, 1702, 1711,
- 1720, 1729, 1738, 1748, 1758, 1768, 1778, 1785, 1792, 1799,
- 1809, 1816, 1826, 1836, 1845, 1855, 1864, 1874, 1881, 1888,
- 1895, 1903, 1910, 1920, 1927, 1937, 1947, 1954, 1964, 1973,
- 1983, 1993, 2002, 2012, 2021, 2031, 2042, 2049, 2056, 2067,
- 2077, 2087, 2097, 2106, 2116, 2123, 2133, 2142, 2152, 2159,
- 2169, 2178, 2188, 2197, 2203, 2212, 2221, 2230, 2239, 2249,
- 2259, 2266, 2276, 2283, 2293, 2302, 2312, 2321, 2330, 2339,
- 2349, 2356, 2366, 2375, 2385, 2395, 2401, 2408, 2418, 2428,
- 2438, 2449, 2459, 2470, 2480, 2491, 2501, 2511, 2520, 2529,
- 2538, 2547, 2557, 2567, 2577, 2586, 2595, 2604, 2613, 2623,
- 2633, 2643, 2652, 2661, 2670, 2680, 2689, 2698, 2705, 2714,
- 2723, 2732, 2742, 2751, 2760, 2770, 2779, 2788, 2797, 2807,
- 2816, 2825, 2834, 2843, 2852, 2862, 2871, 2880, 2890, 2899,
- 2909, 2918, 2928, 2937, 2947, 2956, 2966, 2975, 2985, 2994,
- 3004, 3013, 3023, 3033, 3043, 3052, 3062, 3071, 3080, 3089,
- 3098, 3107, 3116, 3125, 3134, 3143, 3152, 3161, 3171, 3181,
- 3191, 3200
+static const yytype_int16 yyrline[] =
+{
+ 0, 180, 180, 189, 197, 205, 213, 221, 229, 238,
+ 246, 255, 263, 272, 277, 282, 287, 292, 297, 302,
+ 307, 313, 321, 330, 340, 349, 358, 366, 376, 382,
+ 389, 396, 402, 409, 418, 428, 438, 447, 455, 464,
+ 473, 479, 488, 494, 503, 509, 518, 530, 538, 547,
+ 559, 572, 580, 588, 597, 605, 614, 614, 614, 615,
+ 616, 616, 616, 616, 616, 616, 617, 620, 630, 639,
+ 648, 657, 667, 673, 682, 691, 700, 708, 717, 726,
+ 732, 741, 749, 757, 765, 774, 782, 791, 797, 805,
+ 814, 822, 831, 840, 849, 857, 866, 874, 882, 891,
+ 900, 910, 917, 927, 937, 944, 951, 954, 960, 970,
+ 980, 990, 996, 1006, 1016, 1026, 1035, 1045, 1056, 1066,
+ 1073, 1083, 1092, 1102, 1111, 1121, 1127, 1137, 1146, 1156,
+ 1166, 1173, 1182, 1191, 1200, 1209, 1217, 1226, 1235, 1245,
+ 1255, 1264, 1274, 1284, 1291, 1300, 1310, 1319, 1329, 1338,
+ 1345, 1355, 1364, 1374, 1383, 1392, 1402, 1412, 1421, 1431,
+ 1440, 1449, 1458, 1467, 1476, 1486, 1495, 1504, 1513, 1522,
+ 1532, 1541, 1550, 1559, 1568, 1577, 1586, 1595, 1604, 1613,
+ 1622, 1631, 1641, 1651, 1662, 1672, 1682, 1691, 1700, 1709,
+ 1718, 1727, 1736, 1746, 1756, 1766, 1776, 1783, 1790, 1797,
+ 1807, 1814, 1824, 1834, 1843, 1853, 1862, 1872, 1879, 1886,
+ 1893, 1901, 1908, 1918, 1925, 1935, 1945, 1952, 1962, 1971,
+ 1981, 1991, 2000, 2010, 2019, 2029, 2040, 2047, 2054, 2065,
+ 2075, 2085, 2095, 2104, 2114, 2121, 2131, 2140, 2150, 2157,
+ 2167, 2176, 2186, 2195, 2201, 2210, 2219, 2228, 2237, 2247,
+ 2257, 2264, 2274, 2281, 2291, 2300, 2310, 2319, 2328, 2337,
+ 2347, 2354, 2364, 2373, 2383, 2393, 2399, 2406, 2416, 2426,
+ 2436, 2447, 2457, 2468, 2478, 2489, 2499, 2509, 2518, 2527,
+ 2536, 2545, 2555, 2565, 2575, 2584, 2593, 2602, 2611, 2621,
+ 2631, 2641, 2650, 2659, 2668, 2678, 2687, 2696, 2703, 2712,
+ 2721, 2730, 2740, 2749, 2758, 2768, 2777, 2786, 2795, 2805,
+ 2814, 2823, 2832, 2841, 2850, 2860, 2869, 2878, 2888, 2897,
+ 2907, 2916, 2926, 2935, 2945, 2954, 2964, 2973, 2983, 2992,
+ 3002, 3011, 3021, 3031, 3041, 3050, 3060, 3069, 3078, 3087,
+ 3096, 3105, 3114, 3123, 3132, 3141, 3150, 3159, 3169, 3179,
+ 3189, 3198
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 1
+/** Accessing symbol of state STATE. */
+#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
+
+#if 1
+/* The user-facing name of the symbol whose (internal) number is
+ YYSYMBOL. No bounds checking. */
+static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
+
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "jp_ABSTRACT", "jp_ASSERT",
- "jp_BOOLEAN_TYPE", "jp_BREAK", "jp_BYTE_TYPE", "jp_CASE", "jp_CATCH",
- "jp_CHAR_TYPE", "jp_CLASS", "jp_CONTINUE", "jp_DEFAULT", "jp_DO",
- "jp_DOUBLE_TYPE", "jp_ELSE", "jp_EXTENDS", "jp_FINAL", "jp_FINALLY",
- "jp_FLOAT_TYPE", "jp_FOR", "jp_IF", "jp_IMPLEMENTS", "jp_IMPORT",
- "jp_INSTANCEOF", "jp_INT_TYPE", "jp_INTERFACE", "jp_LONG_TYPE",
- "jp_NATIVE", "jp_NEW", "jp_PACKAGE", "jp_PRIVATE", "jp_PROTECTED",
- "jp_PUBLIC", "jp_RETURN", "jp_SHORT_TYPE", "jp_STATIC", "jp_STRICTFP",
- "jp_SUPER", "jp_SWITCH", "jp_SYNCHRONIZED", "jp_THIS", "jp_THROW",
- "jp_THROWS", "jp_TRANSIENT", "jp_TRY", "jp_VOID", "jp_VOLATILE",
- "jp_WHILE", "jp_BOOLEANLITERAL", "jp_CHARACTERLITERAL",
+ "\"end of file\"", "error", "\"invalid token\"", "jp_ABSTRACT",
+ "jp_ASSERT", "jp_BOOLEAN_TYPE", "jp_BREAK", "jp_BYTE_TYPE", "jp_CASE",
+ "jp_CATCH", "jp_CHAR_TYPE", "jp_CLASS", "jp_CONTINUE", "jp_DEFAULT",
+ "jp_DO", "jp_DOUBLE_TYPE", "jp_ELSE", "jp_EXTENDS", "jp_FINAL",
+ "jp_FINALLY", "jp_FLOAT_TYPE", "jp_FOR", "jp_IF", "jp_IMPLEMENTS",
+ "jp_IMPORT", "jp_INSTANCEOF", "jp_INT_TYPE", "jp_INTERFACE",
+ "jp_LONG_TYPE", "jp_NATIVE", "jp_NEW", "jp_PACKAGE", "jp_PRIVATE",
+ "jp_PROTECTED", "jp_PUBLIC", "jp_RETURN", "jp_SHORT_TYPE", "jp_STATIC",
+ "jp_STRICTFP", "jp_SUPER", "jp_SWITCH", "jp_SYNCHRONIZED", "jp_THIS",
+ "jp_THROW", "jp_THROWS", "jp_TRANSIENT", "jp_TRY", "jp_VOID",
+ "jp_VOLATILE", "jp_WHILE", "jp_BOOLEANLITERAL", "jp_CHARACTERLITERAL",
"jp_DECIMALINTEGERLITERAL", "jp_FLOATINGPOINTLITERAL",
"jp_HEXINTEGERLITERAL", "jp_NULLLITERAL", "jp_STRINGLITERAL", "jp_NAME",
"jp_AND", "jp_ANDAND", "jp_ANDEQUALS", "jp_BRACKETEND",
@@ -801,12 +918,18 @@ static const char *const yytname[] =
"LeftHandSide", "AssignmentOperator", "Expression", "ConstantExpression",
"New", YY_NULLPTR
};
+
+static const char *
+yysymbol_name (yysymbol_kind_t yysymbol)
+{
+ return yytname[yysymbol];
+}
#endif
-# ifdef YYPRINT
+#ifdef YYPRINT
/* YYTOKNUM[NUM] -- (External) token number corresponding to the
(internal) symbol number NUM (which must be that of a token). */
-static const yytype_uint16 yytoknum[] =
+static const yytype_int16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
@@ -820,16 +943,16 @@ static const yytype_uint16 yytoknum[] =
345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
355, 356, 357, 358, 359, 360
};
-# endif
+#endif
-#define YYPACT_NINF -503
+#define YYPACT_NINF (-503)
-#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-503)))
+#define yypact_value_is_default(Yyn) \
+ ((Yyn) == YYPACT_NINF)
-#define YYTABLE_NINF -336
+#define YYTABLE_NINF (-336)
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(Yyn) \
0
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -899,7 +1022,7 @@ static const yytype_int16 yypact[] =
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
Performed when YYTABLE does not specify something else to do. Zero
means the default is an error. */
-static const yytype_uint16 yydefact[] =
+static const yytype_int16 yydefact[] =
{
40, 0, 0, 2, 42, 41, 20, 13, 17, 19,
18, 15, 16, 14, 38, 31, 0, 37, 0, 28,
@@ -1460,7 +1583,7 @@ static const yytype_int16 yycheck[] =
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
-static const yytype_uint16 yystos[] =
+static const yytype_int16 yystos[] =
{
0, 31, 107, 122, 123, 126, 5, 7, 10, 15,
20, 26, 28, 36, 47, 57, 71, 111, 117, 118,
@@ -1523,7 +1646,7 @@ static const yytype_uint16 yystos[] =
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint16 yyr1[] =
+static const yytype_int16 yyr1[] =
{
0, 106, 107, 108, 108, 108, 108, 108, 108, 109,
109, 110, 110, 111, 111, 111, 111, 111, 111, 111,
@@ -1564,7 +1687,7 @@ static const yytype_uint16 yyr1[] =
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yyr2[] =
{
0, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -1605,10 +1728,10 @@ static const yytype_uint8 yyr2[] =
};
+enum { YYENOMEM = -2 };
+
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
@@ -1634,10 +1757,9 @@ static const yytype_uint8 yyr2[] =
} \
while (0)
-/* Error token number */
-#define YYTERROR 1
-#define YYERRCODE 256
-
+/* Backward compatibility with an undocumented macro.
+ Use YYerror or YYUNDEF. */
+#define YYERRCODE YYUNDEF
/* Enable debugging if requested. */
@@ -1655,18 +1777,18 @@ do { \
} while (0)
/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+# ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
do { \
if (yydebug) \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
- Type, Value, yyscanner); \
+ Kind, Value, yyscanner); \
YYFPRINTF (stderr, "\n"); \
} \
} while (0)
@@ -1677,7 +1799,8 @@ do { \
`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
YYUSE (yyoutput);
@@ -1685,11 +1808,11 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
if (!yyvaluep)
return;
# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
+ if (yykind < YYNTOKENS)
+ YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -1699,12 +1822,13 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
`---------------------------*/
static void
-yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
YYFPRINTF (yyo, "%s %s (",
- yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+ yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));
- yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ yy_symbol_value_print (yyo, yykind, yyvaluep, yyscanner);
YYFPRINTF (yyo, ")");
}
@@ -1714,7 +1838,7 @@ yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t
`------------------------------------------------------------------*/
static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -1737,21 +1861,21 @@ do { \
`------------------------------------------------*/
static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
+ int yyrule, yyscan_t yyscanner)
{
- unsigned long yylno = yyrline[yyrule];
+ int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
- yystos[yyssp[yyi + 1 - yynrhs]],
- &yyvsp[(yyi + 1) - (yynrhs)]
- , yyscanner);
+ YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
+ &yyvsp[(yyi + 1) - (yynrhs)], yyscanner);
YYFPRINTF (stderr, "\n");
}
}
@@ -1766,8 +1890,8 @@ do { \
multiple parsers can coexist. */
int yydebug;
#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YYDPRINTF(Args) ((void) 0)
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
@@ -1790,28 +1914,76 @@ int yydebug;
#endif
-#if YYERROR_VERBOSE
+/* Context of a parse error. */
+typedef struct
+{
+ yy_state_t *yyssp;
+ yysymbol_kind_t yytoken;
+} yypcontext_t;
+
+/* Put in YYARG at most YYARGN of the expected tokens given the
+ current YYCTX, and return the number of tokens stored in YYARG. If
+ YYARG is null, return the number of expected tokens (guaranteed to
+ be less than YYNTOKENS). Return YYENOMEM on memory exhaustion.
+ Return 0 if there are more than YYARGN expected tokens, yet fill
+ YYARG up to YYARGN. */
+static int
+yypcontext_expected_tokens (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
+{
+ /* Actual size of YYARG. */
+ int yycount = 0;
+ int yyn = yypact[+*yyctx->yyssp];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (!yyarg)
+ ++yycount;
+ else if (yycount == yyargn)
+ return 0;
+ else
+ yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx);
+ }
+ }
+ if (yyarg && yycount == 0 && 0 < yyargn)
+ yyarg[0] = YYSYMBOL_YYEMPTY;
+ return yycount;
+}
+
+
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
+
+#ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
+# else
/* Return the length of YYSTR. */
-static YYSIZE_T
+static YYPTRDIFF_T
yystrlen (const char *yystr)
{
- YYSIZE_T yylen;
+ YYPTRDIFF_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
continue;
return yylen;
}
-# endif
# endif
+#endif
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
+#ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
static char *
@@ -1825,10 +1997,10 @@ yystpcpy (char *yydest, const char *yysrc)
return yyd - 1;
}
-# endif
# endif
+#endif
-# ifndef yytnamerr
+#ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
quotes and backslashes, so that it's suitable for yyerror. The
heuristic is that double-quoting is unnecessary unless the string
@@ -1836,14 +2008,13 @@ yystpcpy (char *yydest, const char *yysrc)
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
-static YYSIZE_T
+static YYPTRDIFF_T
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
- YYSIZE_T yyn = 0;
+ YYPTRDIFF_T yyn = 0;
char const *yyp = yystr;
-
for (;;)
switch (*++yyp)
{
@@ -1872,36 +2043,20 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ;
}
- if (! yyres)
+ if (yyres)
+ return yystpcpy (yyres, yystr) - yyres;
+ else
return yystrlen (yystr);
-
- return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
-# endif
+#endif
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
+yy_syntax_error_arguments (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULLPTR;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
+ /* Actual size of YYARG. */
int yycount = 0;
-
/* There are many possibilities here to consider:
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
@@ -1925,49 +2080,54 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
one exception: it will still contain any token that will not be
accepted due to an error action in a later state.
*/
- if (yytoken != YYEMPTY)
- {
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- {
- YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
- }
- }
- }
+ if (yyctx->yytoken != YYSYMBOL_YYEMPTY)
+ {
+ int yyn;
+ if (yyarg)
+ yyarg[yycount] = yyctx->yytoken;
+ ++yycount;
+ yyn = yypcontext_expected_tokens (yyctx,
+ yyarg ? yyarg + 1 : yyarg, yyargn - 1);
+ if (yyn == YYENOMEM)
+ return YYENOMEM;
+ else
+ yycount += yyn;
}
+ return yycount;
+}
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
+ const yypcontext_t *yyctx)
+{
+ enum { YYARGS_MAX = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat: reported tokens (one for the "unexpected",
+ one per "expected"). */
+ yysymbol_kind_t yyarg[YYARGS_MAX];
+ /* Cumulated lengths of YYARG. */
+ YYPTRDIFF_T yysize = 0;
+
+ /* Actual size of YYARG. */
+ int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX);
+ if (yycount == YYENOMEM)
+ return YYENOMEM;
switch (yycount)
{
-# define YYCASE_(N, S) \
+#define YYCASE_(N, S) \
case N: \
yyformat = S; \
- break
+ break
default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
@@ -1975,15 +2135,23 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
+#undef YYCASE_
}
+ /* Compute error message size. Don't count the "%s"s, but reserve
+ room for the terminator. */
+ yysize = yystrlen (yyformat) - 2 * yycount + 1;
{
- YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
+ int yyi;
+ for (yyi = 0; yyi < yycount; ++yyi)
+ {
+ YYPTRDIFF_T yysize1
+ = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]);
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
+ return YYENOMEM;
+ }
}
if (*yymsg_alloc < yysize)
@@ -1992,7 +2160,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
if (! (yysize <= *yymsg_alloc
&& *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
*yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
+ return -1;
}
/* Avoid sprintf, as that infringes on the user's name space.
@@ -2004,40 +2172,43 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
while ((*yyp = *yyformat) != '\0')
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
- yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);
yyformat += 2;
}
else
{
- yyp++;
- yyformat++;
+ ++yyp;
+ ++yyformat;
}
}
return 0;
}
-#endif /* YYERROR_VERBOSE */
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+yydestruct (const char *yymsg,
+ yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
YYUSE (yyvaluep);
YYUSE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
+
+
/*----------.
| yyparse. |
`----------*/
@@ -2045,7 +2216,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner
int
yyparse (yyscan_t yyscanner)
{
-/* The lookahead symbol. */
+/* Lookahead token kind. */
int yychar;
@@ -2056,45 +2227,41 @@ YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
/* Number of syntax errors so far. */
- int yynerrs;
+ int yynerrs = 0;
- int yystate;
+ yy_state_fast_t yystate = 0;
/* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
-
- /* The stacks and their tools:
- 'yyss': related to states.
- 'yyvs': related to semantic values.
+ int yyerrstatus = 0;
- Refer to the stacks through separate pointers, to allow yyoverflow
+ /* Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss;
- yytype_int16 *yyssp;
+ /* Their size. */
+ YYPTRDIFF_T yystacksize = YYINITDEPTH;
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs;
- YYSTYPE *yyvsp;
+ /* The state stack: array, bottom, top. */
+ yy_state_t yyssa[YYINITDEPTH];
+ yy_state_t *yyss = yyssa;
+ yy_state_t *yyssp = yyss;
- YYSIZE_T yystacksize;
+ /* The semantic value stack: array, bottom, top. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp = yyvs;
int yyn;
+ /* The return value of yyparse. */
int yyresult;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
+ /* Lookahead symbol kind. */
+ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
-#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
+ YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
@@ -2102,15 +2269,8 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;
- yystacksize = YYINITDEPTH;
-
YYDPRINTF ((stderr, "Starting parse\n"));
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
@@ -2125,12 +2285,15 @@ yynewstate:
/*--------------------------------------------------------------------.
-| yynewstate -- set current state (the top of the stack) to yystate. |
+| yysetstate -- set current state (the top of the stack) to yystate. |
`--------------------------------------------------------------------*/
yysetstate:
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
- *yyssp = (yytype_int16) yystate;
+ YY_IGNORE_USELESS_CAST_BEGIN
+ *yyssp = YY_CAST (yy_state_t, yystate);
+ YY_IGNORE_USELESS_CAST_END
+ YY_STACK_PRINT (yyss, yyssp);
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
@@ -2138,23 +2301,23 @@ yysetstate:
#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
+ YYPTRDIFF_T yysize = yyssp - yyss + 1;
# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
+ yy_state_t *yyss1 = yyss;
YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
+ &yyss1, yysize * YYSIZEOF (*yyssp),
+ &yyvs1, yysize * YYSIZEOF (*yyvsp),
&yystacksize);
yyss = yyss1;
yyvs = yyvs1;
@@ -2168,14 +2331,15 @@ yysetstate:
yystacksize = YYMAXDEPTH;
{
- yytype_int16 *yyss1 = yyss;
+ yy_state_t *yyss1 = yyss;
union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ YY_CAST (union yyalloc *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
@@ -2184,8 +2348,10 @@ yysetstate:
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long) yystacksize));
+ YY_IGNORE_USELESS_CAST_BEGIN
+ YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+ YY_CAST (long, yystacksize)));
+ YY_IGNORE_USELESS_CAST_END
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
@@ -2212,18 +2378,29 @@ yybackup:
/* Not known => get a lookahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
if (yychar == YYEMPTY)
{
- YYDPRINTF ((stderr, "Reading a token: "));
+ YYDPRINTF ((stderr, "Reading a token\n"));
yychar = yylex (&yylval, yyscanner);
}
if (yychar <= YYEOF)
{
- yychar = yytoken = YYEOF;
+ yychar = YYEOF;
+ yytoken = YYSYMBOL_YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n"));
}
+ else if (yychar == YYerror)
+ {
+ /* The scanner already issued an error message, process directly
+ to error recovery. But do not keep the error token as
+ lookahead, it is too special and may lead us to an endless
+ loop in error recovery. */
+ yychar = YYUNDEF;
+ yytoken = YYSYMBOL_YYerror;
+ goto yyerrlab1;
+ }
else
{
yytoken = YYTRANSLATE (yychar);
@@ -2251,14 +2428,13 @@ yybackup:
/* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token. */
- yychar = YYEMPTY;
-
yystate = yyn;
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
goto yynewstate;
@@ -2293,330 +2469,330 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 2:
-#line 183 "cmDependsJavaParser.y"
- {
+ case 2: /* Goal: CompilationUnit */
+#line 181 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2305 "cmDependsJavaParser.cxx"
+#line 2481 "cmDependsJavaParser.cxx"
break;
- case 3:
-#line 192 "cmDependsJavaParser.y"
- {
+ case 3: /* Literal: IntegerLiteral */
+#line 190 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2316 "cmDependsJavaParser.cxx"
+#line 2492 "cmDependsJavaParser.cxx"
break;
- case 4:
-#line 200 "cmDependsJavaParser.y"
- {
+ case 4: /* Literal: jp_FLOATINGPOINTLITERAL */
+#line 198 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2327 "cmDependsJavaParser.cxx"
+#line 2503 "cmDependsJavaParser.cxx"
break;
- case 5:
-#line 208 "cmDependsJavaParser.y"
- {
+ case 5: /* Literal: jp_BOOLEANLITERAL */
+#line 206 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2338 "cmDependsJavaParser.cxx"
+#line 2514 "cmDependsJavaParser.cxx"
break;
- case 6:
-#line 216 "cmDependsJavaParser.y"
- {
+ case 6: /* Literal: jp_CHARACTERLITERAL */
+#line 214 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2349 "cmDependsJavaParser.cxx"
+#line 2525 "cmDependsJavaParser.cxx"
break;
- case 7:
-#line 224 "cmDependsJavaParser.y"
- {
+ case 7: /* Literal: jp_STRINGLITERAL */
+#line 222 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2360 "cmDependsJavaParser.cxx"
+#line 2536 "cmDependsJavaParser.cxx"
break;
- case 8:
-#line 232 "cmDependsJavaParser.y"
- {
+ case 8: /* Literal: jp_NULLLITERAL */
+#line 230 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2371 "cmDependsJavaParser.cxx"
+#line 2547 "cmDependsJavaParser.cxx"
break;
- case 9:
-#line 241 "cmDependsJavaParser.y"
- {
+ case 9: /* IntegerLiteral: jp_DECIMALINTEGERLITERAL */
+#line 239 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2382 "cmDependsJavaParser.cxx"
+#line 2558 "cmDependsJavaParser.cxx"
break;
- case 10:
-#line 249 "cmDependsJavaParser.y"
- {
+ case 10: /* IntegerLiteral: jp_HEXINTEGERLITERAL */
+#line 247 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2393 "cmDependsJavaParser.cxx"
+#line 2569 "cmDependsJavaParser.cxx"
break;
- case 11:
-#line 258 "cmDependsJavaParser.y"
- {
+ case 11: /* Type: PrimitiveType */
+#line 256 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2404 "cmDependsJavaParser.cxx"
+#line 2580 "cmDependsJavaParser.cxx"
break;
- case 12:
-#line 266 "cmDependsJavaParser.y"
- {
+ case 12: /* Type: ReferenceType */
+#line 264 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2415 "cmDependsJavaParser.cxx"
+#line 2591 "cmDependsJavaParser.cxx"
break;
- case 13:
-#line 275 "cmDependsJavaParser.y"
- {
+ case 13: /* PrimitiveType: jp_BYTE_TYPE */
+#line 273 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2423 "cmDependsJavaParser.cxx"
+#line 2599 "cmDependsJavaParser.cxx"
break;
- case 14:
-#line 280 "cmDependsJavaParser.y"
- {
+ case 14: /* PrimitiveType: jp_SHORT_TYPE */
+#line 278 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2431 "cmDependsJavaParser.cxx"
+#line 2607 "cmDependsJavaParser.cxx"
break;
- case 15:
-#line 285 "cmDependsJavaParser.y"
- {
+ case 15: /* PrimitiveType: jp_INT_TYPE */
+#line 283 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2439 "cmDependsJavaParser.cxx"
+#line 2615 "cmDependsJavaParser.cxx"
break;
- case 16:
-#line 290 "cmDependsJavaParser.y"
- {
+ case 16: /* PrimitiveType: jp_LONG_TYPE */
+#line 288 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2447 "cmDependsJavaParser.cxx"
+#line 2623 "cmDependsJavaParser.cxx"
break;
- case 17:
-#line 295 "cmDependsJavaParser.y"
- {
+ case 17: /* PrimitiveType: jp_CHAR_TYPE */
+#line 293 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2455 "cmDependsJavaParser.cxx"
+#line 2631 "cmDependsJavaParser.cxx"
break;
- case 18:
-#line 300 "cmDependsJavaParser.y"
- {
+ case 18: /* PrimitiveType: jp_FLOAT_TYPE */
+#line 298 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2463 "cmDependsJavaParser.cxx"
+#line 2639 "cmDependsJavaParser.cxx"
break;
- case 19:
-#line 305 "cmDependsJavaParser.y"
- {
+ case 19: /* PrimitiveType: jp_DOUBLE_TYPE */
+#line 303 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2471 "cmDependsJavaParser.cxx"
+#line 2647 "cmDependsJavaParser.cxx"
break;
- case 20:
-#line 310 "cmDependsJavaParser.y"
- {
+ case 20: /* PrimitiveType: jp_BOOLEAN_TYPE */
+#line 308 "cmDependsJavaParser.y"
+{
jpElementStart(0);
}
-#line 2479 "cmDependsJavaParser.cxx"
+#line 2655 "cmDependsJavaParser.cxx"
break;
- case 21:
-#line 316 "cmDependsJavaParser.y"
- {
+ case 21: /* ReferenceType: ClassOrInterfaceType */
+#line 314 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2490 "cmDependsJavaParser.cxx"
+#line 2666 "cmDependsJavaParser.cxx"
break;
- case 22:
-#line 324 "cmDependsJavaParser.y"
- {
+ case 22: /* ReferenceType: ArrayType */
+#line 322 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2501 "cmDependsJavaParser.cxx"
+#line 2677 "cmDependsJavaParser.cxx"
break;
- case 23:
-#line 333 "cmDependsJavaParser.y"
- {
+ case 23: /* ClassOrInterfaceType: Name */
+#line 331 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpStoreClass((yyvsp[0].str));
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2513 "cmDependsJavaParser.cxx"
+#line 2689 "cmDependsJavaParser.cxx"
break;
- case 24:
-#line 343 "cmDependsJavaParser.y"
- {
+ case 24: /* ClassType: ClassOrInterfaceType */
+#line 341 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2524 "cmDependsJavaParser.cxx"
+#line 2700 "cmDependsJavaParser.cxx"
break;
- case 25:
-#line 352 "cmDependsJavaParser.y"
- {
+ case 25: /* InterfaceType: ClassOrInterfaceType */
+#line 350 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2535 "cmDependsJavaParser.cxx"
+#line 2711 "cmDependsJavaParser.cxx"
break;
- case 26:
-#line 361 "cmDependsJavaParser.y"
- {
+ case 26: /* ArrayType: PrimitiveType Dims */
+#line 359 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2546 "cmDependsJavaParser.cxx"
+#line 2722 "cmDependsJavaParser.cxx"
break;
- case 27:
-#line 369 "cmDependsJavaParser.y"
- {
+ case 27: /* ArrayType: Name Dims */
+#line 367 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpStoreClass((yyvsp[-1].str));
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2558 "cmDependsJavaParser.cxx"
+#line 2734 "cmDependsJavaParser.cxx"
break;
- case 28:
-#line 379 "cmDependsJavaParser.y"
- {
+ case 28: /* Name: SimpleName */
+#line 377 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2567 "cmDependsJavaParser.cxx"
+#line 2743 "cmDependsJavaParser.cxx"
break;
- case 29:
-#line 385 "cmDependsJavaParser.y"
- {
+ case 29: /* Name: QualifiedName */
+#line 383 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2576 "cmDependsJavaParser.cxx"
+#line 2752 "cmDependsJavaParser.cxx"
break;
- case 30:
-#line 392 "cmDependsJavaParser.y"
- {
+ case 30: /* SimpleName: Identifier */
+#line 390 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2585 "cmDependsJavaParser.cxx"
+#line 2761 "cmDependsJavaParser.cxx"
break;
- case 31:
-#line 399 "cmDependsJavaParser.y"
- {
+ case 31: /* Identifier: jp_NAME */
+#line 397 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2594 "cmDependsJavaParser.cxx"
+#line 2770 "cmDependsJavaParser.cxx"
break;
- case 32:
-#line 405 "cmDependsJavaParser.y"
- {
+ case 32: /* Identifier: jp_DOLLAR jp_NAME */
+#line 403 "cmDependsJavaParser.y"
+{
jpElementStart(2);
(yyval.str) = (yyvsp[0].str);
}
-#line 2603 "cmDependsJavaParser.cxx"
+#line 2779 "cmDependsJavaParser.cxx"
break;
- case 33:
-#line 412 "cmDependsJavaParser.y"
- {
+ case 33: /* QualifiedName: Name jp_DOT Identifier */
+#line 410 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->AddClassFound((yyvsp[-2].str));
yyGetParser->UpdateCombine((yyvsp[-2].str), (yyvsp[0].str));
yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
(yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine());
}
-#line 2615 "cmDependsJavaParser.cxx"
+#line 2791 "cmDependsJavaParser.cxx"
break;
- case 34:
-#line 421 "cmDependsJavaParser.y"
- {
+ case 34: /* QualifiedName: Name jp_DOT jp_CLASS */
+#line 419 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
jpCheckEmpty(3);
@@ -2624,12 +2800,12 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2628 "cmDependsJavaParser.cxx"
+#line 2804 "cmDependsJavaParser.cxx"
break;
- case 35:
-#line 431 "cmDependsJavaParser.y"
- {
+ case 35: /* QualifiedName: Name jp_DOT jp_THIS */
+#line 429 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
yyGetParser->SetCurrentCombine("");
@@ -2637,119 +2813,119 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2641 "cmDependsJavaParser.cxx"
+#line 2817 "cmDependsJavaParser.cxx"
break;
- case 36:
-#line 441 "cmDependsJavaParser.y"
- {
+ case 36: /* QualifiedName: SimpleType jp_DOT jp_CLASS */
+#line 439 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2652 "cmDependsJavaParser.cxx"
+#line 2828 "cmDependsJavaParser.cxx"
break;
- case 37:
-#line 450 "cmDependsJavaParser.y"
- {
+ case 37: /* SimpleType: PrimitiveType */
+#line 448 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2663 "cmDependsJavaParser.cxx"
+#line 2839 "cmDependsJavaParser.cxx"
break;
- case 38:
-#line 458 "cmDependsJavaParser.y"
- {
+ case 38: /* SimpleType: jp_VOID */
+#line 456 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2674 "cmDependsJavaParser.cxx"
+#line 2850 "cmDependsJavaParser.cxx"
break;
- case 39:
-#line 467 "cmDependsJavaParser.y"
- {
+ case 39: /* CompilationUnit: PackageDeclarationopt ImportDeclarations TypeDeclarations */
+#line 465 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2685 "cmDependsJavaParser.cxx"
+#line 2861 "cmDependsJavaParser.cxx"
break;
- case 40:
-#line 475 "cmDependsJavaParser.y"
- {
+ case 40: /* PackageDeclarationopt: %empty */
+#line 473 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2695 "cmDependsJavaParser.cxx"
+#line 2871 "cmDependsJavaParser.cxx"
break;
- case 41:
-#line 482 "cmDependsJavaParser.y"
- {
+ case 41: /* PackageDeclarationopt: PackageDeclaration */
+#line 480 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2706 "cmDependsJavaParser.cxx"
+#line 2882 "cmDependsJavaParser.cxx"
break;
- case 42:
-#line 490 "cmDependsJavaParser.y"
- {
+ case 42: /* ImportDeclarations: %empty */
+#line 488 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2716 "cmDependsJavaParser.cxx"
+#line 2892 "cmDependsJavaParser.cxx"
break;
- case 43:
-#line 497 "cmDependsJavaParser.y"
- {
+ case 43: /* ImportDeclarations: ImportDeclarations ImportDeclaration */
+#line 495 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2727 "cmDependsJavaParser.cxx"
+#line 2903 "cmDependsJavaParser.cxx"
break;
- case 44:
-#line 505 "cmDependsJavaParser.y"
- {
+ case 44: /* TypeDeclarations: %empty */
+#line 503 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2737 "cmDependsJavaParser.cxx"
+#line 2913 "cmDependsJavaParser.cxx"
break;
- case 45:
-#line 512 "cmDependsJavaParser.y"
- {
+ case 45: /* TypeDeclarations: TypeDeclarations TypeDeclaration */
+#line 510 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2748 "cmDependsJavaParser.cxx"
+#line 2924 "cmDependsJavaParser.cxx"
break;
- case 46:
-#line 521 "cmDependsJavaParser.y"
- {
+ case 46: /* PackageDeclaration: jp_PACKAGE Name jp_SEMICOL */
+#line 519 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->SetCurrentPackage((yyvsp[-1].str));
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
@@ -2758,34 +2934,34 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2762 "cmDependsJavaParser.cxx"
+#line 2938 "cmDependsJavaParser.cxx"
break;
- case 47:
-#line 533 "cmDependsJavaParser.y"
- {
+ case 47: /* ImportDeclaration: SingleTypeImportDeclaration */
+#line 531 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2773 "cmDependsJavaParser.cxx"
+#line 2949 "cmDependsJavaParser.cxx"
break;
- case 48:
-#line 541 "cmDependsJavaParser.y"
- {
+ case 48: /* ImportDeclaration: TypeImportOnDemandDeclaration */
+#line 539 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2784 "cmDependsJavaParser.cxx"
+#line 2960 "cmDependsJavaParser.cxx"
break;
- case 49:
-#line 550 "cmDependsJavaParser.y"
- {
+ case 49: /* SingleTypeImportDeclaration: jp_IMPORT Name jp_SEMICOL */
+#line 548 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->AddPackagesImport((yyvsp[-1].str));
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
@@ -2794,12 +2970,12 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2798 "cmDependsJavaParser.cxx"
+#line 2974 "cmDependsJavaParser.cxx"
break;
- case 50:
-#line 562 "cmDependsJavaParser.y"
- {
+ case 50: /* TypeImportOnDemandDeclaration: jp_IMPORT Name jp_DOT jp_TIMES jp_SEMICOL */
+#line 560 "cmDependsJavaParser.y"
+{
jpElementStart(5);
std::string str = (yyvsp[-3].str);
str += ".*";
@@ -2809,466 +2985,466 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2813 "cmDependsJavaParser.cxx"
+#line 2989 "cmDependsJavaParser.cxx"
break;
- case 51:
-#line 575 "cmDependsJavaParser.y"
- {
+ case 51: /* TypeDeclaration: ClassDeclaration */
+#line 573 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2824 "cmDependsJavaParser.cxx"
+#line 3000 "cmDependsJavaParser.cxx"
break;
- case 52:
-#line 583 "cmDependsJavaParser.y"
- {
+ case 52: /* TypeDeclaration: InterfaceDeclaration */
+#line 581 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2835 "cmDependsJavaParser.cxx"
+#line 3011 "cmDependsJavaParser.cxx"
break;
- case 53:
-#line 591 "cmDependsJavaParser.y"
- {
+ case 53: /* TypeDeclaration: jp_SEMICOL */
+#line 589 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2846 "cmDependsJavaParser.cxx"
+#line 3022 "cmDependsJavaParser.cxx"
break;
- case 54:
-#line 600 "cmDependsJavaParser.y"
- {
+ case 54: /* Modifiers: Modifier */
+#line 598 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2857 "cmDependsJavaParser.cxx"
+#line 3033 "cmDependsJavaParser.cxx"
break;
- case 55:
-#line 608 "cmDependsJavaParser.y"
- {
+ case 55: /* Modifiers: Modifiers Modifier */
+#line 606 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2868 "cmDependsJavaParser.cxx"
+#line 3044 "cmDependsJavaParser.cxx"
break;
- case 67:
-#line 623 "cmDependsJavaParser.y"
- {
+ case 67: /* ClassHeader: Modifiersopt jp_CLASS Identifier */
+#line 621 "cmDependsJavaParser.y"
+{
yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 2879 "cmDependsJavaParser.cxx"
+#line 3055 "cmDependsJavaParser.cxx"
break;
- case 68:
-#line 633 "cmDependsJavaParser.y"
- {
+ case 68: /* ClassDeclaration: ClassHeader ClassBody */
+#line 631 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2891 "cmDependsJavaParser.cxx"
+#line 3067 "cmDependsJavaParser.cxx"
break;
- case 69:
-#line 642 "cmDependsJavaParser.y"
- {
+ case 69: /* ClassDeclaration: ClassHeader Interfaces ClassBody */
+#line 640 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2903 "cmDependsJavaParser.cxx"
+#line 3079 "cmDependsJavaParser.cxx"
break;
- case 70:
-#line 651 "cmDependsJavaParser.y"
- {
+ case 70: /* ClassDeclaration: ClassHeader Super ClassBody */
+#line 649 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2915 "cmDependsJavaParser.cxx"
+#line 3091 "cmDependsJavaParser.cxx"
break;
- case 71:
-#line 660 "cmDependsJavaParser.y"
- {
+ case 71: /* ClassDeclaration: ClassHeader Super Interfaces ClassBody */
+#line 658 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2927 "cmDependsJavaParser.cxx"
+#line 3103 "cmDependsJavaParser.cxx"
break;
- case 72:
-#line 669 "cmDependsJavaParser.y"
- {
+ case 72: /* Modifiersopt: %empty */
+#line 667 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2937 "cmDependsJavaParser.cxx"
+#line 3113 "cmDependsJavaParser.cxx"
break;
- case 73:
-#line 676 "cmDependsJavaParser.y"
- {
+ case 73: /* Modifiersopt: Modifiers */
+#line 674 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2948 "cmDependsJavaParser.cxx"
+#line 3124 "cmDependsJavaParser.cxx"
break;
- case 74:
-#line 685 "cmDependsJavaParser.y"
- {
+ case 74: /* Super: jp_EXTENDS ClassType */
+#line 683 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2959 "cmDependsJavaParser.cxx"
+#line 3135 "cmDependsJavaParser.cxx"
break;
- case 75:
-#line 694 "cmDependsJavaParser.y"
- {
+ case 75: /* Interfaces: jp_IMPLEMENTS InterfaceTypeList */
+#line 692 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2970 "cmDependsJavaParser.cxx"
+#line 3146 "cmDependsJavaParser.cxx"
break;
- case 76:
-#line 703 "cmDependsJavaParser.y"
- {
+ case 76: /* InterfaceTypeList: InterfaceType */
+#line 701 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2981 "cmDependsJavaParser.cxx"
+#line 3157 "cmDependsJavaParser.cxx"
break;
- case 77:
-#line 711 "cmDependsJavaParser.y"
- {
+ case 77: /* InterfaceTypeList: InterfaceTypeList jp_COMMA InterfaceType */
+#line 709 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2992 "cmDependsJavaParser.cxx"
+#line 3168 "cmDependsJavaParser.cxx"
break;
- case 78:
-#line 720 "cmDependsJavaParser.y"
- {
+ case 78: /* ClassBody: jp_CURLYSTART ClassBodyDeclarations jp_CURLYEND */
+#line 718 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3003 "cmDependsJavaParser.cxx"
+#line 3179 "cmDependsJavaParser.cxx"
break;
- case 79:
-#line 728 "cmDependsJavaParser.y"
- {
+ case 79: /* ClassBodyDeclarations: %empty */
+#line 726 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3013 "cmDependsJavaParser.cxx"
+#line 3189 "cmDependsJavaParser.cxx"
break;
- case 80:
-#line 735 "cmDependsJavaParser.y"
- {
+ case 80: /* ClassBodyDeclarations: ClassBodyDeclarations ClassBodyDeclaration */
+#line 733 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3024 "cmDependsJavaParser.cxx"
+#line 3200 "cmDependsJavaParser.cxx"
break;
- case 81:
-#line 744 "cmDependsJavaParser.y"
- {
+ case 81: /* ClassBodyDeclaration: ClassMemberDeclaration */
+#line 742 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3035 "cmDependsJavaParser.cxx"
+#line 3211 "cmDependsJavaParser.cxx"
break;
- case 82:
-#line 752 "cmDependsJavaParser.y"
- {
+ case 82: /* ClassBodyDeclaration: StaticInitializer */
+#line 750 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3046 "cmDependsJavaParser.cxx"
+#line 3222 "cmDependsJavaParser.cxx"
break;
- case 83:
-#line 760 "cmDependsJavaParser.y"
- {
+ case 83: /* ClassBodyDeclaration: ConstructorDeclaration */
+#line 758 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3057 "cmDependsJavaParser.cxx"
+#line 3233 "cmDependsJavaParser.cxx"
break;
- case 84:
-#line 768 "cmDependsJavaParser.y"
- {
+ case 84: /* ClassBodyDeclaration: TypeDeclaration */
+#line 766 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3068 "cmDependsJavaParser.cxx"
+#line 3244 "cmDependsJavaParser.cxx"
break;
- case 85:
-#line 777 "cmDependsJavaParser.y"
- {
+ case 85: /* ClassMemberDeclaration: FieldDeclaration */
+#line 775 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3079 "cmDependsJavaParser.cxx"
+#line 3255 "cmDependsJavaParser.cxx"
break;
- case 86:
-#line 785 "cmDependsJavaParser.y"
- {
+ case 86: /* ClassMemberDeclaration: MethodDeclaration */
+#line 783 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3090 "cmDependsJavaParser.cxx"
+#line 3266 "cmDependsJavaParser.cxx"
break;
- case 87:
-#line 794 "cmDependsJavaParser.y"
- {
+ case 87: /* FieldDeclaration: Modifiersopt Type VariableDeclarators jp_SEMICOL */
+#line 792 "cmDependsJavaParser.y"
+{
jpElementStart(4);
}
-#line 3098 "cmDependsJavaParser.cxx"
+#line 3274 "cmDependsJavaParser.cxx"
break;
- case 88:
-#line 800 "cmDependsJavaParser.y"
- {
+ case 88: /* VariableDeclarators: VariableDeclarator */
+#line 798 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3109 "cmDependsJavaParser.cxx"
+#line 3285 "cmDependsJavaParser.cxx"
break;
- case 89:
-#line 808 "cmDependsJavaParser.y"
- {
+ case 89: /* VariableDeclarators: VariableDeclarators jp_COMMA VariableDeclarator */
+#line 806 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3120 "cmDependsJavaParser.cxx"
+#line 3296 "cmDependsJavaParser.cxx"
break;
- case 90:
-#line 817 "cmDependsJavaParser.y"
- {
+ case 90: /* VariableDeclarator: VariableDeclaratorId */
+#line 815 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3131 "cmDependsJavaParser.cxx"
+#line 3307 "cmDependsJavaParser.cxx"
break;
- case 91:
-#line 825 "cmDependsJavaParser.y"
- {
+ case 91: /* VariableDeclarator: VariableDeclaratorId jp_EQUALS VariableInitializer */
+#line 823 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3142 "cmDependsJavaParser.cxx"
+#line 3318 "cmDependsJavaParser.cxx"
break;
- case 92:
-#line 834 "cmDependsJavaParser.y"
- {
+ case 92: /* VariableDeclaratorId: Identifier */
+#line 832 "cmDependsJavaParser.y"
+{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3154 "cmDependsJavaParser.cxx"
+#line 3330 "cmDependsJavaParser.cxx"
break;
- case 93:
-#line 843 "cmDependsJavaParser.y"
- {
+ case 93: /* VariableDeclaratorId: VariableDeclaratorId jp_BRACKETSTART jp_BRACKETEND */
+#line 841 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3165 "cmDependsJavaParser.cxx"
+#line 3341 "cmDependsJavaParser.cxx"
break;
- case 94:
-#line 852 "cmDependsJavaParser.y"
- {
+ case 94: /* VariableInitializer: Expression */
+#line 850 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3176 "cmDependsJavaParser.cxx"
+#line 3352 "cmDependsJavaParser.cxx"
break;
- case 95:
-#line 860 "cmDependsJavaParser.y"
- {
+ case 95: /* VariableInitializer: ArrayInitializer */
+#line 858 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3187 "cmDependsJavaParser.cxx"
+#line 3363 "cmDependsJavaParser.cxx"
break;
- case 96:
-#line 869 "cmDependsJavaParser.y"
- {
+ case 96: /* MethodDeclaration: MethodHeader jp_SEMICOL */
+#line 867 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3198 "cmDependsJavaParser.cxx"
+#line 3374 "cmDependsJavaParser.cxx"
break;
- case 97:
-#line 877 "cmDependsJavaParser.y"
- {
+ case 97: /* MethodDeclaration: MethodHeader MethodBody */
+#line 875 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3209 "cmDependsJavaParser.cxx"
+#line 3385 "cmDependsJavaParser.cxx"
break;
- case 98:
-#line 885 "cmDependsJavaParser.y"
- {
+ case 98: /* MethodDeclaration: MethodHeader MethodBody jp_SEMICOL */
+#line 883 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3220 "cmDependsJavaParser.cxx"
+#line 3396 "cmDependsJavaParser.cxx"
break;
- case 99:
-#line 894 "cmDependsJavaParser.y"
- {
+ case 99: /* MethodHeader: Modifiersopt Type MethodDeclarator Throwsopt */
+#line 892 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3232 "cmDependsJavaParser.cxx"
+#line 3408 "cmDependsJavaParser.cxx"
break;
- case 100:
-#line 903 "cmDependsJavaParser.y"
- {
+ case 100: /* MethodHeader: Modifiersopt jp_VOID MethodDeclarator Throwsopt */
+#line 901 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3244 "cmDependsJavaParser.cxx"
+#line 3420 "cmDependsJavaParser.cxx"
break;
- case 101:
-#line 912 "cmDependsJavaParser.y"
- {
+ case 101: /* Throwsopt: %empty */
+#line 910 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3255 "cmDependsJavaParser.cxx"
+#line 3431 "cmDependsJavaParser.cxx"
break;
- case 102:
-#line 920 "cmDependsJavaParser.y"
- {
+ case 102: /* Throwsopt: Throws */
+#line 918 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3267 "cmDependsJavaParser.cxx"
+#line 3443 "cmDependsJavaParser.cxx"
break;
- case 103:
-#line 930 "cmDependsJavaParser.y"
- {
+ case 103: /* MethodDeclarator: Identifier jp_PARESTART FormalParameterListopt jp_PAREEND */
+#line 928 "cmDependsJavaParser.y"
+{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
@@ -3276,146 +3452,146 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3280 "cmDependsJavaParser.cxx"
+#line 3456 "cmDependsJavaParser.cxx"
break;
- case 104:
-#line 940 "cmDependsJavaParser.y"
- {
+ case 104: /* MethodDeclarator: MethodDeclarator jp_BRACKETSTART jp_BRACKETEND */
+#line 938 "cmDependsJavaParser.y"
+{
jpElementStart(3);
}
-#line 3289 "cmDependsJavaParser.cxx"
+#line 3465 "cmDependsJavaParser.cxx"
break;
- case 105:
-#line 946 "cmDependsJavaParser.y"
- {
+ case 105: /* FormalParameterListopt: %empty */
+#line 944 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3300 "cmDependsJavaParser.cxx"
+#line 3476 "cmDependsJavaParser.cxx"
break;
- case 107:
-#line 957 "cmDependsJavaParser.y"
- {
+ case 107: /* FormalParameterList: FormalParameter */
+#line 955 "cmDependsJavaParser.y"
+{
jpElementStart(1);
}
-#line 3309 "cmDependsJavaParser.cxx"
+#line 3485 "cmDependsJavaParser.cxx"
break;
- case 108:
-#line 963 "cmDependsJavaParser.y"
- {
+ case 108: /* FormalParameterList: FormalParameterList jp_COMMA FormalParameter */
+#line 961 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3321 "cmDependsJavaParser.cxx"
+#line 3497 "cmDependsJavaParser.cxx"
break;
- case 109:
-#line 973 "cmDependsJavaParser.y"
- {
+ case 109: /* FormalParameter: Modifiersopt Type VariableDeclaratorId */
+#line 971 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3333 "cmDependsJavaParser.cxx"
+#line 3509 "cmDependsJavaParser.cxx"
break;
- case 110:
-#line 983 "cmDependsJavaParser.y"
- {
+ case 110: /* Throws: jp_THROWS ClassTypeList */
+#line 981 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3345 "cmDependsJavaParser.cxx"
+#line 3521 "cmDependsJavaParser.cxx"
break;
- case 111:
-#line 993 "cmDependsJavaParser.y"
- {
+ case 111: /* ClassTypeList: ClassType */
+#line 991 "cmDependsJavaParser.y"
+{
jpElementStart(1);
}
-#line 3354 "cmDependsJavaParser.cxx"
+#line 3530 "cmDependsJavaParser.cxx"
break;
- case 112:
-#line 999 "cmDependsJavaParser.y"
- {
+ case 112: /* ClassTypeList: ClassTypeList jp_COMMA ClassType */
+#line 997 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3366 "cmDependsJavaParser.cxx"
+#line 3542 "cmDependsJavaParser.cxx"
break;
- case 113:
-#line 1009 "cmDependsJavaParser.y"
- {
+ case 113: /* MethodBody: Block */
+#line 1007 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3378 "cmDependsJavaParser.cxx"
+#line 3554 "cmDependsJavaParser.cxx"
break;
- case 114:
-#line 1019 "cmDependsJavaParser.y"
- {
+ case 114: /* StaticInitializer: jp_STATIC Block */
+#line 1017 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3390 "cmDependsJavaParser.cxx"
+#line 3566 "cmDependsJavaParser.cxx"
break;
- case 115:
-#line 1029 "cmDependsJavaParser.y"
- {
+ case 115: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody */
+#line 1027 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3402 "cmDependsJavaParser.cxx"
+#line 3578 "cmDependsJavaParser.cxx"
break;
- case 116:
-#line 1038 "cmDependsJavaParser.y"
- {
+ case 116: /* ConstructorDeclaration: Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody jp_SEMICOL */
+#line 1036 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3414 "cmDependsJavaParser.cxx"
+#line 3590 "cmDependsJavaParser.cxx"
break;
- case 117:
-#line 1048 "cmDependsJavaParser.y"
- {
+ case 117: /* ConstructorDeclarator: SimpleName jp_PARESTART FormalParameterListopt jp_PAREEND */
+#line 1046 "cmDependsJavaParser.y"
+{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
@@ -3423,781 +3599,781 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3427 "cmDependsJavaParser.cxx"
+#line 3603 "cmDependsJavaParser.cxx"
break;
- case 118:
-#line 1059 "cmDependsJavaParser.y"
- {
+ case 118: /* ConstructorBody: jp_CURLYSTART ExplicitConstructorInvocationopt BlockStatementsopt jp_CURLYEND */
+#line 1057 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3439 "cmDependsJavaParser.cxx"
+#line 3615 "cmDependsJavaParser.cxx"
break;
- case 119:
-#line 1068 "cmDependsJavaParser.y"
- {
+ case 119: /* ExplicitConstructorInvocationopt: %empty */
+#line 1066 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3450 "cmDependsJavaParser.cxx"
+#line 3626 "cmDependsJavaParser.cxx"
break;
- case 120:
-#line 1076 "cmDependsJavaParser.y"
- {
+ case 120: /* ExplicitConstructorInvocationopt: ExplicitConstructorInvocationopt ExplicitConstructorInvocation */
+#line 1074 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3462 "cmDependsJavaParser.cxx"
+#line 3638 "cmDependsJavaParser.cxx"
break;
- case 121:
-#line 1086 "cmDependsJavaParser.y"
- {
+ case 121: /* ExplicitConstructorInvocation: jp_THIS jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */
+#line 1084 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3474 "cmDependsJavaParser.cxx"
+#line 3650 "cmDependsJavaParser.cxx"
break;
- case 122:
-#line 1095 "cmDependsJavaParser.y"
- {
+ case 122: /* ExplicitConstructorInvocation: jp_SUPER jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL */
+#line 1093 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3486 "cmDependsJavaParser.cxx"
+#line 3662 "cmDependsJavaParser.cxx"
break;
- case 123:
-#line 1105 "cmDependsJavaParser.y"
- {
+ case 123: /* InterfaceHeader: Modifiersopt jp_INTERFACE Identifier */
+#line 1103 "cmDependsJavaParser.y"
+{
yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 3497 "cmDependsJavaParser.cxx"
+#line 3673 "cmDependsJavaParser.cxx"
break;
- case 124:
-#line 1114 "cmDependsJavaParser.y"
- {
+ case 124: /* InterfaceDeclaration: InterfaceHeader ExtendsInterfacesopt InterfaceBody */
+#line 1112 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3509 "cmDependsJavaParser.cxx"
+#line 3685 "cmDependsJavaParser.cxx"
break;
- case 125:
-#line 1123 "cmDependsJavaParser.y"
- {
+ case 125: /* ExtendsInterfacesopt: %empty */
+#line 1121 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3519 "cmDependsJavaParser.cxx"
+#line 3695 "cmDependsJavaParser.cxx"
break;
- case 126:
-#line 1130 "cmDependsJavaParser.y"
- {
+ case 126: /* ExtendsInterfacesopt: ExtendsInterfaces */
+#line 1128 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3531 "cmDependsJavaParser.cxx"
+#line 3707 "cmDependsJavaParser.cxx"
break;
- case 127:
-#line 1140 "cmDependsJavaParser.y"
- {
+ case 127: /* ExtendsInterfaces: jp_EXTENDS InterfaceType */
+#line 1138 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3543 "cmDependsJavaParser.cxx"
+#line 3719 "cmDependsJavaParser.cxx"
break;
- case 128:
-#line 1149 "cmDependsJavaParser.y"
- {
+ case 128: /* ExtendsInterfaces: ExtendsInterfaces jp_COMMA InterfaceType */
+#line 1147 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3555 "cmDependsJavaParser.cxx"
+#line 3731 "cmDependsJavaParser.cxx"
break;
- case 129:
-#line 1159 "cmDependsJavaParser.y"
- {
+ case 129: /* InterfaceBody: jp_CURLYSTART InterfaceMemberDeclarations jp_CURLYEND */
+#line 1157 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3567 "cmDependsJavaParser.cxx"
+#line 3743 "cmDependsJavaParser.cxx"
break;
- case 130:
-#line 1168 "cmDependsJavaParser.y"
- {
+ case 130: /* InterfaceMemberDeclarations: %empty */
+#line 1166 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3578 "cmDependsJavaParser.cxx"
+#line 3754 "cmDependsJavaParser.cxx"
break;
- case 131:
-#line 1176 "cmDependsJavaParser.y"
- {
+ case 131: /* InterfaceMemberDeclarations: InterfaceMemberDeclarations InterfaceMemberDeclaration */
+#line 1174 "cmDependsJavaParser.y"
+{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3589 "cmDependsJavaParser.cxx"
+#line 3765 "cmDependsJavaParser.cxx"
break;
- case 132:
-#line 1185 "cmDependsJavaParser.y"
- {
+ case 132: /* InterfaceMemberDeclaration: ConstantDeclaration */
+#line 1183 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3601 "cmDependsJavaParser.cxx"
+#line 3777 "cmDependsJavaParser.cxx"
break;
- case 133:
-#line 1194 "cmDependsJavaParser.y"
- {
+ case 133: /* InterfaceMemberDeclaration: AbstractMethodDeclaration */
+#line 1192 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3613 "cmDependsJavaParser.cxx"
+#line 3789 "cmDependsJavaParser.cxx"
break;
- case 134:
-#line 1203 "cmDependsJavaParser.y"
- {
+ case 134: /* InterfaceMemberDeclaration: ClassDeclaration */
+#line 1201 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3625 "cmDependsJavaParser.cxx"
+#line 3801 "cmDependsJavaParser.cxx"
break;
- case 135:
-#line 1212 "cmDependsJavaParser.y"
- {
+ case 135: /* InterfaceMemberDeclaration: ClassDeclaration jp_SEMICOL */
+#line 1210 "cmDependsJavaParser.y"
+{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3636 "cmDependsJavaParser.cxx"
+#line 3812 "cmDependsJavaParser.cxx"
break;
- case 136:
-#line 1220 "cmDependsJavaParser.y"
- {
+ case 136: /* InterfaceMemberDeclaration: InterfaceDeclaration */
+#line 1218 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3648 "cmDependsJavaParser.cxx"
+#line 3824 "cmDependsJavaParser.cxx"
break;
- case 137:
-#line 1229 "cmDependsJavaParser.y"
- {
+ case 137: /* InterfaceMemberDeclaration: InterfaceDeclaration jp_SEMICOL */
+#line 1227 "cmDependsJavaParser.y"
+{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3659 "cmDependsJavaParser.cxx"
+#line 3835 "cmDependsJavaParser.cxx"
break;
- case 138:
-#line 1238 "cmDependsJavaParser.y"
- {
+ case 138: /* ConstantDeclaration: FieldDeclaration */
+#line 1236 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3671 "cmDependsJavaParser.cxx"
+#line 3847 "cmDependsJavaParser.cxx"
break;
- case 139:
-#line 1248 "cmDependsJavaParser.y"
- {
+ case 139: /* AbstractMethodDeclaration: MethodHeader Semicols */
+#line 1246 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3683 "cmDependsJavaParser.cxx"
+#line 3859 "cmDependsJavaParser.cxx"
break;
- case 140:
-#line 1258 "cmDependsJavaParser.y"
- {
+ case 140: /* Semicols: jp_SEMICOL */
+#line 1256 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3695 "cmDependsJavaParser.cxx"
+#line 3871 "cmDependsJavaParser.cxx"
break;
- case 141:
-#line 1267 "cmDependsJavaParser.y"
- {
+ case 141: /* Semicols: Semicols jp_SEMICOL */
+#line 1265 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3707 "cmDependsJavaParser.cxx"
+#line 3883 "cmDependsJavaParser.cxx"
break;
- case 142:
-#line 1277 "cmDependsJavaParser.y"
- {
+ case 142: /* ArrayInitializer: jp_CURLYSTART VariableInitializersOptional jp_CURLYEND */
+#line 1275 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3719 "cmDependsJavaParser.cxx"
+#line 3895 "cmDependsJavaParser.cxx"
break;
- case 143:
-#line 1286 "cmDependsJavaParser.y"
- {
+ case 143: /* VariableInitializersOptional: %empty */
+#line 1284 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3730 "cmDependsJavaParser.cxx"
+#line 3906 "cmDependsJavaParser.cxx"
break;
- case 144:
-#line 1294 "cmDependsJavaParser.y"
- {
+ case 144: /* VariableInitializersOptional: VariableInitializers */
+#line 1292 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3742 "cmDependsJavaParser.cxx"
+#line 3918 "cmDependsJavaParser.cxx"
break;
- case 145:
-#line 1303 "cmDependsJavaParser.y"
- {
+ case 145: /* VariableInitializersOptional: VariableInitializers jp_COMMA */
+#line 1301 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3754 "cmDependsJavaParser.cxx"
+#line 3930 "cmDependsJavaParser.cxx"
break;
- case 146:
-#line 1313 "cmDependsJavaParser.y"
- {
+ case 146: /* VariableInitializers: VariableInitializer */
+#line 1311 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3766 "cmDependsJavaParser.cxx"
+#line 3942 "cmDependsJavaParser.cxx"
break;
- case 147:
-#line 1322 "cmDependsJavaParser.y"
- {
+ case 147: /* VariableInitializers: VariableInitializers jp_COMMA VariableInitializer */
+#line 1320 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3778 "cmDependsJavaParser.cxx"
+#line 3954 "cmDependsJavaParser.cxx"
break;
- case 148:
-#line 1332 "cmDependsJavaParser.y"
- {
+ case 148: /* Block: jp_CURLYSTART BlockStatementsopt jp_CURLYEND */
+#line 1330 "cmDependsJavaParser.y"
+{
jpElementStart(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3789 "cmDependsJavaParser.cxx"
+#line 3965 "cmDependsJavaParser.cxx"
break;
- case 149:
-#line 1340 "cmDependsJavaParser.y"
- {
+ case 149: /* BlockStatementsopt: %empty */
+#line 1338 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3800 "cmDependsJavaParser.cxx"
+#line 3976 "cmDependsJavaParser.cxx"
break;
- case 150:
-#line 1348 "cmDependsJavaParser.y"
- {
+ case 150: /* BlockStatementsopt: BlockStatements */
+#line 1346 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3812 "cmDependsJavaParser.cxx"
+#line 3988 "cmDependsJavaParser.cxx"
break;
- case 151:
-#line 1358 "cmDependsJavaParser.y"
- {
+ case 151: /* BlockStatements: BlockStatement */
+#line 1356 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3824 "cmDependsJavaParser.cxx"
+#line 4000 "cmDependsJavaParser.cxx"
break;
- case 152:
-#line 1367 "cmDependsJavaParser.y"
- {
+ case 152: /* BlockStatements: BlockStatements BlockStatement */
+#line 1365 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3836 "cmDependsJavaParser.cxx"
+#line 4012 "cmDependsJavaParser.cxx"
break;
- case 153:
-#line 1377 "cmDependsJavaParser.y"
- {
+ case 153: /* BlockStatement: LocalVariableDeclarationStatement */
+#line 1375 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3848 "cmDependsJavaParser.cxx"
+#line 4024 "cmDependsJavaParser.cxx"
break;
- case 154:
-#line 1386 "cmDependsJavaParser.y"
- {
+ case 154: /* BlockStatement: Statement */
+#line 1384 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3860 "cmDependsJavaParser.cxx"
+#line 4036 "cmDependsJavaParser.cxx"
break;
- case 155:
-#line 1395 "cmDependsJavaParser.y"
- {
+ case 155: /* BlockStatement: ClassDeclaration */
+#line 1393 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3872 "cmDependsJavaParser.cxx"
+#line 4048 "cmDependsJavaParser.cxx"
break;
- case 156:
-#line 1405 "cmDependsJavaParser.y"
- {
+ case 156: /* LocalVariableDeclarationStatement: LocalVariableDeclaration jp_SEMICOL */
+#line 1403 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3884 "cmDependsJavaParser.cxx"
+#line 4060 "cmDependsJavaParser.cxx"
break;
- case 157:
-#line 1415 "cmDependsJavaParser.y"
- {
+ case 157: /* LocalVariableDeclaration: Modifiers Type VariableDeclarators */
+#line 1413 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3896 "cmDependsJavaParser.cxx"
+#line 4072 "cmDependsJavaParser.cxx"
break;
- case 158:
-#line 1424 "cmDependsJavaParser.y"
- {
+ case 158: /* LocalVariableDeclaration: Type VariableDeclarators */
+#line 1422 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3908 "cmDependsJavaParser.cxx"
+#line 4084 "cmDependsJavaParser.cxx"
break;
- case 159:
-#line 1434 "cmDependsJavaParser.y"
- {
+ case 159: /* Statement: StatementWithoutTrailingSubstatement */
+#line 1432 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3920 "cmDependsJavaParser.cxx"
+#line 4096 "cmDependsJavaParser.cxx"
break;
- case 160:
-#line 1443 "cmDependsJavaParser.y"
- {
+ case 160: /* Statement: LabeledStatement */
+#line 1441 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3932 "cmDependsJavaParser.cxx"
+#line 4108 "cmDependsJavaParser.cxx"
break;
- case 161:
-#line 1452 "cmDependsJavaParser.y"
- {
+ case 161: /* Statement: IfThenStatement */
+#line 1450 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3944 "cmDependsJavaParser.cxx"
+#line 4120 "cmDependsJavaParser.cxx"
break;
- case 162:
-#line 1461 "cmDependsJavaParser.y"
- {
+ case 162: /* Statement: IfThenElseStatement */
+#line 1459 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3956 "cmDependsJavaParser.cxx"
+#line 4132 "cmDependsJavaParser.cxx"
break;
- case 163:
-#line 1470 "cmDependsJavaParser.y"
- {
+ case 163: /* Statement: WhileStatement */
+#line 1468 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3968 "cmDependsJavaParser.cxx"
+#line 4144 "cmDependsJavaParser.cxx"
break;
- case 164:
-#line 1479 "cmDependsJavaParser.y"
- {
+ case 164: /* Statement: ForStatement */
+#line 1477 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3980 "cmDependsJavaParser.cxx"
+#line 4156 "cmDependsJavaParser.cxx"
break;
- case 165:
-#line 1489 "cmDependsJavaParser.y"
- {
+ case 165: /* StatementNoShortIf: StatementWithoutTrailingSubstatement */
+#line 1487 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3992 "cmDependsJavaParser.cxx"
+#line 4168 "cmDependsJavaParser.cxx"
break;
- case 166:
-#line 1498 "cmDependsJavaParser.y"
- {
+ case 166: /* StatementNoShortIf: LabeledStatementNoShortIf */
+#line 1496 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4004 "cmDependsJavaParser.cxx"
+#line 4180 "cmDependsJavaParser.cxx"
break;
- case 167:
-#line 1507 "cmDependsJavaParser.y"
- {
+ case 167: /* StatementNoShortIf: IfThenElseStatementNoShortIf */
+#line 1505 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4016 "cmDependsJavaParser.cxx"
+#line 4192 "cmDependsJavaParser.cxx"
break;
- case 168:
-#line 1516 "cmDependsJavaParser.y"
- {
+ case 168: /* StatementNoShortIf: WhileStatementNoShortIf */
+#line 1514 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4028 "cmDependsJavaParser.cxx"
+#line 4204 "cmDependsJavaParser.cxx"
break;
- case 169:
-#line 1525 "cmDependsJavaParser.y"
- {
+ case 169: /* StatementNoShortIf: ForStatementNoShortIf */
+#line 1523 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4040 "cmDependsJavaParser.cxx"
+#line 4216 "cmDependsJavaParser.cxx"
break;
- case 170:
-#line 1535 "cmDependsJavaParser.y"
- {
+ case 170: /* StatementWithoutTrailingSubstatement: Block */
+#line 1533 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4052 "cmDependsJavaParser.cxx"
+#line 4228 "cmDependsJavaParser.cxx"
break;
- case 171:
-#line 1544 "cmDependsJavaParser.y"
- {
+ case 171: /* StatementWithoutTrailingSubstatement: EmptyStatement */
+#line 1542 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4064 "cmDependsJavaParser.cxx"
+#line 4240 "cmDependsJavaParser.cxx"
break;
- case 172:
-#line 1553 "cmDependsJavaParser.y"
- {
+ case 172: /* StatementWithoutTrailingSubstatement: ExpressionStatement */
+#line 1551 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4076 "cmDependsJavaParser.cxx"
+#line 4252 "cmDependsJavaParser.cxx"
break;
- case 173:
-#line 1562 "cmDependsJavaParser.y"
- {
+ case 173: /* StatementWithoutTrailingSubstatement: SwitchStatement */
+#line 1560 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4088 "cmDependsJavaParser.cxx"
+#line 4264 "cmDependsJavaParser.cxx"
break;
- case 174:
-#line 1571 "cmDependsJavaParser.y"
- {
+ case 174: /* StatementWithoutTrailingSubstatement: DoStatement */
+#line 1569 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4100 "cmDependsJavaParser.cxx"
+#line 4276 "cmDependsJavaParser.cxx"
break;
- case 175:
-#line 1580 "cmDependsJavaParser.y"
- {
+ case 175: /* StatementWithoutTrailingSubstatement: BreakStatement */
+#line 1578 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4112 "cmDependsJavaParser.cxx"
+#line 4288 "cmDependsJavaParser.cxx"
break;
- case 176:
-#line 1589 "cmDependsJavaParser.y"
- {
+ case 176: /* StatementWithoutTrailingSubstatement: ContinueStatement */
+#line 1587 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4124 "cmDependsJavaParser.cxx"
+#line 4300 "cmDependsJavaParser.cxx"
break;
- case 177:
-#line 1598 "cmDependsJavaParser.y"
- {
+ case 177: /* StatementWithoutTrailingSubstatement: ReturnStatement */
+#line 1596 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4136 "cmDependsJavaParser.cxx"
+#line 4312 "cmDependsJavaParser.cxx"
break;
- case 178:
-#line 1607 "cmDependsJavaParser.y"
- {
+ case 178: /* StatementWithoutTrailingSubstatement: SynchronizedStatement */
+#line 1605 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4148 "cmDependsJavaParser.cxx"
+#line 4324 "cmDependsJavaParser.cxx"
break;
- case 179:
-#line 1616 "cmDependsJavaParser.y"
- {
+ case 179: /* StatementWithoutTrailingSubstatement: ThrowStatement */
+#line 1614 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4160 "cmDependsJavaParser.cxx"
+#line 4336 "cmDependsJavaParser.cxx"
break;
- case 180:
-#line 1625 "cmDependsJavaParser.y"
- {
+ case 180: /* StatementWithoutTrailingSubstatement: TryStatement */
+#line 1623 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4172 "cmDependsJavaParser.cxx"
+#line 4348 "cmDependsJavaParser.cxx"
break;
- case 181:
-#line 1634 "cmDependsJavaParser.y"
- {
+ case 181: /* StatementWithoutTrailingSubstatement: AssertStatement */
+#line 1632 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4184 "cmDependsJavaParser.cxx"
+#line 4360 "cmDependsJavaParser.cxx"
break;
- case 182:
-#line 1644 "cmDependsJavaParser.y"
- {
+ case 182: /* EmptyStatement: jp_SEMICOL */
+#line 1642 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4196 "cmDependsJavaParser.cxx"
+#line 4372 "cmDependsJavaParser.cxx"
break;
- case 183:
-#line 1654 "cmDependsJavaParser.y"
- {
+ case 183: /* LabeledStatement: Identifier jp_COLON Statement */
+#line 1652 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
jpCheckEmpty(3);
@@ -4205,480 +4381,480 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4209 "cmDependsJavaParser.cxx"
+#line 4385 "cmDependsJavaParser.cxx"
break;
- case 184:
-#line 1665 "cmDependsJavaParser.y"
- {
+ case 184: /* LabeledStatementNoShortIf: Identifier jp_COLON StatementNoShortIf */
+#line 1663 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4221 "cmDependsJavaParser.cxx"
+#line 4397 "cmDependsJavaParser.cxx"
break;
- case 185:
-#line 1675 "cmDependsJavaParser.y"
- {
+ case 185: /* ExpressionStatement: StatementExpression jp_SEMICOL */
+#line 1673 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4233 "cmDependsJavaParser.cxx"
+#line 4409 "cmDependsJavaParser.cxx"
break;
- case 186:
-#line 1685 "cmDependsJavaParser.y"
- {
+ case 186: /* StatementExpression: Assignment */
+#line 1683 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4245 "cmDependsJavaParser.cxx"
+#line 4421 "cmDependsJavaParser.cxx"
break;
- case 187:
-#line 1694 "cmDependsJavaParser.y"
- {
+ case 187: /* StatementExpression: PreIncrementExpression */
+#line 1692 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4257 "cmDependsJavaParser.cxx"
+#line 4433 "cmDependsJavaParser.cxx"
break;
- case 188:
-#line 1703 "cmDependsJavaParser.y"
- {
+ case 188: /* StatementExpression: PreDecrementExpression */
+#line 1701 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4269 "cmDependsJavaParser.cxx"
+#line 4445 "cmDependsJavaParser.cxx"
break;
- case 189:
-#line 1712 "cmDependsJavaParser.y"
- {
+ case 189: /* StatementExpression: PostIncrementExpression */
+#line 1710 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4281 "cmDependsJavaParser.cxx"
+#line 4457 "cmDependsJavaParser.cxx"
break;
- case 190:
-#line 1721 "cmDependsJavaParser.y"
- {
+ case 190: /* StatementExpression: PostDecrementExpression */
+#line 1719 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4293 "cmDependsJavaParser.cxx"
+#line 4469 "cmDependsJavaParser.cxx"
break;
- case 191:
-#line 1730 "cmDependsJavaParser.y"
- {
+ case 191: /* StatementExpression: MethodInvocation */
+#line 1728 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4305 "cmDependsJavaParser.cxx"
+#line 4481 "cmDependsJavaParser.cxx"
break;
- case 192:
-#line 1739 "cmDependsJavaParser.y"
- {
+ case 192: /* StatementExpression: ClassInstanceCreationExpression */
+#line 1737 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4317 "cmDependsJavaParser.cxx"
+#line 4493 "cmDependsJavaParser.cxx"
break;
- case 193:
-#line 1749 "cmDependsJavaParser.y"
- {
+ case 193: /* IfThenStatement: jp_IF jp_PARESTART Expression jp_PAREEND Statement */
+#line 1747 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4329 "cmDependsJavaParser.cxx"
+#line 4505 "cmDependsJavaParser.cxx"
break;
- case 194:
-#line 1759 "cmDependsJavaParser.y"
- {
+ case 194: /* IfThenElseStatement: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE Statement */
+#line 1757 "cmDependsJavaParser.y"
+{
jpElementStart(7);
jpCheckEmpty(7);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4341 "cmDependsJavaParser.cxx"
+#line 4517 "cmDependsJavaParser.cxx"
break;
- case 195:
-#line 1769 "cmDependsJavaParser.y"
- {
+ case 195: /* IfThenElseStatementNoShortIf: jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE StatementNoShortIf */
+#line 1767 "cmDependsJavaParser.y"
+{
jpElementStart(7);
jpCheckEmpty(7);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4353 "cmDependsJavaParser.cxx"
+#line 4529 "cmDependsJavaParser.cxx"
break;
- case 196:
-#line 1779 "cmDependsJavaParser.y"
- {
+ case 196: /* SwitchStatement: jp_SWITCH jp_PARESTART Expression jp_PAREEND SwitchBlock */
+#line 1777 "cmDependsJavaParser.y"
+{
jpElementStart(5);
}
-#line 4362 "cmDependsJavaParser.cxx"
+#line 4538 "cmDependsJavaParser.cxx"
break;
- case 197:
-#line 1786 "cmDependsJavaParser.y"
- {
+ case 197: /* SwitchBlock: jp_CURLYSTART SwitchBlockStatementGroups SwitchLabelsopt jp_CURLYEND */
+#line 1784 "cmDependsJavaParser.y"
+{
jpElementStart(4);
}
-#line 4371 "cmDependsJavaParser.cxx"
+#line 4547 "cmDependsJavaParser.cxx"
break;
- case 198:
-#line 1792 "cmDependsJavaParser.y"
- {
+ case 198: /* SwitchLabelsopt: %empty */
+#line 1790 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4382 "cmDependsJavaParser.cxx"
+#line 4558 "cmDependsJavaParser.cxx"
break;
- case 199:
-#line 1800 "cmDependsJavaParser.y"
- {
+ case 199: /* SwitchLabelsopt: SwitchLabels */
+#line 1798 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4394 "cmDependsJavaParser.cxx"
+#line 4570 "cmDependsJavaParser.cxx"
break;
- case 200:
-#line 1809 "cmDependsJavaParser.y"
- {
+ case 200: /* SwitchBlockStatementGroups: %empty */
+#line 1807 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4405 "cmDependsJavaParser.cxx"
+#line 4581 "cmDependsJavaParser.cxx"
break;
- case 201:
-#line 1817 "cmDependsJavaParser.y"
- {
+ case 201: /* SwitchBlockStatementGroups: SwitchBlockStatementGroups SwitchBlockStatementGroup */
+#line 1815 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4417 "cmDependsJavaParser.cxx"
+#line 4593 "cmDependsJavaParser.cxx"
break;
- case 202:
-#line 1827 "cmDependsJavaParser.y"
- {
+ case 202: /* SwitchBlockStatementGroup: SwitchLabels BlockStatements */
+#line 1825 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4429 "cmDependsJavaParser.cxx"
+#line 4605 "cmDependsJavaParser.cxx"
break;
- case 203:
-#line 1837 "cmDependsJavaParser.y"
- {
+ case 203: /* SwitchLabels: SwitchLabel */
+#line 1835 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4441 "cmDependsJavaParser.cxx"
+#line 4617 "cmDependsJavaParser.cxx"
break;
- case 204:
-#line 1846 "cmDependsJavaParser.y"
- {
+ case 204: /* SwitchLabels: SwitchLabels SwitchLabel */
+#line 1844 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4453 "cmDependsJavaParser.cxx"
+#line 4629 "cmDependsJavaParser.cxx"
break;
- case 205:
-#line 1856 "cmDependsJavaParser.y"
- {
+ case 205: /* SwitchLabel: jp_CASE ConstantExpression jp_COLON */
+#line 1854 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4465 "cmDependsJavaParser.cxx"
+#line 4641 "cmDependsJavaParser.cxx"
break;
- case 206:
-#line 1865 "cmDependsJavaParser.y"
- {
+ case 206: /* SwitchLabel: jp_DEFAULT jp_COLON */
+#line 1863 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4477 "cmDependsJavaParser.cxx"
+#line 4653 "cmDependsJavaParser.cxx"
break;
- case 207:
-#line 1875 "cmDependsJavaParser.y"
- {
+ case 207: /* WhileStatement: jp_WHILE jp_PARESTART Expression jp_PAREEND Statement */
+#line 1873 "cmDependsJavaParser.y"
+{
jpElementStart(5);
}
-#line 4486 "cmDependsJavaParser.cxx"
+#line 4662 "cmDependsJavaParser.cxx"
break;
- case 208:
-#line 1882 "cmDependsJavaParser.y"
- {
+ case 208: /* WhileStatementNoShortIf: jp_WHILE jp_PARESTART Expression jp_PAREEND StatementNoShortIf */
+#line 1880 "cmDependsJavaParser.y"
+{
jpElementStart(5);
}
-#line 4495 "cmDependsJavaParser.cxx"
+#line 4671 "cmDependsJavaParser.cxx"
break;
- case 209:
-#line 1889 "cmDependsJavaParser.y"
- {
+ case 209: /* DoStatement: jp_DO Statement jp_WHILE jp_PARESTART Expression jp_PAREEND jp_SEMICOL */
+#line 1887 "cmDependsJavaParser.y"
+{
jpElementStart(7);
}
-#line 4504 "cmDependsJavaParser.cxx"
+#line 4680 "cmDependsJavaParser.cxx"
break;
- case 210:
-#line 1897 "cmDependsJavaParser.y"
- {
+ case 210: /* ForStatement: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND Statement */
+#line 1895 "cmDependsJavaParser.y"
+{
jpElementStart(9);
}
-#line 4513 "cmDependsJavaParser.cxx"
+#line 4689 "cmDependsJavaParser.cxx"
break;
- case 211:
-#line 1903 "cmDependsJavaParser.y"
- {
+ case 211: /* ForUpdateopt: %empty */
+#line 1901 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4524 "cmDependsJavaParser.cxx"
+#line 4700 "cmDependsJavaParser.cxx"
break;
- case 212:
-#line 1911 "cmDependsJavaParser.y"
- {
+ case 212: /* ForUpdateopt: ForUpdate */
+#line 1909 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4536 "cmDependsJavaParser.cxx"
+#line 4712 "cmDependsJavaParser.cxx"
break;
- case 213:
-#line 1920 "cmDependsJavaParser.y"
- {
+ case 213: /* ForInitopt: %empty */
+#line 1918 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4547 "cmDependsJavaParser.cxx"
+#line 4723 "cmDependsJavaParser.cxx"
break;
- case 214:
-#line 1928 "cmDependsJavaParser.y"
- {
+ case 214: /* ForInitopt: ForInit */
+#line 1926 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4559 "cmDependsJavaParser.cxx"
+#line 4735 "cmDependsJavaParser.cxx"
break;
- case 215:
-#line 1939 "cmDependsJavaParser.y"
- {
+ case 215: /* ForStatementNoShortIf: jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND StatementNoShortIf */
+#line 1937 "cmDependsJavaParser.y"
+{
jpElementStart(9);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4570 "cmDependsJavaParser.cxx"
+#line 4746 "cmDependsJavaParser.cxx"
break;
- case 216:
-#line 1947 "cmDependsJavaParser.y"
- {
+ case 216: /* Expressionopt: %empty */
+#line 1945 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4581 "cmDependsJavaParser.cxx"
+#line 4757 "cmDependsJavaParser.cxx"
break;
- case 217:
-#line 1955 "cmDependsJavaParser.y"
- {
+ case 217: /* Expressionopt: Expression */
+#line 1953 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4593 "cmDependsJavaParser.cxx"
+#line 4769 "cmDependsJavaParser.cxx"
break;
- case 218:
-#line 1965 "cmDependsJavaParser.y"
- {
+ case 218: /* ForInit: StatementExpressionList */
+#line 1963 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4605 "cmDependsJavaParser.cxx"
+#line 4781 "cmDependsJavaParser.cxx"
break;
- case 219:
-#line 1974 "cmDependsJavaParser.y"
- {
+ case 219: /* ForInit: LocalVariableDeclaration */
+#line 1972 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4617 "cmDependsJavaParser.cxx"
+#line 4793 "cmDependsJavaParser.cxx"
break;
- case 220:
-#line 1984 "cmDependsJavaParser.y"
- {
+ case 220: /* ForUpdate: StatementExpressionList */
+#line 1982 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4629 "cmDependsJavaParser.cxx"
+#line 4805 "cmDependsJavaParser.cxx"
break;
- case 221:
-#line 1994 "cmDependsJavaParser.y"
- {
+ case 221: /* StatementExpressionList: StatementExpression */
+#line 1992 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4641 "cmDependsJavaParser.cxx"
+#line 4817 "cmDependsJavaParser.cxx"
break;
- case 222:
-#line 2003 "cmDependsJavaParser.y"
- {
+ case 222: /* StatementExpressionList: StatementExpressionList jp_COMMA StatementExpression */
+#line 2001 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4653 "cmDependsJavaParser.cxx"
+#line 4829 "cmDependsJavaParser.cxx"
break;
- case 223:
-#line 2013 "cmDependsJavaParser.y"
- {
+ case 223: /* AssertStatement: jp_ASSERT Expression jp_SEMICOL */
+#line 2011 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4665 "cmDependsJavaParser.cxx"
+#line 4841 "cmDependsJavaParser.cxx"
break;
- case 224:
-#line 2022 "cmDependsJavaParser.y"
- {
+ case 224: /* AssertStatement: jp_ASSERT Expression jp_COLON Expression jp_SEMICOL */
+#line 2020 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4677 "cmDependsJavaParser.cxx"
+#line 4853 "cmDependsJavaParser.cxx"
break;
- case 225:
-#line 2032 "cmDependsJavaParser.y"
- {
+ case 225: /* BreakStatement: jp_BREAK Identifieropt jp_SEMICOL */
+#line 2030 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
jpCheckEmpty(3);
@@ -4686,32 +4862,32 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4690 "cmDependsJavaParser.cxx"
+#line 4866 "cmDependsJavaParser.cxx"
break;
- case 226:
-#line 2042 "cmDependsJavaParser.y"
- {
+ case 226: /* Identifieropt: %empty */
+#line 2040 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4701 "cmDependsJavaParser.cxx"
+#line 4877 "cmDependsJavaParser.cxx"
break;
- case 227:
-#line 2050 "cmDependsJavaParser.y"
- {
+ case 227: /* Identifieropt: Identifier */
+#line 2048 "cmDependsJavaParser.y"
+{
jpElementStart(1);
}
-#line 4710 "cmDependsJavaParser.cxx"
+#line 4886 "cmDependsJavaParser.cxx"
break;
- case 228:
-#line 2057 "cmDependsJavaParser.y"
- {
+ case 228: /* ContinueStatement: jp_CONTINUE Identifieropt jp_SEMICOL */
+#line 2055 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
jpCheckEmpty(3);
@@ -4719,452 +4895,452 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4723 "cmDependsJavaParser.cxx"
+#line 4899 "cmDependsJavaParser.cxx"
break;
- case 229:
-#line 2068 "cmDependsJavaParser.y"
- {
+ case 229: /* ReturnStatement: jp_RETURN Expressionopt jp_SEMICOL */
+#line 2066 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4735 "cmDependsJavaParser.cxx"
+#line 4911 "cmDependsJavaParser.cxx"
break;
- case 230:
-#line 2078 "cmDependsJavaParser.y"
- {
+ case 230: /* ThrowStatement: jp_THROW Expression jp_SEMICOL */
+#line 2076 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4747 "cmDependsJavaParser.cxx"
+#line 4923 "cmDependsJavaParser.cxx"
break;
- case 231:
-#line 2088 "cmDependsJavaParser.y"
- {
+ case 231: /* SynchronizedStatement: jp_SYNCHRONIZED jp_PARESTART Expression jp_PAREEND Block */
+#line 2086 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4759 "cmDependsJavaParser.cxx"
+#line 4935 "cmDependsJavaParser.cxx"
break;
- case 232:
-#line 2098 "cmDependsJavaParser.y"
- {
+ case 232: /* TryStatement: jp_TRY Block Catches */
+#line 2096 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4771 "cmDependsJavaParser.cxx"
+#line 4947 "cmDependsJavaParser.cxx"
break;
- case 233:
-#line 2107 "cmDependsJavaParser.y"
- {
+ case 233: /* TryStatement: jp_TRY Block Catchesopt Finally */
+#line 2105 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4783 "cmDependsJavaParser.cxx"
+#line 4959 "cmDependsJavaParser.cxx"
break;
- case 234:
-#line 2116 "cmDependsJavaParser.y"
- {
+ case 234: /* Catchesopt: %empty */
+#line 2114 "cmDependsJavaParser.y"
+{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4794 "cmDependsJavaParser.cxx"
+#line 4970 "cmDependsJavaParser.cxx"
break;
- case 235:
-#line 2124 "cmDependsJavaParser.y"
- {
+ case 235: /* Catchesopt: Catches */
+#line 2122 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4806 "cmDependsJavaParser.cxx"
+#line 4982 "cmDependsJavaParser.cxx"
break;
- case 236:
-#line 2134 "cmDependsJavaParser.y"
- {
+ case 236: /* Catches: CatchClause */
+#line 2132 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4818 "cmDependsJavaParser.cxx"
+#line 4994 "cmDependsJavaParser.cxx"
break;
- case 237:
-#line 2143 "cmDependsJavaParser.y"
- {
+ case 237: /* Catches: Catches CatchClause */
+#line 2141 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4830 "cmDependsJavaParser.cxx"
+#line 5006 "cmDependsJavaParser.cxx"
break;
- case 238:
-#line 2153 "cmDependsJavaParser.y"
- {
+ case 238: /* CatchClause: jp_CATCH jp_PARESTART FormalParameter jp_PAREEND Block */
+#line 2151 "cmDependsJavaParser.y"
+{
jpElementStart(5);
}
-#line 4839 "cmDependsJavaParser.cxx"
+#line 5015 "cmDependsJavaParser.cxx"
break;
- case 239:
-#line 2160 "cmDependsJavaParser.y"
- {
+ case 239: /* Finally: jp_FINALLY Block */
+#line 2158 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4851 "cmDependsJavaParser.cxx"
+#line 5027 "cmDependsJavaParser.cxx"
break;
- case 240:
-#line 2170 "cmDependsJavaParser.y"
- {
+ case 240: /* Primary: PrimaryNoNewArray */
+#line 2168 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4863 "cmDependsJavaParser.cxx"
+#line 5039 "cmDependsJavaParser.cxx"
break;
- case 241:
-#line 2179 "cmDependsJavaParser.y"
- {
+ case 241: /* Primary: ArrayCreationExpression */
+#line 2177 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4875 "cmDependsJavaParser.cxx"
+#line 5051 "cmDependsJavaParser.cxx"
break;
- case 242:
-#line 2189 "cmDependsJavaParser.y"
- {
+ case 242: /* PrimaryNoNewArray: Literal */
+#line 2187 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4887 "cmDependsJavaParser.cxx"
+#line 5063 "cmDependsJavaParser.cxx"
break;
- case 243:
-#line 2198 "cmDependsJavaParser.y"
- {
+ case 243: /* PrimaryNoNewArray: jp_THIS */
+#line 2196 "cmDependsJavaParser.y"
+{
jpElementStart(1);
}
-#line 4896 "cmDependsJavaParser.cxx"
+#line 5072 "cmDependsJavaParser.cxx"
break;
- case 244:
-#line 2204 "cmDependsJavaParser.y"
- {
+ case 244: /* PrimaryNoNewArray: jp_PARESTART Expression jp_PAREEND */
+#line 2202 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4908 "cmDependsJavaParser.cxx"
+#line 5084 "cmDependsJavaParser.cxx"
break;
- case 245:
-#line 2213 "cmDependsJavaParser.y"
- {
+ case 245: /* PrimaryNoNewArray: ClassInstanceCreationExpression */
+#line 2211 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4920 "cmDependsJavaParser.cxx"
+#line 5096 "cmDependsJavaParser.cxx"
break;
- case 246:
-#line 2222 "cmDependsJavaParser.y"
- {
+ case 246: /* PrimaryNoNewArray: FieldAccess */
+#line 2220 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4932 "cmDependsJavaParser.cxx"
+#line 5108 "cmDependsJavaParser.cxx"
break;
- case 247:
-#line 2231 "cmDependsJavaParser.y"
- {
+ case 247: /* PrimaryNoNewArray: MethodInvocation */
+#line 2229 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4944 "cmDependsJavaParser.cxx"
+#line 5120 "cmDependsJavaParser.cxx"
break;
- case 248:
-#line 2240 "cmDependsJavaParser.y"
- {
+ case 248: /* PrimaryNoNewArray: ArrayAccess */
+#line 2238 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4956 "cmDependsJavaParser.cxx"
+#line 5132 "cmDependsJavaParser.cxx"
break;
- case 249:
-#line 2250 "cmDependsJavaParser.y"
- {
+ case 249: /* ClassInstanceCreationExpression: New ClassType jp_PARESTART ArgumentListopt jp_PAREEND ClassBodyOpt */
+#line 2248 "cmDependsJavaParser.y"
+{
jpElementStart(6);
jpCheckEmpty(6);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4968 "cmDependsJavaParser.cxx"
+#line 5144 "cmDependsJavaParser.cxx"
break;
- case 250:
-#line 2259 "cmDependsJavaParser.y"
- {
+ case 250: /* ClassBodyOpt: %empty */
+#line 2257 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4979 "cmDependsJavaParser.cxx"
+#line 5155 "cmDependsJavaParser.cxx"
break;
- case 251:
-#line 2267 "cmDependsJavaParser.y"
- {
+ case 251: /* ClassBodyOpt: ClassBody */
+#line 2265 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4991 "cmDependsJavaParser.cxx"
+#line 5167 "cmDependsJavaParser.cxx"
break;
- case 252:
-#line 2276 "cmDependsJavaParser.y"
- {
+ case 252: /* ArgumentListopt: %empty */
+#line 2274 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5002 "cmDependsJavaParser.cxx"
+#line 5178 "cmDependsJavaParser.cxx"
break;
- case 253:
-#line 2284 "cmDependsJavaParser.y"
- {
+ case 253: /* ArgumentListopt: ArgumentList */
+#line 2282 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5014 "cmDependsJavaParser.cxx"
+#line 5190 "cmDependsJavaParser.cxx"
break;
- case 254:
-#line 2294 "cmDependsJavaParser.y"
- {
+ case 254: /* ArgumentList: Expression */
+#line 2292 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5026 "cmDependsJavaParser.cxx"
+#line 5202 "cmDependsJavaParser.cxx"
break;
- case 255:
-#line 2303 "cmDependsJavaParser.y"
- {
+ case 255: /* ArgumentList: ArgumentList jp_COMMA Expression */
+#line 2301 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5038 "cmDependsJavaParser.cxx"
+#line 5214 "cmDependsJavaParser.cxx"
break;
- case 256:
-#line 2313 "cmDependsJavaParser.y"
- {
+ case 256: /* ArrayCreationExpression: New PrimitiveType DimExprs Dimsopt */
+#line 2311 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5050 "cmDependsJavaParser.cxx"
+#line 5226 "cmDependsJavaParser.cxx"
break;
- case 257:
-#line 2322 "cmDependsJavaParser.y"
- {
+ case 257: /* ArrayCreationExpression: New ClassOrInterfaceType DimExprs Dimsopt */
+#line 2320 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5062 "cmDependsJavaParser.cxx"
+#line 5238 "cmDependsJavaParser.cxx"
break;
- case 258:
-#line 2331 "cmDependsJavaParser.y"
- {
+ case 258: /* ArrayCreationExpression: New PrimitiveType Dims ArrayInitializer */
+#line 2329 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5074 "cmDependsJavaParser.cxx"
+#line 5250 "cmDependsJavaParser.cxx"
break;
- case 259:
-#line 2340 "cmDependsJavaParser.y"
- {
+ case 259: /* ArrayCreationExpression: New ClassOrInterfaceType Dims ArrayInitializer */
+#line 2338 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5086 "cmDependsJavaParser.cxx"
+#line 5262 "cmDependsJavaParser.cxx"
break;
- case 260:
-#line 2349 "cmDependsJavaParser.y"
- {
+ case 260: /* Dimsopt: %empty */
+#line 2347 "cmDependsJavaParser.y"
+{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5097 "cmDependsJavaParser.cxx"
+#line 5273 "cmDependsJavaParser.cxx"
break;
- case 261:
-#line 2357 "cmDependsJavaParser.y"
- {
+ case 261: /* Dimsopt: Dims */
+#line 2355 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5109 "cmDependsJavaParser.cxx"
+#line 5285 "cmDependsJavaParser.cxx"
break;
- case 262:
-#line 2367 "cmDependsJavaParser.y"
- {
+ case 262: /* DimExprs: DimExpr */
+#line 2365 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5121 "cmDependsJavaParser.cxx"
+#line 5297 "cmDependsJavaParser.cxx"
break;
- case 263:
-#line 2376 "cmDependsJavaParser.y"
- {
+ case 263: /* DimExprs: DimExprs DimExpr */
+#line 2374 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5133 "cmDependsJavaParser.cxx"
+#line 5309 "cmDependsJavaParser.cxx"
break;
- case 264:
-#line 2386 "cmDependsJavaParser.y"
- {
+ case 264: /* DimExpr: jp_BRACKETSTART Expression jp_BRACKETEND */
+#line 2384 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5145 "cmDependsJavaParser.cxx"
+#line 5321 "cmDependsJavaParser.cxx"
break;
- case 265:
-#line 2396 "cmDependsJavaParser.y"
- {
+ case 265: /* Dims: jp_BRACKETSTART jp_BRACKETEND */
+#line 2394 "cmDependsJavaParser.y"
+{
jpElementStart(2);
}
-#line 5154 "cmDependsJavaParser.cxx"
+#line 5330 "cmDependsJavaParser.cxx"
break;
- case 266:
-#line 2402 "cmDependsJavaParser.y"
- {
+ case 266: /* Dims: Dims jp_BRACKETSTART jp_BRACKETEND */
+#line 2400 "cmDependsJavaParser.y"
+{
jpElementStart(3);
}
-#line 5163 "cmDependsJavaParser.cxx"
+#line 5339 "cmDependsJavaParser.cxx"
break;
- case 267:
-#line 2409 "cmDependsJavaParser.y"
- {
+ case 267: /* FieldAccess: Primary jp_DOT Identifier */
+#line 2407 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
@@ -5172,12 +5348,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5176 "cmDependsJavaParser.cxx"
+#line 5352 "cmDependsJavaParser.cxx"
break;
- case 268:
-#line 2419 "cmDependsJavaParser.y"
- {
+ case 268: /* FieldAccess: jp_SUPER jp_DOT Identifier */
+#line 2417 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
@@ -5185,12 +5361,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5189 "cmDependsJavaParser.cxx"
+#line 5365 "cmDependsJavaParser.cxx"
break;
- case 269:
-#line 2429 "cmDependsJavaParser.y"
- {
+ case 269: /* FieldAccess: jp_THIS jp_DOT Identifier */
+#line 2427 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
@@ -5198,12 +5374,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5202 "cmDependsJavaParser.cxx"
+#line 5378 "cmDependsJavaParser.cxx"
break;
- case 270:
-#line 2439 "cmDependsJavaParser.y"
- {
+ case 270: /* FieldAccess: Primary jp_DOT jp_THIS */
+#line 2437 "cmDependsJavaParser.y"
+{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
@@ -5211,12 +5387,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5215 "cmDependsJavaParser.cxx"
+#line 5391 "cmDependsJavaParser.cxx"
break;
- case 271:
-#line 2450 "cmDependsJavaParser.y"
- {
+ case 271: /* MethodInvocation: Name jp_PARESTART ArgumentListopt jp_PAREEND */
+#line 2448 "cmDependsJavaParser.y"
+{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
@@ -5224,12 +5400,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5228 "cmDependsJavaParser.cxx"
+#line 5404 "cmDependsJavaParser.cxx"
break;
- case 272:
-#line 2460 "cmDependsJavaParser.y"
- {
+ case 272: /* MethodInvocation: Primary jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */
+#line 2458 "cmDependsJavaParser.y"
+{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-5].str)));
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5238,12 +5414,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5242 "cmDependsJavaParser.cxx"
+#line 5418 "cmDependsJavaParser.cxx"
break;
- case 273:
-#line 2471 "cmDependsJavaParser.y"
- {
+ case 273: /* MethodInvocation: jp_SUPER jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */
+#line 2469 "cmDependsJavaParser.y"
+{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(6);
@@ -5251,12 +5427,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5255 "cmDependsJavaParser.cxx"
+#line 5431 "cmDependsJavaParser.cxx"
break;
- case 274:
-#line 2481 "cmDependsJavaParser.y"
- {
+ case 274: /* MethodInvocation: jp_THIS jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND */
+#line 2479 "cmDependsJavaParser.y"
+{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(6);
@@ -5264,12 +5440,12 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5268 "cmDependsJavaParser.cxx"
+#line 5444 "cmDependsJavaParser.cxx"
break;
- case 275:
-#line 2492 "cmDependsJavaParser.y"
- {
+ case 275: /* ArrayAccess: Name jp_BRACKETSTART Expression jp_BRACKETEND */
+#line 2490 "cmDependsJavaParser.y"
+{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
jpCheckEmpty(4);
@@ -5277,693 +5453,693 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5281 "cmDependsJavaParser.cxx"
+#line 5457 "cmDependsJavaParser.cxx"
break;
- case 276:
-#line 2502 "cmDependsJavaParser.y"
- {
+ case 276: /* ArrayAccess: PrimaryNoNewArray jp_BRACKETSTART Expression jp_BRACKETEND */
+#line 2500 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5293 "cmDependsJavaParser.cxx"
+#line 5469 "cmDependsJavaParser.cxx"
break;
- case 277:
-#line 2512 "cmDependsJavaParser.y"
- {
+ case 277: /* PostfixExpression: Primary */
+#line 2510 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5305 "cmDependsJavaParser.cxx"
+#line 5481 "cmDependsJavaParser.cxx"
break;
- case 278:
-#line 2521 "cmDependsJavaParser.y"
- {
+ case 278: /* PostfixExpression: Name */
+#line 2519 "cmDependsJavaParser.y"
+{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5317 "cmDependsJavaParser.cxx"
+#line 5493 "cmDependsJavaParser.cxx"
break;
- case 279:
-#line 2530 "cmDependsJavaParser.y"
- {
+ case 279: /* PostfixExpression: ArrayType jp_DOT jp_CLASS */
+#line 2528 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5329 "cmDependsJavaParser.cxx"
+#line 5505 "cmDependsJavaParser.cxx"
break;
- case 280:
-#line 2539 "cmDependsJavaParser.y"
- {
+ case 280: /* PostfixExpression: PostIncrementExpression */
+#line 2537 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5341 "cmDependsJavaParser.cxx"
+#line 5517 "cmDependsJavaParser.cxx"
break;
- case 281:
-#line 2548 "cmDependsJavaParser.y"
- {
+ case 281: /* PostfixExpression: PostDecrementExpression */
+#line 2546 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5353 "cmDependsJavaParser.cxx"
+#line 5529 "cmDependsJavaParser.cxx"
break;
- case 282:
-#line 2558 "cmDependsJavaParser.y"
- {
+ case 282: /* PostIncrementExpression: PostfixExpression jp_PLUSPLUS */
+#line 2556 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5365 "cmDependsJavaParser.cxx"
+#line 5541 "cmDependsJavaParser.cxx"
break;
- case 283:
-#line 2568 "cmDependsJavaParser.y"
- {
+ case 283: /* PostDecrementExpression: PostfixExpression jp_MINUSMINUS */
+#line 2566 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5377 "cmDependsJavaParser.cxx"
+#line 5553 "cmDependsJavaParser.cxx"
break;
- case 284:
-#line 2578 "cmDependsJavaParser.y"
- {
+ case 284: /* UnaryExpression: PreIncrementExpression */
+#line 2576 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5389 "cmDependsJavaParser.cxx"
+#line 5565 "cmDependsJavaParser.cxx"
break;
- case 285:
-#line 2587 "cmDependsJavaParser.y"
- {
+ case 285: /* UnaryExpression: PreDecrementExpression */
+#line 2585 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5401 "cmDependsJavaParser.cxx"
+#line 5577 "cmDependsJavaParser.cxx"
break;
- case 286:
-#line 2596 "cmDependsJavaParser.y"
- {
+ case 286: /* UnaryExpression: jp_PLUS UnaryExpression */
+#line 2594 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5413 "cmDependsJavaParser.cxx"
+#line 5589 "cmDependsJavaParser.cxx"
break;
- case 287:
-#line 2605 "cmDependsJavaParser.y"
- {
+ case 287: /* UnaryExpression: jp_MINUS UnaryExpression */
+#line 2603 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5425 "cmDependsJavaParser.cxx"
+#line 5601 "cmDependsJavaParser.cxx"
break;
- case 288:
-#line 2614 "cmDependsJavaParser.y"
- {
+ case 288: /* UnaryExpression: UnaryExpressionNotPlusMinus */
+#line 2612 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5437 "cmDependsJavaParser.cxx"
+#line 5613 "cmDependsJavaParser.cxx"
break;
- case 289:
-#line 2624 "cmDependsJavaParser.y"
- {
+ case 289: /* PreIncrementExpression: jp_PLUSPLUS UnaryExpression */
+#line 2622 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5449 "cmDependsJavaParser.cxx"
+#line 5625 "cmDependsJavaParser.cxx"
break;
- case 290:
-#line 2634 "cmDependsJavaParser.y"
- {
+ case 290: /* PreDecrementExpression: jp_MINUSMINUS UnaryExpression */
+#line 2632 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5461 "cmDependsJavaParser.cxx"
+#line 5637 "cmDependsJavaParser.cxx"
break;
- case 291:
-#line 2644 "cmDependsJavaParser.y"
- {
+ case 291: /* UnaryExpressionNotPlusMinus: PostfixExpression */
+#line 2642 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5473 "cmDependsJavaParser.cxx"
+#line 5649 "cmDependsJavaParser.cxx"
break;
- case 292:
-#line 2653 "cmDependsJavaParser.y"
- {
+ case 292: /* UnaryExpressionNotPlusMinus: jp_TILDE UnaryExpression */
+#line 2651 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5485 "cmDependsJavaParser.cxx"
+#line 5661 "cmDependsJavaParser.cxx"
break;
- case 293:
-#line 2662 "cmDependsJavaParser.y"
- {
+ case 293: /* UnaryExpressionNotPlusMinus: jp_EXCLAMATION UnaryExpression */
+#line 2660 "cmDependsJavaParser.y"
+{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5497 "cmDependsJavaParser.cxx"
+#line 5673 "cmDependsJavaParser.cxx"
break;
- case 294:
-#line 2671 "cmDependsJavaParser.y"
- {
+ case 294: /* UnaryExpressionNotPlusMinus: CastExpression */
+#line 2669 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5509 "cmDependsJavaParser.cxx"
+#line 5685 "cmDependsJavaParser.cxx"
break;
- case 295:
-#line 2681 "cmDependsJavaParser.y"
- {
+ case 295: /* CastExpression: jp_PARESTART PrimitiveType Dimsopt jp_PAREEND UnaryExpression */
+#line 2679 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5521 "cmDependsJavaParser.cxx"
+#line 5697 "cmDependsJavaParser.cxx"
break;
- case 296:
-#line 2690 "cmDependsJavaParser.y"
- {
+ case 296: /* CastExpression: jp_PARESTART Expression jp_PAREEND UnaryExpressionNotPlusMinus */
+#line 2688 "cmDependsJavaParser.y"
+{
jpElementStart(4);
jpCheckEmpty(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5533 "cmDependsJavaParser.cxx"
+#line 5709 "cmDependsJavaParser.cxx"
break;
- case 297:
-#line 2699 "cmDependsJavaParser.y"
- {
+ case 297: /* CastExpression: jp_PARESTART Name Dims jp_PAREEND UnaryExpressionNotPlusMinus */
+#line 2697 "cmDependsJavaParser.y"
+{
jpElementStart(5);
}
-#line 5542 "cmDependsJavaParser.cxx"
+#line 5718 "cmDependsJavaParser.cxx"
break;
- case 298:
-#line 2706 "cmDependsJavaParser.y"
- {
+ case 298: /* MultiplicativeExpression: UnaryExpression */
+#line 2704 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5554 "cmDependsJavaParser.cxx"
+#line 5730 "cmDependsJavaParser.cxx"
break;
- case 299:
-#line 2715 "cmDependsJavaParser.y"
- {
+ case 299: /* MultiplicativeExpression: MultiplicativeExpression jp_TIMES UnaryExpression */
+#line 2713 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5566 "cmDependsJavaParser.cxx"
+#line 5742 "cmDependsJavaParser.cxx"
break;
- case 300:
-#line 2724 "cmDependsJavaParser.y"
- {
+ case 300: /* MultiplicativeExpression: MultiplicativeExpression jp_DIVIDE UnaryExpression */
+#line 2722 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5578 "cmDependsJavaParser.cxx"
+#line 5754 "cmDependsJavaParser.cxx"
break;
- case 301:
-#line 2733 "cmDependsJavaParser.y"
- {
+ case 301: /* MultiplicativeExpression: MultiplicativeExpression jp_PERCENT UnaryExpression */
+#line 2731 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5590 "cmDependsJavaParser.cxx"
+#line 5766 "cmDependsJavaParser.cxx"
break;
- case 302:
-#line 2743 "cmDependsJavaParser.y"
- {
+ case 302: /* AdditiveExpression: MultiplicativeExpression */
+#line 2741 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5602 "cmDependsJavaParser.cxx"
+#line 5778 "cmDependsJavaParser.cxx"
break;
- case 303:
-#line 2752 "cmDependsJavaParser.y"
- {
+ case 303: /* AdditiveExpression: AdditiveExpression jp_PLUS MultiplicativeExpression */
+#line 2750 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5614 "cmDependsJavaParser.cxx"
+#line 5790 "cmDependsJavaParser.cxx"
break;
- case 304:
-#line 2761 "cmDependsJavaParser.y"
- {
+ case 304: /* AdditiveExpression: AdditiveExpression jp_MINUS MultiplicativeExpression */
+#line 2759 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5626 "cmDependsJavaParser.cxx"
+#line 5802 "cmDependsJavaParser.cxx"
break;
- case 305:
-#line 2771 "cmDependsJavaParser.y"
- {
+ case 305: /* ShiftExpression: AdditiveExpression */
+#line 2769 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5638 "cmDependsJavaParser.cxx"
+#line 5814 "cmDependsJavaParser.cxx"
break;
- case 306:
-#line 2780 "cmDependsJavaParser.y"
- {
+ case 306: /* ShiftExpression: ShiftExpression jp_LTLT AdditiveExpression */
+#line 2778 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5650 "cmDependsJavaParser.cxx"
+#line 5826 "cmDependsJavaParser.cxx"
break;
- case 307:
-#line 2789 "cmDependsJavaParser.y"
- {
+ case 307: /* ShiftExpression: ShiftExpression jp_GTGT AdditiveExpression */
+#line 2787 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5662 "cmDependsJavaParser.cxx"
+#line 5838 "cmDependsJavaParser.cxx"
break;
- case 308:
-#line 2798 "cmDependsJavaParser.y"
- {
+ case 308: /* ShiftExpression: ShiftExpression jp_GTGTGT AdditiveExpression */
+#line 2796 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5674 "cmDependsJavaParser.cxx"
+#line 5850 "cmDependsJavaParser.cxx"
break;
- case 309:
-#line 2808 "cmDependsJavaParser.y"
- {
+ case 309: /* RelationalExpression: ShiftExpression */
+#line 2806 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5686 "cmDependsJavaParser.cxx"
+#line 5862 "cmDependsJavaParser.cxx"
break;
- case 310:
-#line 2817 "cmDependsJavaParser.y"
- {
+ case 310: /* RelationalExpression: RelationalExpression jp_LESSTHAN ShiftExpression */
+#line 2815 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5698 "cmDependsJavaParser.cxx"
+#line 5874 "cmDependsJavaParser.cxx"
break;
- case 311:
-#line 2826 "cmDependsJavaParser.y"
- {
+ case 311: /* RelationalExpression: RelationalExpression jp_GREATER ShiftExpression */
+#line 2824 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5710 "cmDependsJavaParser.cxx"
+#line 5886 "cmDependsJavaParser.cxx"
break;
- case 312:
-#line 2835 "cmDependsJavaParser.y"
- {
+ case 312: /* RelationalExpression: RelationalExpression jp_LTEQUALS ShiftExpression */
+#line 2833 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5722 "cmDependsJavaParser.cxx"
+#line 5898 "cmDependsJavaParser.cxx"
break;
- case 313:
-#line 2844 "cmDependsJavaParser.y"
- {
+ case 313: /* RelationalExpression: RelationalExpression jp_GTEQUALS ShiftExpression */
+#line 2842 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5734 "cmDependsJavaParser.cxx"
+#line 5910 "cmDependsJavaParser.cxx"
break;
- case 314:
-#line 2853 "cmDependsJavaParser.y"
- {
+ case 314: /* RelationalExpression: RelationalExpression jp_INSTANCEOF ReferenceType */
+#line 2851 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5746 "cmDependsJavaParser.cxx"
+#line 5922 "cmDependsJavaParser.cxx"
break;
- case 315:
-#line 2863 "cmDependsJavaParser.y"
- {
+ case 315: /* EqualityExpression: RelationalExpression */
+#line 2861 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5758 "cmDependsJavaParser.cxx"
+#line 5934 "cmDependsJavaParser.cxx"
break;
- case 316:
-#line 2872 "cmDependsJavaParser.y"
- {
+ case 316: /* EqualityExpression: EqualityExpression jp_EQUALSEQUALS RelationalExpression */
+#line 2870 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5770 "cmDependsJavaParser.cxx"
+#line 5946 "cmDependsJavaParser.cxx"
break;
- case 317:
-#line 2881 "cmDependsJavaParser.y"
- {
+ case 317: /* EqualityExpression: EqualityExpression jp_EXCLAMATIONEQUALS RelationalExpression */
+#line 2879 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5782 "cmDependsJavaParser.cxx"
+#line 5958 "cmDependsJavaParser.cxx"
break;
- case 318:
-#line 2891 "cmDependsJavaParser.y"
- {
+ case 318: /* AndExpression: EqualityExpression */
+#line 2889 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5794 "cmDependsJavaParser.cxx"
+#line 5970 "cmDependsJavaParser.cxx"
break;
- case 319:
-#line 2900 "cmDependsJavaParser.y"
- {
+ case 319: /* AndExpression: AndExpression jp_AND EqualityExpression */
+#line 2898 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5806 "cmDependsJavaParser.cxx"
+#line 5982 "cmDependsJavaParser.cxx"
break;
- case 320:
-#line 2910 "cmDependsJavaParser.y"
- {
+ case 320: /* ExclusiveOrExpression: AndExpression */
+#line 2908 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5818 "cmDependsJavaParser.cxx"
+#line 5994 "cmDependsJavaParser.cxx"
break;
- case 321:
-#line 2919 "cmDependsJavaParser.y"
- {
+ case 321: /* ExclusiveOrExpression: ExclusiveOrExpression jp_CARROT AndExpression */
+#line 2917 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5830 "cmDependsJavaParser.cxx"
+#line 6006 "cmDependsJavaParser.cxx"
break;
- case 322:
-#line 2929 "cmDependsJavaParser.y"
- {
+ case 322: /* InclusiveOrExpression: ExclusiveOrExpression */
+#line 2927 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5842 "cmDependsJavaParser.cxx"
+#line 6018 "cmDependsJavaParser.cxx"
break;
- case 323:
-#line 2938 "cmDependsJavaParser.y"
- {
+ case 323: /* InclusiveOrExpression: InclusiveOrExpression jp_PIPE ExclusiveOrExpression */
+#line 2936 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5854 "cmDependsJavaParser.cxx"
+#line 6030 "cmDependsJavaParser.cxx"
break;
- case 324:
-#line 2948 "cmDependsJavaParser.y"
- {
+ case 324: /* ConditionalAndExpression: InclusiveOrExpression */
+#line 2946 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5866 "cmDependsJavaParser.cxx"
+#line 6042 "cmDependsJavaParser.cxx"
break;
- case 325:
-#line 2957 "cmDependsJavaParser.y"
- {
+ case 325: /* ConditionalAndExpression: ConditionalAndExpression jp_ANDAND InclusiveOrExpression */
+#line 2955 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5878 "cmDependsJavaParser.cxx"
+#line 6054 "cmDependsJavaParser.cxx"
break;
- case 326:
-#line 2967 "cmDependsJavaParser.y"
- {
+ case 326: /* ConditionalOrExpression: ConditionalAndExpression */
+#line 2965 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5890 "cmDependsJavaParser.cxx"
+#line 6066 "cmDependsJavaParser.cxx"
break;
- case 327:
-#line 2976 "cmDependsJavaParser.y"
- {
+ case 327: /* ConditionalOrExpression: ConditionalOrExpression jp_PIPEPIPE ConditionalAndExpression */
+#line 2974 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5902 "cmDependsJavaParser.cxx"
+#line 6078 "cmDependsJavaParser.cxx"
break;
- case 328:
-#line 2986 "cmDependsJavaParser.y"
- {
+ case 328: /* ConditionalExpression: ConditionalOrExpression */
+#line 2984 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5914 "cmDependsJavaParser.cxx"
+#line 6090 "cmDependsJavaParser.cxx"
break;
- case 329:
-#line 2995 "cmDependsJavaParser.y"
- {
+ case 329: /* ConditionalExpression: ConditionalOrExpression jp_QUESTION Expression jp_COLON ConditionalExpression */
+#line 2993 "cmDependsJavaParser.y"
+{
jpElementStart(5);
jpCheckEmpty(5);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5926 "cmDependsJavaParser.cxx"
+#line 6102 "cmDependsJavaParser.cxx"
break;
- case 330:
-#line 3005 "cmDependsJavaParser.y"
- {
+ case 330: /* AssignmentExpression: ConditionalExpression */
+#line 3003 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5938 "cmDependsJavaParser.cxx"
+#line 6114 "cmDependsJavaParser.cxx"
break;
- case 331:
-#line 3014 "cmDependsJavaParser.y"
- {
+ case 331: /* AssignmentExpression: Assignment */
+#line 3012 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5950 "cmDependsJavaParser.cxx"
+#line 6126 "cmDependsJavaParser.cxx"
break;
- case 332:
-#line 3024 "cmDependsJavaParser.y"
- {
+ case 332: /* Assignment: LeftHandSide AssignmentOperator AssignmentExpression */
+#line 3022 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5962 "cmDependsJavaParser.cxx"
+#line 6138 "cmDependsJavaParser.cxx"
break;
- case 333:
-#line 3034 "cmDependsJavaParser.y"
- {
+ case 333: /* LeftHandSide: Name */
+#line 3032 "cmDependsJavaParser.y"
+{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(1);
@@ -5971,216 +6147,216 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5975 "cmDependsJavaParser.cxx"
+#line 6151 "cmDependsJavaParser.cxx"
break;
- case 334:
-#line 3044 "cmDependsJavaParser.y"
- {
+ case 334: /* LeftHandSide: FieldAccess */
+#line 3042 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5987 "cmDependsJavaParser.cxx"
+#line 6163 "cmDependsJavaParser.cxx"
break;
- case 335:
-#line 3053 "cmDependsJavaParser.y"
- {
+ case 335: /* LeftHandSide: ArrayAccess */
+#line 3051 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5999 "cmDependsJavaParser.cxx"
+#line 6175 "cmDependsJavaParser.cxx"
break;
- case 336:
-#line 3063 "cmDependsJavaParser.y"
- {
+ case 336: /* AssignmentOperator: jp_EQUALS */
+#line 3061 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6011 "cmDependsJavaParser.cxx"
+#line 6187 "cmDependsJavaParser.cxx"
break;
- case 337:
-#line 3072 "cmDependsJavaParser.y"
- {
+ case 337: /* AssignmentOperator: jp_TIMESEQUALS */
+#line 3070 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6023 "cmDependsJavaParser.cxx"
+#line 6199 "cmDependsJavaParser.cxx"
break;
- case 338:
-#line 3081 "cmDependsJavaParser.y"
- {
+ case 338: /* AssignmentOperator: jp_DIVIDEEQUALS */
+#line 3079 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6035 "cmDependsJavaParser.cxx"
+#line 6211 "cmDependsJavaParser.cxx"
break;
- case 339:
-#line 3090 "cmDependsJavaParser.y"
- {
+ case 339: /* AssignmentOperator: jp_PERCENTEQUALS */
+#line 3088 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6047 "cmDependsJavaParser.cxx"
+#line 6223 "cmDependsJavaParser.cxx"
break;
- case 340:
-#line 3099 "cmDependsJavaParser.y"
- {
+ case 340: /* AssignmentOperator: jp_PLUSEQUALS */
+#line 3097 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6059 "cmDependsJavaParser.cxx"
+#line 6235 "cmDependsJavaParser.cxx"
break;
- case 341:
-#line 3108 "cmDependsJavaParser.y"
- {
+ case 341: /* AssignmentOperator: jp_MINUSEQUALS */
+#line 3106 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6071 "cmDependsJavaParser.cxx"
+#line 6247 "cmDependsJavaParser.cxx"
break;
- case 342:
-#line 3117 "cmDependsJavaParser.y"
- {
+ case 342: /* AssignmentOperator: jp_LESLESEQUALS */
+#line 3115 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6083 "cmDependsJavaParser.cxx"
+#line 6259 "cmDependsJavaParser.cxx"
break;
- case 343:
-#line 3126 "cmDependsJavaParser.y"
- {
+ case 343: /* AssignmentOperator: jp_GTGTEQUALS */
+#line 3124 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6095 "cmDependsJavaParser.cxx"
+#line 6271 "cmDependsJavaParser.cxx"
break;
- case 344:
-#line 3135 "cmDependsJavaParser.y"
- {
+ case 344: /* AssignmentOperator: jp_GTGTGTEQUALS */
+#line 3133 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6107 "cmDependsJavaParser.cxx"
+#line 6283 "cmDependsJavaParser.cxx"
break;
- case 345:
-#line 3144 "cmDependsJavaParser.y"
- {
+ case 345: /* AssignmentOperator: jp_ANDEQUALS */
+#line 3142 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6119 "cmDependsJavaParser.cxx"
+#line 6295 "cmDependsJavaParser.cxx"
break;
- case 346:
-#line 3153 "cmDependsJavaParser.y"
- {
+ case 346: /* AssignmentOperator: jp_CARROTEQUALS */
+#line 3151 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6131 "cmDependsJavaParser.cxx"
+#line 6307 "cmDependsJavaParser.cxx"
break;
- case 347:
-#line 3162 "cmDependsJavaParser.y"
- {
+ case 347: /* AssignmentOperator: jp_PIPEEQUALS */
+#line 3160 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6143 "cmDependsJavaParser.cxx"
+#line 6319 "cmDependsJavaParser.cxx"
break;
- case 348:
-#line 3172 "cmDependsJavaParser.y"
- {
+ case 348: /* Expression: AssignmentExpression */
+#line 3170 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6155 "cmDependsJavaParser.cxx"
+#line 6331 "cmDependsJavaParser.cxx"
break;
- case 349:
-#line 3182 "cmDependsJavaParser.y"
- {
+ case 349: /* ConstantExpression: Expression */
+#line 3180 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6167 "cmDependsJavaParser.cxx"
+#line 6343 "cmDependsJavaParser.cxx"
break;
- case 350:
-#line 3192 "cmDependsJavaParser.y"
- {
+ case 350: /* New: jp_NEW */
+#line 3190 "cmDependsJavaParser.y"
+{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 6179 "cmDependsJavaParser.cxx"
+#line 6355 "cmDependsJavaParser.cxx"
break;
- case 351:
-#line 3201 "cmDependsJavaParser.y"
- {
+ case 351: /* New: Name jp_DOT jp_NEW */
+#line 3199 "cmDependsJavaParser.y"
+{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
jpCheckEmpty(3);
@@ -6188,11 +6364,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6192 "cmDependsJavaParser.cxx"
+#line 6368 "cmDependsJavaParser.cxx"
break;
-#line 6196 "cmDependsJavaParser.cxx"
+#line 6372 "cmDependsJavaParser.cxx"
default: break;
}
@@ -6207,11 +6383,10 @@ yyreduce:
case of YYERROR or YYBACKUP, subsequent parser actions might lead
to an incorrect destructor call or verbose syntax error message
before the lookahead is translated. */
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);
YYPOPSTACK (yylen);
yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
@@ -6235,50 +6410,44 @@ yyreduce:
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
+ yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (yyscanner, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
{
+ yypcontext_t yyctx
+ = {yyssp, yytoken};
char const *yymsgp = YY_("syntax error");
int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
+ yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
if (yysyntax_error_status == 0)
yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
+ else if (yysyntax_error_status == -1)
{
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
+ yymsg = YY_CAST (char *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc)));
+ if (yymsg)
{
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
+ yysyntax_error_status
+ = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
+ yymsgp = yymsg;
}
else
{
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = YYENOMEM;
}
}
yyerror (yyscanner, yymsgp);
- if (yysyntax_error_status == 2)
+ if (yysyntax_error_status == YYENOMEM)
goto yyexhaustedlab;
}
-# undef YYSYNTAX_ERROR
-#endif
}
-
-
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
@@ -6298,7 +6467,6 @@ yyerrlab:
}
}
-#if 0
/* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -6326,16 +6494,16 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
-#endif
yyerrstatus = 3; /* Each real token shifted decrements this. */
+ /* Pop stack until we find a state that shifts the error token. */
for (;;)
{
yyn = yypact[yystate];
if (!yypact_value_is_default (yyn))
{
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ yyn += YYSYMBOL_YYerror;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
{
yyn = yytable[yyn];
if (0 < yyn)
@@ -6349,7 +6517,7 @@ yyerrlab1:
yydestruct ("Error: popping",
- yystos[yystate], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (yystate), yyvsp, yyscanner);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
@@ -6361,7 +6529,7 @@ yyerrlab1:
/* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
yystate = yyn;
goto yynewstate;
@@ -6383,20 +6551,20 @@ yyabortlab:
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if 1
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
yyerror (yyscanner, YY_("memory exhausted"));
yyresult = 2;
- /* Fall through. */
+ goto yyreturn;
#endif
-/*-----------------------------------------------------.
-| yyreturn -- parsing is finished, return the result. |
-`-----------------------------------------------------*/
+/*-------------------------------------------------------.
+| yyreturn -- parsing is finished, clean up and return. |
+`-------------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -6413,20 +6581,19 @@ yyreturn:
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yyscanner);
YYPOPSTACK (1);
}
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
-#if YYERROR_VERBOSE
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
-#endif
return yyresult;
}
-#line 3210 "cmDependsJavaParser.y"
+
+#line 3208 "cmDependsJavaParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y
index d15cffc56..a76ec5064 100644
--- a/Source/LexerParser/cmDependsJavaParser.y
+++ b/Source/LexerParser/cmDependsJavaParser.y
@@ -7,15 +7,13 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
-
-Modify cmDependsJavaParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+ bison --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
*/
#include "cmConfigure.h" // IWYU pragma: keep
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <string>
@@ -25,7 +23,6 @@ Modify cmDependsJavaParser.cxx:
/*-------------------------------------------------------------------------*/
#include "cmDependsJavaParserHelper.h" /* Interface to parser object. */
#include "cmDependsJavaLexer.h" /* Interface to lexer object. */
-#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL. */
/* Forward declare the lexer entry point. */
YY_DECL;
@@ -46,6 +43,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
#endif
%}
diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h
index e0dfa01cc..4ae55fa3b 100644
--- a/Source/LexerParser/cmDependsJavaParserTokens.h
+++ b/Source/LexerParser/cmDependsJavaParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -31,8 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
@@ -44,220 +45,121 @@
extern int cmDependsJava_yydebug;
#endif
-/* Token type. */
+/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
- jp_ABSTRACT = 258,
- jp_ASSERT = 259,
- jp_BOOLEAN_TYPE = 260,
- jp_BREAK = 261,
- jp_BYTE_TYPE = 262,
- jp_CASE = 263,
- jp_CATCH = 264,
- jp_CHAR_TYPE = 265,
- jp_CLASS = 266,
- jp_CONTINUE = 267,
- jp_DEFAULT = 268,
- jp_DO = 269,
- jp_DOUBLE_TYPE = 270,
- jp_ELSE = 271,
- jp_EXTENDS = 272,
- jp_FINAL = 273,
- jp_FINALLY = 274,
- jp_FLOAT_TYPE = 275,
- jp_FOR = 276,
- jp_IF = 277,
- jp_IMPLEMENTS = 278,
- jp_IMPORT = 279,
- jp_INSTANCEOF = 280,
- jp_INT_TYPE = 281,
- jp_INTERFACE = 282,
- jp_LONG_TYPE = 283,
- jp_NATIVE = 284,
- jp_NEW = 285,
- jp_PACKAGE = 286,
- jp_PRIVATE = 287,
- jp_PROTECTED = 288,
- jp_PUBLIC = 289,
- jp_RETURN = 290,
- jp_SHORT_TYPE = 291,
- jp_STATIC = 292,
- jp_STRICTFP = 293,
- jp_SUPER = 294,
- jp_SWITCH = 295,
- jp_SYNCHRONIZED = 296,
- jp_THIS = 297,
- jp_THROW = 298,
- jp_THROWS = 299,
- jp_TRANSIENT = 300,
- jp_TRY = 301,
- jp_VOID = 302,
- jp_VOLATILE = 303,
- jp_WHILE = 304,
- jp_BOOLEANLITERAL = 305,
- jp_CHARACTERLITERAL = 306,
- jp_DECIMALINTEGERLITERAL = 307,
- jp_FLOATINGPOINTLITERAL = 308,
- jp_HEXINTEGERLITERAL = 309,
- jp_NULLLITERAL = 310,
- jp_STRINGLITERAL = 311,
- jp_NAME = 312,
- jp_AND = 313,
- jp_ANDAND = 314,
- jp_ANDEQUALS = 315,
- jp_BRACKETEND = 316,
- jp_BRACKETSTART = 317,
- jp_CARROT = 318,
- jp_CARROTEQUALS = 319,
- jp_COLON = 320,
- jp_COMMA = 321,
- jp_CURLYEND = 322,
- jp_CURLYSTART = 323,
- jp_DIVIDE = 324,
- jp_DIVIDEEQUALS = 325,
- jp_DOLLAR = 326,
- jp_DOT = 327,
- jp_EQUALS = 328,
- jp_EQUALSEQUALS = 329,
- jp_EXCLAMATION = 330,
- jp_EXCLAMATIONEQUALS = 331,
- jp_GREATER = 332,
- jp_GTEQUALS = 333,
- jp_GTGT = 334,
- jp_GTGTEQUALS = 335,
- jp_GTGTGT = 336,
- jp_GTGTGTEQUALS = 337,
- jp_LESLESEQUALS = 338,
- jp_LESSTHAN = 339,
- jp_LTEQUALS = 340,
- jp_LTLT = 341,
- jp_MINUS = 342,
- jp_MINUSEQUALS = 343,
- jp_MINUSMINUS = 344,
- jp_PAREEND = 345,
- jp_PARESTART = 346,
- jp_PERCENT = 347,
- jp_PERCENTEQUALS = 348,
- jp_PIPE = 349,
- jp_PIPEEQUALS = 350,
- jp_PIPEPIPE = 351,
- jp_PLUS = 352,
- jp_PLUSEQUALS = 353,
- jp_PLUSPLUS = 354,
- jp_QUESTION = 355,
- jp_SEMICOL = 356,
- jp_TILDE = 357,
- jp_TIMES = 358,
- jp_TIMESEQUALS = 359,
- jp_ERROR = 360
+ YYEMPTY = -2,
+ YYEOF = 0, /* "end of file" */
+ YYerror = 256, /* error */
+ YYUNDEF = 257, /* "invalid token" */
+ jp_ABSTRACT = 258, /* jp_ABSTRACT */
+ jp_ASSERT = 259, /* jp_ASSERT */
+ jp_BOOLEAN_TYPE = 260, /* jp_BOOLEAN_TYPE */
+ jp_BREAK = 261, /* jp_BREAK */
+ jp_BYTE_TYPE = 262, /* jp_BYTE_TYPE */
+ jp_CASE = 263, /* jp_CASE */
+ jp_CATCH = 264, /* jp_CATCH */
+ jp_CHAR_TYPE = 265, /* jp_CHAR_TYPE */
+ jp_CLASS = 266, /* jp_CLASS */
+ jp_CONTINUE = 267, /* jp_CONTINUE */
+ jp_DEFAULT = 268, /* jp_DEFAULT */
+ jp_DO = 269, /* jp_DO */
+ jp_DOUBLE_TYPE = 270, /* jp_DOUBLE_TYPE */
+ jp_ELSE = 271, /* jp_ELSE */
+ jp_EXTENDS = 272, /* jp_EXTENDS */
+ jp_FINAL = 273, /* jp_FINAL */
+ jp_FINALLY = 274, /* jp_FINALLY */
+ jp_FLOAT_TYPE = 275, /* jp_FLOAT_TYPE */
+ jp_FOR = 276, /* jp_FOR */
+ jp_IF = 277, /* jp_IF */
+ jp_IMPLEMENTS = 278, /* jp_IMPLEMENTS */
+ jp_IMPORT = 279, /* jp_IMPORT */
+ jp_INSTANCEOF = 280, /* jp_INSTANCEOF */
+ jp_INT_TYPE = 281, /* jp_INT_TYPE */
+ jp_INTERFACE = 282, /* jp_INTERFACE */
+ jp_LONG_TYPE = 283, /* jp_LONG_TYPE */
+ jp_NATIVE = 284, /* jp_NATIVE */
+ jp_NEW = 285, /* jp_NEW */
+ jp_PACKAGE = 286, /* jp_PACKAGE */
+ jp_PRIVATE = 287, /* jp_PRIVATE */
+ jp_PROTECTED = 288, /* jp_PROTECTED */
+ jp_PUBLIC = 289, /* jp_PUBLIC */
+ jp_RETURN = 290, /* jp_RETURN */
+ jp_SHORT_TYPE = 291, /* jp_SHORT_TYPE */
+ jp_STATIC = 292, /* jp_STATIC */
+ jp_STRICTFP = 293, /* jp_STRICTFP */
+ jp_SUPER = 294, /* jp_SUPER */
+ jp_SWITCH = 295, /* jp_SWITCH */
+ jp_SYNCHRONIZED = 296, /* jp_SYNCHRONIZED */
+ jp_THIS = 297, /* jp_THIS */
+ jp_THROW = 298, /* jp_THROW */
+ jp_THROWS = 299, /* jp_THROWS */
+ jp_TRANSIENT = 300, /* jp_TRANSIENT */
+ jp_TRY = 301, /* jp_TRY */
+ jp_VOID = 302, /* jp_VOID */
+ jp_VOLATILE = 303, /* jp_VOLATILE */
+ jp_WHILE = 304, /* jp_WHILE */
+ jp_BOOLEANLITERAL = 305, /* jp_BOOLEANLITERAL */
+ jp_CHARACTERLITERAL = 306, /* jp_CHARACTERLITERAL */
+ jp_DECIMALINTEGERLITERAL = 307, /* jp_DECIMALINTEGERLITERAL */
+ jp_FLOATINGPOINTLITERAL = 308, /* jp_FLOATINGPOINTLITERAL */
+ jp_HEXINTEGERLITERAL = 309, /* jp_HEXINTEGERLITERAL */
+ jp_NULLLITERAL = 310, /* jp_NULLLITERAL */
+ jp_STRINGLITERAL = 311, /* jp_STRINGLITERAL */
+ jp_NAME = 312, /* jp_NAME */
+ jp_AND = 313, /* jp_AND */
+ jp_ANDAND = 314, /* jp_ANDAND */
+ jp_ANDEQUALS = 315, /* jp_ANDEQUALS */
+ jp_BRACKETEND = 316, /* jp_BRACKETEND */
+ jp_BRACKETSTART = 317, /* jp_BRACKETSTART */
+ jp_CARROT = 318, /* jp_CARROT */
+ jp_CARROTEQUALS = 319, /* jp_CARROTEQUALS */
+ jp_COLON = 320, /* jp_COLON */
+ jp_COMMA = 321, /* jp_COMMA */
+ jp_CURLYEND = 322, /* jp_CURLYEND */
+ jp_CURLYSTART = 323, /* jp_CURLYSTART */
+ jp_DIVIDE = 324, /* jp_DIVIDE */
+ jp_DIVIDEEQUALS = 325, /* jp_DIVIDEEQUALS */
+ jp_DOLLAR = 326, /* jp_DOLLAR */
+ jp_DOT = 327, /* jp_DOT */
+ jp_EQUALS = 328, /* jp_EQUALS */
+ jp_EQUALSEQUALS = 329, /* jp_EQUALSEQUALS */
+ jp_EXCLAMATION = 330, /* jp_EXCLAMATION */
+ jp_EXCLAMATIONEQUALS = 331, /* jp_EXCLAMATIONEQUALS */
+ jp_GREATER = 332, /* jp_GREATER */
+ jp_GTEQUALS = 333, /* jp_GTEQUALS */
+ jp_GTGT = 334, /* jp_GTGT */
+ jp_GTGTEQUALS = 335, /* jp_GTGTEQUALS */
+ jp_GTGTGT = 336, /* jp_GTGTGT */
+ jp_GTGTGTEQUALS = 337, /* jp_GTGTGTEQUALS */
+ jp_LESLESEQUALS = 338, /* jp_LESLESEQUALS */
+ jp_LESSTHAN = 339, /* jp_LESSTHAN */
+ jp_LTEQUALS = 340, /* jp_LTEQUALS */
+ jp_LTLT = 341, /* jp_LTLT */
+ jp_MINUS = 342, /* jp_MINUS */
+ jp_MINUSEQUALS = 343, /* jp_MINUSEQUALS */
+ jp_MINUSMINUS = 344, /* jp_MINUSMINUS */
+ jp_PAREEND = 345, /* jp_PAREEND */
+ jp_PARESTART = 346, /* jp_PARESTART */
+ jp_PERCENT = 347, /* jp_PERCENT */
+ jp_PERCENTEQUALS = 348, /* jp_PERCENTEQUALS */
+ jp_PIPE = 349, /* jp_PIPE */
+ jp_PIPEEQUALS = 350, /* jp_PIPEEQUALS */
+ jp_PIPEPIPE = 351, /* jp_PIPEPIPE */
+ jp_PLUS = 352, /* jp_PLUS */
+ jp_PLUSEQUALS = 353, /* jp_PLUSEQUALS */
+ jp_PLUSPLUS = 354, /* jp_PLUSPLUS */
+ jp_QUESTION = 355, /* jp_QUESTION */
+ jp_SEMICOL = 356, /* jp_SEMICOL */
+ jp_TILDE = 357, /* jp_TILDE */
+ jp_TIMES = 358, /* jp_TIMES */
+ jp_TIMESEQUALS = 359, /* jp_TIMESEQUALS */
+ jp_ERROR = 360 /* jp_ERROR */
};
+ typedef enum yytokentype yytoken_kind_t;
#endif
-/* Tokens. */
-#define jp_ABSTRACT 258
-#define jp_ASSERT 259
-#define jp_BOOLEAN_TYPE 260
-#define jp_BREAK 261
-#define jp_BYTE_TYPE 262
-#define jp_CASE 263
-#define jp_CATCH 264
-#define jp_CHAR_TYPE 265
-#define jp_CLASS 266
-#define jp_CONTINUE 267
-#define jp_DEFAULT 268
-#define jp_DO 269
-#define jp_DOUBLE_TYPE 270
-#define jp_ELSE 271
-#define jp_EXTENDS 272
-#define jp_FINAL 273
-#define jp_FINALLY 274
-#define jp_FLOAT_TYPE 275
-#define jp_FOR 276
-#define jp_IF 277
-#define jp_IMPLEMENTS 278
-#define jp_IMPORT 279
-#define jp_INSTANCEOF 280
-#define jp_INT_TYPE 281
-#define jp_INTERFACE 282
-#define jp_LONG_TYPE 283
-#define jp_NATIVE 284
-#define jp_NEW 285
-#define jp_PACKAGE 286
-#define jp_PRIVATE 287
-#define jp_PROTECTED 288
-#define jp_PUBLIC 289
-#define jp_RETURN 290
-#define jp_SHORT_TYPE 291
-#define jp_STATIC 292
-#define jp_STRICTFP 293
-#define jp_SUPER 294
-#define jp_SWITCH 295
-#define jp_SYNCHRONIZED 296
-#define jp_THIS 297
-#define jp_THROW 298
-#define jp_THROWS 299
-#define jp_TRANSIENT 300
-#define jp_TRY 301
-#define jp_VOID 302
-#define jp_VOLATILE 303
-#define jp_WHILE 304
-#define jp_BOOLEANLITERAL 305
-#define jp_CHARACTERLITERAL 306
-#define jp_DECIMALINTEGERLITERAL 307
-#define jp_FLOATINGPOINTLITERAL 308
-#define jp_HEXINTEGERLITERAL 309
-#define jp_NULLLITERAL 310
-#define jp_STRINGLITERAL 311
-#define jp_NAME 312
-#define jp_AND 313
-#define jp_ANDAND 314
-#define jp_ANDEQUALS 315
-#define jp_BRACKETEND 316
-#define jp_BRACKETSTART 317
-#define jp_CARROT 318
-#define jp_CARROTEQUALS 319
-#define jp_COLON 320
-#define jp_COMMA 321
-#define jp_CURLYEND 322
-#define jp_CURLYSTART 323
-#define jp_DIVIDE 324
-#define jp_DIVIDEEQUALS 325
-#define jp_DOLLAR 326
-#define jp_DOT 327
-#define jp_EQUALS 328
-#define jp_EQUALSEQUALS 329
-#define jp_EXCLAMATION 330
-#define jp_EXCLAMATIONEQUALS 331
-#define jp_GREATER 332
-#define jp_GTEQUALS 333
-#define jp_GTGT 334
-#define jp_GTGTEQUALS 335
-#define jp_GTGTGT 336
-#define jp_GTGTGTEQUALS 337
-#define jp_LESLESEQUALS 338
-#define jp_LESSTHAN 339
-#define jp_LTEQUALS 340
-#define jp_LTLT 341
-#define jp_MINUS 342
-#define jp_MINUSEQUALS 343
-#define jp_MINUSMINUS 344
-#define jp_PAREEND 345
-#define jp_PARESTART 346
-#define jp_PERCENT 347
-#define jp_PERCENTEQUALS 348
-#define jp_PIPE 349
-#define jp_PIPEEQUALS 350
-#define jp_PIPEPIPE 351
-#define jp_PLUS 352
-#define jp_PLUSEQUALS 353
-#define jp_PLUSPLUS 354
-#define jp_QUESTION 355
-#define jp_SEMICOL 356
-#define jp_TILDE 357
-#define jp_TIMES 358
-#define jp_TIMESEQUALS 359
-#define jp_ERROR 360
/* Value type. */
diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx
index 562b35bf7..b747d8b13 100644
--- a/Source/LexerParser/cmExprParser.cxx
+++ b/Source/LexerParser/cmExprParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -34,6 +34,10 @@
/* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
+
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros.
@@ -41,14 +45,11 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
-
-/* Identify Bison output. */
-#define YYBISON 1
+/* Identify Bison output, and Bison version. */
+#define YYBISON 30704
-/* Bison version. */
-#define YYBISON_VERSION "3.4.2"
+/* Bison version string. */
+#define YYBISON_VERSION "3.7.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -70,7 +71,6 @@
#define yydebug cmExpr_yydebug
#define yynerrs cmExpr_yynerrs
-
/* First part of user prologue. */
#line 1 "cmExprParser.y"
@@ -82,15 +82,13 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
-
-Modify cmExprParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+ bison --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
*/
#include "cmConfigure.h" // IWYU pragma: keep
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
@@ -114,10 +112,25 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+#endif
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wused-but-marked-unused")
+# pragma clang diagnostic ignored "-Wused-but-marked-unused"
+# endif
#endif
-#line 120 "cmExprParser.cxx"
+#line 124 "cmExprParser.cxx"
+# ifndef YY_CAST
+# ifdef __cplusplus
+# define YY_CAST(Type, Val) static_cast<Type> (Val)
+# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
+# else
+# define YY_CAST(Type, Val) ((Type) (Val))
+# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+# endif
+# endif
# ifndef YY_NULLPTR
# if defined __cplusplus
# if 201103L <= __cplusplus
@@ -130,99 +143,117 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
# endif
# endif
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* Use api.header.include to #include this header
- instead of duplicating it here. */
-#ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
-# define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
-/* Debug traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int cmExpr_yydebug;
-#endif
-
-/* Token type. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- enum yytokentype
- {
- exp_PLUS = 258,
- exp_MINUS = 259,
- exp_TIMES = 260,
- exp_DIVIDE = 261,
- exp_MOD = 262,
- exp_SHIFTLEFT = 263,
- exp_SHIFTRIGHT = 264,
- exp_OPENPARENT = 265,
- exp_CLOSEPARENT = 266,
- exp_OR = 267,
- exp_AND = 268,
- exp_XOR = 269,
- exp_NOT = 270,
- exp_NUMBER = 271
- };
-#endif
-/* Tokens. */
-#define exp_PLUS 258
-#define exp_MINUS 259
-#define exp_TIMES 260
-#define exp_DIVIDE 261
-#define exp_MOD 262
-#define exp_SHIFTLEFT 263
-#define exp_SHIFTRIGHT 264
-#define exp_OPENPARENT 265
-#define exp_CLOSEPARENT 266
-#define exp_OR 267
-#define exp_AND 268
-#define exp_XOR 269
-#define exp_NOT 270
-#define exp_NUMBER 271
+#include "cmExprParserTokens.h"
+/* Symbol kind. */
+enum yysymbol_kind_t
+{
+ YYSYMBOL_YYEMPTY = -2,
+ YYSYMBOL_YYEOF = 0, /* "end of file" */
+ YYSYMBOL_YYerror = 1, /* error */
+ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
+ YYSYMBOL_exp_PLUS = 3, /* exp_PLUS */
+ YYSYMBOL_exp_MINUS = 4, /* exp_MINUS */
+ YYSYMBOL_exp_TIMES = 5, /* exp_TIMES */
+ YYSYMBOL_exp_DIVIDE = 6, /* exp_DIVIDE */
+ YYSYMBOL_exp_MOD = 7, /* exp_MOD */
+ YYSYMBOL_exp_SHIFTLEFT = 8, /* exp_SHIFTLEFT */
+ YYSYMBOL_exp_SHIFTRIGHT = 9, /* exp_SHIFTRIGHT */
+ YYSYMBOL_exp_OPENPARENT = 10, /* exp_OPENPARENT */
+ YYSYMBOL_exp_CLOSEPARENT = 11, /* exp_CLOSEPARENT */
+ YYSYMBOL_exp_OR = 12, /* exp_OR */
+ YYSYMBOL_exp_AND = 13, /* exp_AND */
+ YYSYMBOL_exp_XOR = 14, /* exp_XOR */
+ YYSYMBOL_exp_NOT = 15, /* exp_NOT */
+ YYSYMBOL_exp_NUMBER = 16, /* exp_NUMBER */
+ YYSYMBOL_YYACCEPT = 17, /* $accept */
+ YYSYMBOL_start = 18, /* start */
+ YYSYMBOL_exp = 19, /* exp */
+ YYSYMBOL_bitwiseor = 20, /* bitwiseor */
+ YYSYMBOL_bitwisexor = 21, /* bitwisexor */
+ YYSYMBOL_bitwiseand = 22, /* bitwiseand */
+ YYSYMBOL_shift = 23, /* shift */
+ YYSYMBOL_term = 24, /* term */
+ YYSYMBOL_unary = 25, /* unary */
+ YYSYMBOL_factor = 26 /* factor */
+};
+typedef enum yysymbol_kind_t yysymbol_kind_t;
-/* Value type. */
-int cmExpr_yyparse (yyscan_t yyscanner);
+#ifdef short
+# undef short
+#endif
-#endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED */
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+ <limits.h> and (if available) <stdint.h> are included
+ so that the code can choose integer types of a good width. */
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_STDINT_H
+# endif
+#endif
+/* Narrow types that promote to a signed type and that can represent a
+ signed or unsigned integer of at least N bits. In tables they can
+ save space and decrease cache pressure. Promoting to a signed type
+ helps avoid bugs in integer arithmetic. */
-#ifdef short
-# undef short
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
+#else
+typedef signed char yytype_int8;
#endif
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
#else
-typedef unsigned char yytype_uint8;
+typedef short yytype_int16;
#endif
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
+#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 \
+ && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
#else
-typedef signed char yytype_int8;
+typedef short yytype_uint8;
#endif
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
#endif
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short yytype_int16;
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+# define YYPTRDIFF_T __PTRDIFF_TYPE__
+# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+# ifndef ptrdiff_t
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# endif
+# define YYPTRDIFF_T ptrdiff_t
+# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+# define YYPTRDIFF_T long
+# define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
#endif
#ifndef YYSIZE_T
@@ -230,7 +261,7 @@ typedef short yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -238,7 +269,20 @@ typedef short yytype_int16;
# endif
#endif
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+#define YYSIZE_MAXIMUM \
+ YY_CAST (YYPTRDIFF_T, \
+ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
+ ? YYPTRDIFF_MAXIMUM \
+ : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_int8 yy_state_t;
+
+/* State numbers in computations. */
+typedef int yy_state_fast_t;
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
@@ -252,22 +296,21 @@ typedef short yytype_int16;
# endif
#endif
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__ \
- && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
- || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
-# else
-# define YY_ATTRIBUTE(Spec) /* empty */
-# endif
-#endif
#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define YY_ATTRIBUTE_PURE
+# endif
#endif
#ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+# define YY_ATTRIBUTE_UNUSED
+# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
@@ -279,11 +322,11 @@ typedef short yytype_int16;
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
@@ -296,10 +339,22 @@ typedef short yytype_int16;
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
+#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END \
+ _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
#define YY_ASSERT(E) ((void) (0 && (E)))
-#if ! defined yyoverflow || YYERROR_VERBOSE
+#if 1
/* The parser invokes alloca or malloc; define the necessary symbols. */
@@ -364,8 +419,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
+#endif /* 1 */
#if (! defined yyoverflow \
&& (! defined __cplusplus \
@@ -374,17 +428,17 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss_alloc;
+ yy_state_t yyss_alloc;
YYSTYPE yyvs_alloc;
};
/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
# define YYCOPY_NEEDED 1
@@ -397,11 +451,11 @@ union yyalloc
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
- YYSIZE_T yynewbytes; \
+ YYPTRDIFF_T yynewbytes; \
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
+ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / YYSIZEOF (*yyptr); \
} \
while (0)
@@ -413,12 +467,12 @@ union yyalloc
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
# else
# define YYCOPY(Dst, Src, Count) \
do \
{ \
- YYSIZE_T yyi; \
+ YYPTRDIFF_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
@@ -441,17 +495,20 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 41
-#define YYUNDEFTOK 2
+/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 271
+
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
-#define YYTRANSLATE(YYX) \
- ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+#define YYTRANSLATE(YYX) \
+ (0 <= (YYX) && (YYX) <= YYMAXUTOK \
+ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
+ : YYSYMBOL_YYUNDEF)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */
-static const yytype_uint8 yytranslate[] =
+static const yytype_int8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -487,43 +544,57 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 77, 77, 82, 85, 90, 93, 98, 101, 106,
- 109, 112, 117, 120, 123, 128, 131, 134, 140, 145,
- 148, 151, 154, 159, 162
+ 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
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 1
+/** Accessing symbol of state STATE. */
+#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
+
+#if 1
+/* The user-facing name of the symbol whose (internal) number is
+ YYSYMBOL. No bounds checking. */
+static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
+
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "exp_PLUS", "exp_MINUS", "exp_TIMES",
- "exp_DIVIDE", "exp_MOD", "exp_SHIFTLEFT", "exp_SHIFTRIGHT",
- "exp_OPENPARENT", "exp_CLOSEPARENT", "exp_OR", "exp_AND", "exp_XOR",
- "exp_NOT", "exp_NUMBER", "$accept", "start", "exp", "bitwiseor",
- "bitwisexor", "bitwiseand", "shift", "term", "unary", "factor", YY_NULLPTR
+ "\"end of file\"", "error", "\"invalid token\"", "exp_PLUS",
+ "exp_MINUS", "exp_TIMES", "exp_DIVIDE", "exp_MOD", "exp_SHIFTLEFT",
+ "exp_SHIFTRIGHT", "exp_OPENPARENT", "exp_CLOSEPARENT", "exp_OR",
+ "exp_AND", "exp_XOR", "exp_NOT", "exp_NUMBER", "$accept", "start", "exp",
+ "bitwiseor", "bitwisexor", "bitwiseand", "shift", "term", "unary",
+ "factor", YY_NULLPTR
};
+
+static const char *
+yysymbol_name (yysymbol_kind_t yysymbol)
+{
+ return yytname[yysymbol];
+}
#endif
-# ifdef YYPRINT
+#ifdef YYPRINT
/* YYTOKNUM[NUM] -- (External) token number corresponding to the
(internal) symbol number NUM (which must be that of a token). */
-static const yytype_uint16 yytoknum[] =
+static const yytype_int16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271
};
-# endif
+#endif
-#define YYPACT_NINF -11
+#define YYPACT_NINF (-11)
-#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-11)))
+#define yypact_value_is_default(Yyn) \
+ ((Yyn) == YYPACT_NINF)
-#define YYTABLE_NINF -1
+#define YYTABLE_NINF (-1)
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(Yyn) \
0
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -540,7 +611,7 @@ static const yytype_int8 yypact[] =
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
Performed when YYTABLE does not specify something else to do. Zero
means the default is an error. */
-static const yytype_uint8 yydefact[] =
+static const yytype_int8 yydefact[] =
{
0, 0, 0, 0, 0, 23, 0, 2, 3, 5,
7, 9, 12, 15, 19, 20, 21, 0, 22, 1,
@@ -564,7 +635,7 @@ static const yytype_int8 yydefgoto[] =
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule whose
number is the opposite. If YYTABLE_NINF, syntax error. */
-static const yytype_uint8 yytable[] =
+static const yytype_int8 yytable[] =
{
15, 16, 20, 18, 1, 2, 19, 27, 28, 29,
21, 3, 23, 24, 25, 26, 4, 5, 30, 20,
@@ -582,7 +653,7 @@ static const yytype_int8 yycheck[] =
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
+static const yytype_int8 yystos[] =
{
0, 3, 4, 10, 15, 16, 18, 19, 20, 21,
22, 23, 24, 25, 26, 25, 25, 19, 25, 0,
@@ -592,7 +663,7 @@ static const yytype_uint8 yystos[] =
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
+static const yytype_int8 yyr1[] =
{
0, 17, 18, 19, 19, 20, 20, 21, 21, 22,
22, 22, 23, 23, 23, 24, 24, 24, 24, 25,
@@ -600,7 +671,7 @@ static const yytype_uint8 yyr1[] =
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yyr2[] =
{
0, 2, 1, 1, 3, 1, 3, 1, 3, 1,
3, 3, 1, 3, 3, 1, 3, 3, 3, 1,
@@ -608,10 +679,10 @@ static const yytype_uint8 yyr2[] =
};
+enum { YYENOMEM = -2 };
+
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
@@ -637,10 +708,9 @@ static const yytype_uint8 yyr2[] =
} \
while (0)
-/* Error token number */
-#define YYTERROR 1
-#define YYERRCODE 256
-
+/* Backward compatibility with an undocumented macro.
+ Use YYerror or YYUNDEF. */
+#define YYERRCODE YYUNDEF
/* Enable debugging if requested. */
@@ -658,18 +728,18 @@ do { \
} while (0)
/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+# ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
do { \
if (yydebug) \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
- Type, Value, yyscanner); \
+ Kind, Value, yyscanner); \
YYFPRINTF (stderr, "\n"); \
} \
} while (0)
@@ -680,7 +750,8 @@ do { \
`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
YYUSE (yyoutput);
@@ -688,11 +759,11 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
if (!yyvaluep)
return;
# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
+ if (yykind < YYNTOKENS)
+ YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -702,12 +773,13 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
`---------------------------*/
static void
-yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
YYFPRINTF (yyo, "%s %s (",
- yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+ yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));
- yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ yy_symbol_value_print (yyo, yykind, yyvaluep, yyscanner);
YYFPRINTF (yyo, ")");
}
@@ -717,7 +789,7 @@ yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t
`------------------------------------------------------------------*/
static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -740,21 +812,21 @@ do { \
`------------------------------------------------*/
static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
+ int yyrule, yyscan_t yyscanner)
{
- unsigned long yylno = yyrline[yyrule];
+ int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
- yystos[yyssp[yyi + 1 - yynrhs]],
- &yyvsp[(yyi + 1) - (yynrhs)]
- , yyscanner);
+ YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
+ &yyvsp[(yyi + 1) - (yynrhs)], yyscanner);
YYFPRINTF (stderr, "\n");
}
}
@@ -769,8 +841,8 @@ do { \
multiple parsers can coexist. */
int yydebug;
#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YYDPRINTF(Args) ((void) 0)
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
@@ -793,28 +865,76 @@ int yydebug;
#endif
-#if YYERROR_VERBOSE
+/* Context of a parse error. */
+typedef struct
+{
+ yy_state_t *yyssp;
+ yysymbol_kind_t yytoken;
+} yypcontext_t;
+
+/* Put in YYARG at most YYARGN of the expected tokens given the
+ current YYCTX, and return the number of tokens stored in YYARG. If
+ YYARG is null, return the number of expected tokens (guaranteed to
+ be less than YYNTOKENS). Return YYENOMEM on memory exhaustion.
+ Return 0 if there are more than YYARGN expected tokens, yet fill
+ YYARG up to YYARGN. */
+static int
+yypcontext_expected_tokens (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
+{
+ /* Actual size of YYARG. */
+ int yycount = 0;
+ int yyn = yypact[+*yyctx->yyssp];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (!yyarg)
+ ++yycount;
+ else if (yycount == yyargn)
+ return 0;
+ else
+ yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx);
+ }
+ }
+ if (yyarg && yycount == 0 && 0 < yyargn)
+ yyarg[0] = YYSYMBOL_YYEMPTY;
+ return yycount;
+}
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
+
+
+
+#ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
+# else
/* Return the length of YYSTR. */
-static YYSIZE_T
+static YYPTRDIFF_T
yystrlen (const char *yystr)
{
- YYSIZE_T yylen;
+ YYPTRDIFF_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
continue;
return yylen;
}
-# endif
# endif
+#endif
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
+#ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
static char *
@@ -828,10 +948,10 @@ yystpcpy (char *yydest, const char *yysrc)
return yyd - 1;
}
-# endif
# endif
+#endif
-# ifndef yytnamerr
+#ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
quotes and backslashes, so that it's suitable for yyerror. The
heuristic is that double-quoting is unnecessary unless the string
@@ -839,14 +959,13 @@ yystpcpy (char *yydest, const char *yysrc)
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
-static YYSIZE_T
+static YYPTRDIFF_T
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
- YYSIZE_T yyn = 0;
+ YYPTRDIFF_T yyn = 0;
char const *yyp = yystr;
-
for (;;)
switch (*++yyp)
{
@@ -875,36 +994,20 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ;
}
- if (! yyres)
+ if (yyres)
+ return yystpcpy (yyres, yystr) - yyres;
+ else
return yystrlen (yystr);
-
- return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
-# endif
+#endif
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
+yy_syntax_error_arguments (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULLPTR;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
+ /* Actual size of YYARG. */
int yycount = 0;
-
/* There are many possibilities here to consider:
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
@@ -928,49 +1031,54 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
one exception: it will still contain any token that will not be
accepted due to an error action in a later state.
*/
- if (yytoken != YYEMPTY)
+ if (yyctx->yytoken != YYSYMBOL_YYEMPTY)
{
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- {
- YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
- }
- }
- }
+ int yyn;
+ if (yyarg)
+ yyarg[yycount] = yyctx->yytoken;
+ ++yycount;
+ yyn = yypcontext_expected_tokens (yyctx,
+ yyarg ? yyarg + 1 : yyarg, yyargn - 1);
+ if (yyn == YYENOMEM)
+ return YYENOMEM;
+ else
+ yycount += yyn;
}
+ return yycount;
+}
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
+ const yypcontext_t *yyctx)
+{
+ enum { YYARGS_MAX = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat: reported tokens (one for the "unexpected",
+ one per "expected"). */
+ yysymbol_kind_t yyarg[YYARGS_MAX];
+ /* Cumulated lengths of YYARG. */
+ YYPTRDIFF_T yysize = 0;
+
+ /* Actual size of YYARG. */
+ int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX);
+ if (yycount == YYENOMEM)
+ return YYENOMEM;
switch (yycount)
{
-# define YYCASE_(N, S) \
+#define YYCASE_(N, S) \
case N: \
yyformat = S; \
- break
+ break
default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
@@ -978,15 +1086,23 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
+#undef YYCASE_
}
+ /* Compute error message size. Don't count the "%s"s, but reserve
+ room for the terminator. */
+ yysize = yystrlen (yyformat) - 2 * yycount + 1;
{
- YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
+ int yyi;
+ for (yyi = 0; yyi < yycount; ++yyi)
+ {
+ YYPTRDIFF_T yysize1
+ = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]);
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
+ return YYENOMEM;
+ }
}
if (*yymsg_alloc < yysize)
@@ -995,7 +1111,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
if (! (yysize <= *yymsg_alloc
&& *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
*yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
+ return -1;
}
/* Avoid sprintf, as that infringes on the user's name space.
@@ -1007,40 +1123,43 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
while ((*yyp = *yyformat) != '\0')
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
- yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);
yyformat += 2;
}
else
{
- yyp++;
- yyformat++;
+ ++yyp;
+ ++yyformat;
}
}
return 0;
}
-#endif /* YYERROR_VERBOSE */
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+yydestruct (const char *yymsg,
+ yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
YYUSE (yyvaluep);
YYUSE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
+
+
/*----------.
| yyparse. |
`----------*/
@@ -1048,7 +1167,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner
int
yyparse (yyscan_t yyscanner)
{
-/* The lookahead symbol. */
+/* Lookahead token kind. */
int yychar;
@@ -1059,45 +1178,41 @@ YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
/* Number of syntax errors so far. */
- int yynerrs;
+ int yynerrs = 0;
- int yystate;
+ yy_state_fast_t yystate = 0;
/* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
-
- /* The stacks and their tools:
- 'yyss': related to states.
- 'yyvs': related to semantic values.
+ int yyerrstatus = 0;
- Refer to the stacks through separate pointers, to allow yyoverflow
+ /* Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss;
- yytype_int16 *yyssp;
+ /* Their size. */
+ YYPTRDIFF_T yystacksize = YYINITDEPTH;
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs;
- YYSTYPE *yyvsp;
+ /* The state stack: array, bottom, top. */
+ yy_state_t yyssa[YYINITDEPTH];
+ yy_state_t *yyss = yyssa;
+ yy_state_t *yyssp = yyss;
- YYSIZE_T yystacksize;
+ /* The semantic value stack: array, bottom, top. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp = yyvs;
int yyn;
+ /* The return value of yyparse. */
int yyresult;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
+ /* Lookahead symbol kind. */
+ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
-#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
+ YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
@@ -1105,15 +1220,8 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;
- yystacksize = YYINITDEPTH;
-
YYDPRINTF ((stderr, "Starting parse\n"));
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
@@ -1128,12 +1236,15 @@ yynewstate:
/*--------------------------------------------------------------------.
-| yynewstate -- set current state (the top of the stack) to yystate. |
+| yysetstate -- set current state (the top of the stack) to yystate. |
`--------------------------------------------------------------------*/
yysetstate:
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
- *yyssp = (yytype_int16) yystate;
+ YY_IGNORE_USELESS_CAST_BEGIN
+ *yyssp = YY_CAST (yy_state_t, yystate);
+ YY_IGNORE_USELESS_CAST_END
+ YY_STACK_PRINT (yyss, yyssp);
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
@@ -1141,23 +1252,23 @@ yysetstate:
#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
+ YYPTRDIFF_T yysize = yyssp - yyss + 1;
# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
+ yy_state_t *yyss1 = yyss;
YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
+ &yyss1, yysize * YYSIZEOF (*yyssp),
+ &yyvs1, yysize * YYSIZEOF (*yyvsp),
&yystacksize);
yyss = yyss1;
yyvs = yyvs1;
@@ -1171,14 +1282,15 @@ yysetstate:
yystacksize = YYMAXDEPTH;
{
- yytype_int16 *yyss1 = yyss;
+ yy_state_t *yyss1 = yyss;
union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ YY_CAST (union yyalloc *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
@@ -1187,8 +1299,10 @@ yysetstate:
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long) yystacksize));
+ YY_IGNORE_USELESS_CAST_BEGIN
+ YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+ YY_CAST (long, yystacksize)));
+ YY_IGNORE_USELESS_CAST_END
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
@@ -1215,18 +1329,29 @@ yybackup:
/* Not known => get a lookahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
if (yychar == YYEMPTY)
{
- YYDPRINTF ((stderr, "Reading a token: "));
+ YYDPRINTF ((stderr, "Reading a token\n"));
yychar = yylex (&yylval, yyscanner);
}
if (yychar <= YYEOF)
{
- yychar = yytoken = YYEOF;
+ yychar = YYEOF;
+ yytoken = YYSYMBOL_YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n"));
}
+ else if (yychar == YYerror)
+ {
+ /* The scanner already issued an error message, process directly
+ to error recovery. But do not keep the error token as
+ lookahead, it is too special and may lead us to an endless
+ loop in error recovery. */
+ yychar = YYUNDEF;
+ yytoken = YYSYMBOL_YYerror;
+ goto yyerrlab1;
+ }
else
{
yytoken = YYTRANSLATE (yychar);
@@ -1254,14 +1379,13 @@ yybackup:
/* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token. */
- yychar = YYEMPTY;
-
yystate = yyn;
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
goto yynewstate;
@@ -1296,195 +1420,195 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 2:
-#line 77 "cmExprParser.y"
- {
+ case 2: /* start: exp */
+#line 81 "cmExprParser.y"
+ {
cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
}
-#line 1305 "cmExprParser.cxx"
+#line 1429 "cmExprParser.cxx"
break;
- case 3:
-#line 82 "cmExprParser.y"
- {
+ case 3: /* exp: bitwiseor */
+#line 86 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1313 "cmExprParser.cxx"
+#line 1437 "cmExprParser.cxx"
break;
- case 4:
-#line 85 "cmExprParser.y"
- {
+ case 4: /* exp: exp exp_OR bitwiseor */
+#line 89 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
}
-#line 1321 "cmExprParser.cxx"
+#line 1445 "cmExprParser.cxx"
break;
- case 5:
-#line 90 "cmExprParser.y"
- {
+ case 5: /* bitwiseor: bitwisexor */
+#line 94 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1329 "cmExprParser.cxx"
+#line 1453 "cmExprParser.cxx"
break;
- case 6:
-#line 93 "cmExprParser.y"
- {
+ case 6: /* bitwiseor: bitwiseor exp_XOR bitwisexor */
+#line 97 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
}
-#line 1337 "cmExprParser.cxx"
+#line 1461 "cmExprParser.cxx"
break;
- case 7:
-#line 98 "cmExprParser.y"
- {
+ case 7: /* bitwisexor: bitwiseand */
+#line 102 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1345 "cmExprParser.cxx"
+#line 1469 "cmExprParser.cxx"
break;
- case 8:
-#line 101 "cmExprParser.y"
- {
+ case 8: /* bitwisexor: bitwisexor exp_AND bitwiseand */
+#line 105 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
}
-#line 1353 "cmExprParser.cxx"
+#line 1477 "cmExprParser.cxx"
break;
- case 9:
-#line 106 "cmExprParser.y"
- {
+ case 9: /* bitwiseand: shift */
+#line 110 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1361 "cmExprParser.cxx"
+#line 1485 "cmExprParser.cxx"
break;
- case 10:
-#line 109 "cmExprParser.y"
- {
+ case 10: /* bitwiseand: bitwiseand exp_SHIFTLEFT shift */
+#line 113 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
}
-#line 1369 "cmExprParser.cxx"
+#line 1493 "cmExprParser.cxx"
break;
- case 11:
-#line 112 "cmExprParser.y"
- {
+ case 11: /* bitwiseand: bitwiseand exp_SHIFTRIGHT shift */
+#line 116 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
}
-#line 1377 "cmExprParser.cxx"
+#line 1501 "cmExprParser.cxx"
break;
- case 12:
-#line 117 "cmExprParser.y"
- {
+ case 12: /* shift: term */
+#line 121 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1385 "cmExprParser.cxx"
+#line 1509 "cmExprParser.cxx"
break;
- case 13:
-#line 120 "cmExprParser.y"
- {
+ case 13: /* shift: shift exp_PLUS term */
+#line 124 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
}
-#line 1393 "cmExprParser.cxx"
+#line 1517 "cmExprParser.cxx"
break;
- case 14:
-#line 123 "cmExprParser.y"
- {
+ case 14: /* shift: shift exp_MINUS term */
+#line 127 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
}
-#line 1401 "cmExprParser.cxx"
+#line 1525 "cmExprParser.cxx"
break;
- case 15:
-#line 128 "cmExprParser.y"
- {
+ case 15: /* term: unary */
+#line 132 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1409 "cmExprParser.cxx"
+#line 1533 "cmExprParser.cxx"
break;
- case 16:
-#line 131 "cmExprParser.y"
- {
+ case 16: /* term: term exp_TIMES unary */
+#line 135 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
}
-#line 1417 "cmExprParser.cxx"
+#line 1541 "cmExprParser.cxx"
break;
- case 17:
-#line 134 "cmExprParser.y"
- {
+ case 17: /* term: term exp_DIVIDE unary */
+#line 138 "cmExprParser.y"
+ {
if (yyvsp[0].Number == 0) {
throw std::overflow_error("divide by zero");
}
(yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
}
-#line 1428 "cmExprParser.cxx"
+#line 1552 "cmExprParser.cxx"
break;
- case 18:
-#line 140 "cmExprParser.y"
- {
+ case 18: /* term: term exp_MOD unary */
+#line 144 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
}
-#line 1436 "cmExprParser.cxx"
+#line 1560 "cmExprParser.cxx"
break;
- case 19:
-#line 145 "cmExprParser.y"
- {
+ case 19: /* unary: factor */
+#line 149 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1444 "cmExprParser.cxx"
+#line 1568 "cmExprParser.cxx"
break;
- case 20:
-#line 148 "cmExprParser.y"
- {
+ case 20: /* unary: exp_PLUS unary */
+#line 152 "cmExprParser.y"
+ {
(yyval.Number) = + (yyvsp[0].Number);
}
-#line 1452 "cmExprParser.cxx"
+#line 1576 "cmExprParser.cxx"
break;
- case 21:
-#line 151 "cmExprParser.y"
- {
+ case 21: /* unary: exp_MINUS unary */
+#line 155 "cmExprParser.y"
+ {
(yyval.Number) = - (yyvsp[0].Number);
}
-#line 1460 "cmExprParser.cxx"
+#line 1584 "cmExprParser.cxx"
break;
- case 22:
-#line 154 "cmExprParser.y"
- {
+ case 22: /* unary: exp_NOT unary */
+#line 158 "cmExprParser.y"
+ {
(yyval.Number) = ~ (yyvsp[0].Number);
}
-#line 1468 "cmExprParser.cxx"
+#line 1592 "cmExprParser.cxx"
break;
- case 23:
-#line 159 "cmExprParser.y"
- {
+ case 23: /* factor: exp_NUMBER */
+#line 163 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1476 "cmExprParser.cxx"
+#line 1600 "cmExprParser.cxx"
break;
- case 24:
-#line 162 "cmExprParser.y"
- {
+ case 24: /* factor: exp_OPENPARENT exp exp_CLOSEPARENT */
+#line 166 "cmExprParser.y"
+ {
(yyval.Number) = (yyvsp[-1].Number);
}
-#line 1484 "cmExprParser.cxx"
+#line 1608 "cmExprParser.cxx"
break;
-#line 1488 "cmExprParser.cxx"
+#line 1612 "cmExprParser.cxx"
default: break;
}
@@ -1499,11 +1623,10 @@ yyreduce:
case of YYERROR or YYBACKUP, subsequent parser actions might lead
to an incorrect destructor call or verbose syntax error message
before the lookahead is translated. */
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);
YYPOPSTACK (yylen);
yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
@@ -1527,50 +1650,44 @@ yyreduce:
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
+ yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (yyscanner, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
{
+ yypcontext_t yyctx
+ = {yyssp, yytoken};
char const *yymsgp = YY_("syntax error");
int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
+ yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
if (yysyntax_error_status == 0)
yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
+ else if (yysyntax_error_status == -1)
{
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
+ yymsg = YY_CAST (char *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc)));
+ if (yymsg)
{
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
+ yysyntax_error_status
+ = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
+ yymsgp = yymsg;
}
else
{
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = YYENOMEM;
}
}
yyerror (yyscanner, yymsgp);
- if (yysyntax_error_status == 2)
+ if (yysyntax_error_status == YYENOMEM)
goto yyexhaustedlab;
}
-# undef YYSYNTAX_ERROR
-#endif
}
-
-
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
@@ -1590,7 +1707,6 @@ yyerrlab:
}
}
-#if 0
/* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -1618,16 +1734,16 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
-#endif
yyerrstatus = 3; /* Each real token shifted decrements this. */
+ /* Pop stack until we find a state that shifts the error token. */
for (;;)
{
yyn = yypact[yystate];
if (!yypact_value_is_default (yyn))
{
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ yyn += YYSYMBOL_YYerror;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
{
yyn = yytable[yyn];
if (0 < yyn)
@@ -1641,7 +1757,7 @@ yyerrlab1:
yydestruct ("Error: popping",
- yystos[yystate], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (yystate), yyvsp, yyscanner);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
@@ -1653,7 +1769,7 @@ yyerrlab1:
/* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
yystate = yyn;
goto yynewstate;
@@ -1675,20 +1791,20 @@ yyabortlab:
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if 1
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
yyerror (yyscanner, YY_("memory exhausted"));
yyresult = 2;
- /* Fall through. */
+ goto yyreturn;
#endif
-/*-----------------------------------------------------.
-| yyreturn -- parsing is finished, return the result. |
-`-----------------------------------------------------*/
+/*-------------------------------------------------------.
+| yyreturn -- parsing is finished, clean up and return. |
+`-------------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -1705,20 +1821,19 @@ yyreturn:
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yyscanner);
YYPOPSTACK (1);
}
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
-#if YYERROR_VERBOSE
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
-#endif
return yyresult;
}
-#line 167 "cmExprParser.y"
+
+#line 171 "cmExprParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y
index 7ae21188e..b49f48212 100644
--- a/Source/LexerParser/cmExprParser.y
+++ b/Source/LexerParser/cmExprParser.y
@@ -7,15 +7,13 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
-
-Modify cmExprParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+ bison --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
*/
#include "cmConfigure.h" // IWYU pragma: keep
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
@@ -39,6 +37,12 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+#endif
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wused-but-marked-unused")
+# pragma clang diagnostic ignored "-Wused-but-marked-unused"
+# endif
#endif
%}
diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h
index e30a83257..2eb1fe928 100644
--- a/Source/LexerParser/cmExprParserTokens.h
+++ b/Source/LexerParser/cmExprParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -31,8 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
#ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
# define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
@@ -44,42 +45,32 @@
extern int cmExpr_yydebug;
#endif
-/* Token type. */
+/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
- exp_PLUS = 258,
- exp_MINUS = 259,
- exp_TIMES = 260,
- exp_DIVIDE = 261,
- exp_MOD = 262,
- exp_SHIFTLEFT = 263,
- exp_SHIFTRIGHT = 264,
- exp_OPENPARENT = 265,
- exp_CLOSEPARENT = 266,
- exp_OR = 267,
- exp_AND = 268,
- exp_XOR = 269,
- exp_NOT = 270,
- exp_NUMBER = 271
+ YYEMPTY = -2,
+ YYEOF = 0, /* "end of file" */
+ YYerror = 256, /* error */
+ YYUNDEF = 257, /* "invalid token" */
+ exp_PLUS = 258, /* exp_PLUS */
+ exp_MINUS = 259, /* exp_MINUS */
+ exp_TIMES = 260, /* exp_TIMES */
+ exp_DIVIDE = 261, /* exp_DIVIDE */
+ exp_MOD = 262, /* exp_MOD */
+ exp_SHIFTLEFT = 263, /* exp_SHIFTLEFT */
+ exp_SHIFTRIGHT = 264, /* exp_SHIFTRIGHT */
+ exp_OPENPARENT = 265, /* exp_OPENPARENT */
+ exp_CLOSEPARENT = 266, /* exp_CLOSEPARENT */
+ exp_OR = 267, /* exp_OR */
+ exp_AND = 268, /* exp_AND */
+ exp_XOR = 269, /* exp_XOR */
+ exp_NOT = 270, /* exp_NOT */
+ exp_NUMBER = 271 /* exp_NUMBER */
};
+ typedef enum yytokentype yytoken_kind_t;
#endif
-/* Tokens. */
-#define exp_PLUS 258
-#define exp_MINUS 259
-#define exp_TIMES 260
-#define exp_DIVIDE 261
-#define exp_MOD 262
-#define exp_SHIFTLEFT 263
-#define exp_SHIFTRIGHT 264
-#define exp_OPENPARENT 265
-#define exp_CLOSEPARENT 266
-#define exp_OR 267
-#define exp_AND 268
-#define exp_XOR 269
-#define exp_NOT 270
-#define exp_NUMBER 271
/* Value type. */
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 2494aadcc..dba2cac13 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -34,6 +34,10 @@
/* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
+
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros.
@@ -41,14 +45,11 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
-
-/* Identify Bison output. */
-#define YYBISON 1
+/* Identify Bison output, and Bison version. */
+#define YYBISON 30704
-/* Bison version. */
-#define YYBISON_VERSION "3.4.2"
+/* Bison version string. */
+#define YYBISON_VERSION "3.7.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -70,7 +71,6 @@
#define yydebug cmFortran_yydebug
#define yynerrs cmFortran_yynerrs
-
/* First part of user prologue. */
#line 1 "cmFortranParser.y"
@@ -92,13 +92,11 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmFortran_yy
+ bison --name-prefix=cmFortran_yy
--defines=cmFortranParserTokens.h
-ocmFortranParser.cxx
cmFortranParser.y
-Modify cmFortranParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
*/
#include "cmConfigure.h" // IWYU pragma: keep
@@ -110,7 +108,6 @@ Modify cmFortranParser.cxx:
/*-------------------------------------------------------------------------*/
#define cmFortranParser_cxx
#include "cmFortranParser.h" /* Interface to parser object. */
-#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */
/* Forward declare the lexer entry point. */
YY_DECL;
@@ -133,10 +130,20 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
#endif
-#line 139 "cmFortranParser.cxx"
+#line 137 "cmFortranParser.cxx"
+# ifndef YY_CAST
+# ifdef __cplusplus
+# define YY_CAST(Type, Val) static_cast<Type> (Val)
+# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
+# else
+# define YY_CAST(Type, Val) ((Type) (Val))
+# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+# endif
+# endif
# ifndef YY_NULLPTR
# if defined __cplusplus
# if 201103L <= __cplusplus
@@ -149,132 +156,69 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
# endif
# endif
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* Use api.header.include to #include this header
- instead of duplicating it here. */
-#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
-# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
-/* Debug traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int cmFortran_yydebug;
-#endif
-
-/* Token type. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- enum yytokentype
- {
- EOSTMT = 258,
- ASSIGNMENT_OP = 259,
- GARBAGE = 260,
- CPP_LINE_DIRECTIVE = 261,
- CPP_INCLUDE = 262,
- F90PPR_INCLUDE = 263,
- COCO_INCLUDE = 264,
- F90PPR_DEFINE = 265,
- CPP_DEFINE = 266,
- F90PPR_UNDEF = 267,
- CPP_UNDEF = 268,
- CPP_IFDEF = 269,
- CPP_IFNDEF = 270,
- CPP_IF = 271,
- CPP_ELSE = 272,
- CPP_ELIF = 273,
- CPP_ENDIF = 274,
- F90PPR_IFDEF = 275,
- F90PPR_IFNDEF = 276,
- F90PPR_IF = 277,
- F90PPR_ELSE = 278,
- F90PPR_ELIF = 279,
- F90PPR_ENDIF = 280,
- COMMA = 281,
- COLON = 282,
- DCOLON = 283,
- LPAREN = 284,
- RPAREN = 285,
- UNTERMINATED_STRING = 286,
- STRING = 287,
- WORD = 288,
- CPP_INCLUDE_ANGLE = 289,
- END = 290,
- INCLUDE = 291,
- INTERFACE = 292,
- MODULE = 293,
- SUBMODULE = 294,
- USE = 295
- };
-#endif
-/* Tokens. */
-#define EOSTMT 258
-#define ASSIGNMENT_OP 259
-#define GARBAGE 260
-#define CPP_LINE_DIRECTIVE 261
-#define CPP_INCLUDE 262
-#define F90PPR_INCLUDE 263
-#define COCO_INCLUDE 264
-#define F90PPR_DEFINE 265
-#define CPP_DEFINE 266
-#define F90PPR_UNDEF 267
-#define CPP_UNDEF 268
-#define CPP_IFDEF 269
-#define CPP_IFNDEF 270
-#define CPP_IF 271
-#define CPP_ELSE 272
-#define CPP_ELIF 273
-#define CPP_ENDIF 274
-#define F90PPR_IFDEF 275
-#define F90PPR_IFNDEF 276
-#define F90PPR_IF 277
-#define F90PPR_ELSE 278
-#define F90PPR_ELIF 279
-#define F90PPR_ENDIF 280
-#define COMMA 281
-#define COLON 282
-#define DCOLON 283
-#define LPAREN 284
-#define RPAREN 285
-#define UNTERMINATED_STRING 286
-#define STRING 287
-#define WORD 288
-#define CPP_INCLUDE_ANGLE 289
-#define END 290
-#define INCLUDE 291
-#define INTERFACE 292
-#define MODULE 293
-#define SUBMODULE 294
-#define USE 295
-
-/* Value type. */
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-union YYSTYPE
+#include "cmFortranParserTokens.h"
+/* Symbol kind. */
+enum yysymbol_kind_t
{
-#line 73 "cmFortranParser.y"
-
- char* string;
-
-#line 266 "cmFortranParser.cxx"
-
+ YYSYMBOL_YYEMPTY = -2,
+ YYSYMBOL_YYEOF = 0, /* "end of file" */
+ YYSYMBOL_YYerror = 1, /* error */
+ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
+ YYSYMBOL_EOSTMT = 3, /* EOSTMT */
+ YYSYMBOL_ASSIGNMENT_OP = 4, /* ASSIGNMENT_OP */
+ YYSYMBOL_GARBAGE = 5, /* GARBAGE */
+ YYSYMBOL_CPP_LINE_DIRECTIVE = 6, /* CPP_LINE_DIRECTIVE */
+ YYSYMBOL_CPP_INCLUDE = 7, /* CPP_INCLUDE */
+ YYSYMBOL_F90PPR_INCLUDE = 8, /* F90PPR_INCLUDE */
+ YYSYMBOL_COCO_INCLUDE = 9, /* COCO_INCLUDE */
+ YYSYMBOL_F90PPR_DEFINE = 10, /* F90PPR_DEFINE */
+ YYSYMBOL_CPP_DEFINE = 11, /* CPP_DEFINE */
+ YYSYMBOL_F90PPR_UNDEF = 12, /* F90PPR_UNDEF */
+ YYSYMBOL_CPP_UNDEF = 13, /* CPP_UNDEF */
+ YYSYMBOL_CPP_IFDEF = 14, /* CPP_IFDEF */
+ YYSYMBOL_CPP_IFNDEF = 15, /* CPP_IFNDEF */
+ YYSYMBOL_CPP_IF = 16, /* CPP_IF */
+ YYSYMBOL_CPP_ELSE = 17, /* CPP_ELSE */
+ YYSYMBOL_CPP_ELIF = 18, /* CPP_ELIF */
+ YYSYMBOL_CPP_ENDIF = 19, /* CPP_ENDIF */
+ YYSYMBOL_F90PPR_IFDEF = 20, /* F90PPR_IFDEF */
+ YYSYMBOL_F90PPR_IFNDEF = 21, /* F90PPR_IFNDEF */
+ YYSYMBOL_F90PPR_IF = 22, /* F90PPR_IF */
+ YYSYMBOL_F90PPR_ELSE = 23, /* F90PPR_ELSE */
+ YYSYMBOL_F90PPR_ELIF = 24, /* F90PPR_ELIF */
+ YYSYMBOL_F90PPR_ENDIF = 25, /* F90PPR_ENDIF */
+ YYSYMBOL_COMMA = 26, /* COMMA */
+ YYSYMBOL_COLON = 27, /* COLON */
+ YYSYMBOL_DCOLON = 28, /* DCOLON */
+ YYSYMBOL_LPAREN = 29, /* LPAREN */
+ YYSYMBOL_RPAREN = 30, /* RPAREN */
+ YYSYMBOL_UNTERMINATED_STRING = 31, /* UNTERMINATED_STRING */
+ YYSYMBOL_STRING = 32, /* STRING */
+ YYSYMBOL_WORD = 33, /* WORD */
+ YYSYMBOL_CPP_INCLUDE_ANGLE = 34, /* CPP_INCLUDE_ANGLE */
+ YYSYMBOL_END = 35, /* END */
+ YYSYMBOL_INCLUDE = 36, /* INCLUDE */
+ YYSYMBOL_INTERFACE = 37, /* INTERFACE */
+ YYSYMBOL_MODULE = 38, /* MODULE */
+ YYSYMBOL_SUBMODULE = 39, /* SUBMODULE */
+ YYSYMBOL_USE = 40, /* USE */
+ YYSYMBOL_YYACCEPT = 41, /* $accept */
+ YYSYMBOL_code = 42, /* code */
+ YYSYMBOL_stmt = 43, /* stmt */
+ YYSYMBOL_include = 44, /* include */
+ YYSYMBOL_define = 45, /* define */
+ YYSYMBOL_undef = 46, /* undef */
+ YYSYMBOL_ifdef = 47, /* ifdef */
+ YYSYMBOL_ifndef = 48, /* ifndef */
+ YYSYMBOL_if = 49, /* if */
+ YYSYMBOL_elif = 50, /* elif */
+ YYSYMBOL_else = 51, /* else */
+ YYSYMBOL_endif = 52, /* endif */
+ YYSYMBOL_other = 53, /* other */
+ YYSYMBOL_misc_code = 54 /* misc_code */
};
-typedef union YYSTYPE YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-
+typedef enum yysymbol_kind_t yysymbol_kind_t;
-int cmFortran_yyparse (yyscan_t yyscanner);
-
-#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED */
@@ -282,28 +226,75 @@ int cmFortran_yyparse (yyscan_t yyscanner);
# undef short
#endif
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+ <limits.h> and (if available) <stdint.h> are included
+ so that the code can choose integer types of a good width. */
+
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_STDINT_H
+# endif
#endif
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
+/* Narrow types that promote to a signed type and that can represent a
+ signed or unsigned integer of at least N bits. In tables they can
+ save space and decrease cache pressure. Promoting to a signed type
+ helps avoid bugs in integer arithmetic. */
+
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
#else
typedef signed char yytype_int8;
#endif
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
#else
-typedef unsigned short yytype_uint16;
+typedef short yytype_int16;
#endif
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
+#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 \
+ && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
#else
-typedef short yytype_int16;
+typedef short yytype_uint8;
+#endif
+
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
+typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
+#endif
+
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+# define YYPTRDIFF_T __PTRDIFF_TYPE__
+# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+# ifndef ptrdiff_t
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# endif
+# define YYPTRDIFF_T ptrdiff_t
+# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+# define YYPTRDIFF_T long
+# define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
#endif
#ifndef YYSIZE_T
@@ -311,7 +302,7 @@ typedef short yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -319,7 +310,20 @@ typedef short yytype_int16;
# endif
#endif
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+#define YYSIZE_MAXIMUM \
+ YY_CAST (YYPTRDIFF_T, \
+ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
+ ? YYPTRDIFF_MAXIMUM \
+ : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_int8 yy_state_t;
+
+/* State numbers in computations. */
+typedef int yy_state_fast_t;
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
@@ -333,22 +337,21 @@ typedef short yytype_int16;
# endif
#endif
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__ \
- && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
- || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
-# else
-# define YY_ATTRIBUTE(Spec) /* empty */
-# endif
-#endif
#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define YY_ATTRIBUTE_PURE
+# endif
#endif
#ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+# define YY_ATTRIBUTE_UNUSED
+# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
@@ -360,11 +363,11 @@ typedef short yytype_int16;
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
- _Pragma ("GCC diagnostic push") \
- _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
@@ -377,10 +380,22 @@ typedef short yytype_int16;
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
+#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END \
+ _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
#define YY_ASSERT(E) ((void) (0 && (E)))
-#if ! defined yyoverflow || YYERROR_VERBOSE
+#if 1
/* The parser invokes alloca or malloc; define the necessary symbols. */
@@ -445,8 +460,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
+#endif /* 1 */
#if (! defined yyoverflow \
&& (! defined __cplusplus \
@@ -455,17 +469,17 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss_alloc;
+ yy_state_t yyss_alloc;
YYSTYPE yyvs_alloc;
};
/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
# define YYCOPY_NEEDED 1
@@ -478,11 +492,11 @@ union yyalloc
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
- YYSIZE_T yynewbytes; \
+ YYPTRDIFF_T yynewbytes; \
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
+ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / YYSIZEOF (*yyptr); \
} \
while (0)
@@ -494,12 +508,12 @@ union yyalloc
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
# else
# define YYCOPY(Dst, Src, Count) \
do \
{ \
- YYSIZE_T yyi; \
+ YYPTRDIFF_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
@@ -522,17 +536,20 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 127
-#define YYUNDEFTOK 2
+/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 295
+
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
-#define YYTRANSLATE(YYX) \
- ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+#define YYTRANSLATE(YYX) \
+ (0 <= (YYX) && (YYX) <= YYMAXUTOK \
+ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
+ : YYSYMBOL_YYUNDEF)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */
-static const yytype_uint8 yytranslate[] =
+static const yytype_int8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -570,38 +587,52 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 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
+ 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
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 1
+/** Accessing symbol of state STATE. */
+#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
+
+#if 1
+/* The user-facing name of the symbol whose (internal) number is
+ YYSYMBOL. No bounds checking. */
+static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
+
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "EOSTMT", "ASSIGNMENT_OP", "GARBAGE",
- "CPP_LINE_DIRECTIVE", "CPP_INCLUDE", "F90PPR_INCLUDE", "COCO_INCLUDE",
- "F90PPR_DEFINE", "CPP_DEFINE", "F90PPR_UNDEF", "CPP_UNDEF", "CPP_IFDEF",
- "CPP_IFNDEF", "CPP_IF", "CPP_ELSE", "CPP_ELIF", "CPP_ENDIF",
- "F90PPR_IFDEF", "F90PPR_IFNDEF", "F90PPR_IF", "F90PPR_ELSE",
- "F90PPR_ELIF", "F90PPR_ENDIF", "COMMA", "COLON", "DCOLON", "LPAREN",
- "RPAREN", "UNTERMINATED_STRING", "STRING", "WORD", "CPP_INCLUDE_ANGLE",
- "END", "INCLUDE", "INTERFACE", "MODULE", "SUBMODULE", "USE", "$accept",
- "code", "stmt", "include", "define", "undef", "ifdef", "ifndef", "if",
- "elif", "else", "endif", "other", "misc_code", YY_NULLPTR
+ "\"end of file\"", "error", "\"invalid token\"", "EOSTMT",
+ "ASSIGNMENT_OP", "GARBAGE", "CPP_LINE_DIRECTIVE", "CPP_INCLUDE",
+ "F90PPR_INCLUDE", "COCO_INCLUDE", "F90PPR_DEFINE", "CPP_DEFINE",
+ "F90PPR_UNDEF", "CPP_UNDEF", "CPP_IFDEF", "CPP_IFNDEF", "CPP_IF",
+ "CPP_ELSE", "CPP_ELIF", "CPP_ENDIF", "F90PPR_IFDEF", "F90PPR_IFNDEF",
+ "F90PPR_IF", "F90PPR_ELSE", "F90PPR_ELIF", "F90PPR_ENDIF", "COMMA",
+ "COLON", "DCOLON", "LPAREN", "RPAREN", "UNTERMINATED_STRING", "STRING",
+ "WORD", "CPP_INCLUDE_ANGLE", "END", "INCLUDE", "INTERFACE", "MODULE",
+ "SUBMODULE", "USE", "$accept", "code", "stmt", "include", "define",
+ "undef", "ifdef", "ifndef", "if", "elif", "else", "endif", "other",
+ "misc_code", YY_NULLPTR
};
+
+static const char *
+yysymbol_name (yysymbol_kind_t yysymbol)
+{
+ return yytname[yysymbol];
+}
#endif
-# ifdef YYPRINT
+#ifdef YYPRINT
/* YYTOKNUM[NUM] -- (External) token number corresponding to the
(internal) symbol number NUM (which must be that of a token). */
-static const yytype_uint16 yytoknum[] =
+static const yytype_int16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
@@ -609,16 +640,16 @@ static const yytype_uint16 yytoknum[] =
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295
};
-# endif
+#endif
-#define YYPACT_NINF -39
+#define YYPACT_NINF (-39)
-#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-39)))
+#define yypact_value_is_default(Yyn) \
+ ((Yyn) == YYPACT_NINF)
-#define YYTABLE_NINF -1
+#define YYTABLE_NINF (-1)
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(Yyn) \
0
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -643,7 +674,7 @@ static const yytype_int16 yypact[] =
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
Performed when YYTABLE does not specify something else to do. Zero
means the default is an error. */
-static const yytype_uint8 yydefact[] =
+static const yytype_int8 yydefact[] =
{
2, 0, 1, 0, 25, 0, 27, 28, 29, 31,
30, 33, 32, 34, 36, 38, 42, 40, 44, 35,
@@ -677,7 +708,7 @@ static const yytype_int8 yydefgoto[] =
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule whose
number is the opposite. If YYTABLE_NINF, syntax error. */
-static const yytype_uint8 yytable[] =
+static const yytype_int8 yytable[] =
{
59, 60, 61, 62, 42, 63, 105, 83, 84, 106,
85, 86, 43, 45, 46, 90, 91, 92, 93, 94,
@@ -807,7 +838,7 @@ static const yytype_int8 yycheck[] =
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
+static const yytype_int8 yystos[] =
{
0, 42, 0, 1, 3, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
@@ -825,7 +856,7 @@ static const yytype_uint8 yystos[] =
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
+static const yytype_int8 yyr1[] =
{
0, 41, 42, 42, 43, 43, 43, 43, 43, 43,
43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
@@ -837,7 +868,7 @@ static const yytype_uint8 yyr1[] =
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yyr2[] =
{
0, 2, 0, 2, 2, 4, 4, 7, 9, 4,
4, 5, 7, 4, 4, 3, 4, 4, 4, 4,
@@ -849,10 +880,10 @@ static const yytype_uint8 yyr2[] =
};
+enum { YYENOMEM = -2 };
+
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
@@ -878,10 +909,9 @@ static const yytype_uint8 yyr2[] =
} \
while (0)
-/* Error token number */
-#define YYTERROR 1
-#define YYERRCODE 256
-
+/* Backward compatibility with an undocumented macro.
+ Use YYerror or YYUNDEF. */
+#define YYERRCODE YYUNDEF
/* Enable debugging if requested. */
@@ -899,18 +929,18 @@ do { \
} while (0)
/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+# ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
do { \
if (yydebug) \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
- Type, Value, yyscanner); \
+ Kind, Value, yyscanner); \
YYFPRINTF (stderr, "\n"); \
} \
} while (0)
@@ -921,7 +951,8 @@ do { \
`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
FILE *yyoutput = yyo;
YYUSE (yyoutput);
@@ -929,11 +960,11 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
if (!yyvaluep)
return;
# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
+ if (yykind < YYNTOKENS)
+ YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
@@ -943,12 +974,13 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy
`---------------------------*/
static void
-yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
YYFPRINTF (yyo, "%s %s (",
- yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+ yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));
- yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ yy_symbol_value_print (yyo, yykind, yyvaluep, yyscanner);
YYFPRINTF (yyo, ")");
}
@@ -958,7 +990,7 @@ yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t
`------------------------------------------------------------------*/
static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -981,21 +1013,21 @@ do { \
`------------------------------------------------*/
static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
+ int yyrule, yyscan_t yyscanner)
{
- unsigned long yylno = yyrline[yyrule];
+ int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
- yystos[yyssp[yyi + 1 - yynrhs]],
- &yyvsp[(yyi + 1) - (yynrhs)]
- , yyscanner);
+ YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
+ &yyvsp[(yyi + 1) - (yynrhs)], yyscanner);
YYFPRINTF (stderr, "\n");
}
}
@@ -1010,8 +1042,8 @@ do { \
multiple parsers can coexist. */
int yydebug;
#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YYDPRINTF(Args) ((void) 0)
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
@@ -1034,28 +1066,76 @@ int yydebug;
#endif
-#if YYERROR_VERBOSE
+/* Context of a parse error. */
+typedef struct
+{
+ yy_state_t *yyssp;
+ yysymbol_kind_t yytoken;
+} yypcontext_t;
+
+/* Put in YYARG at most YYARGN of the expected tokens given the
+ current YYCTX, and return the number of tokens stored in YYARG. If
+ YYARG is null, return the number of expected tokens (guaranteed to
+ be less than YYNTOKENS). Return YYENOMEM on memory exhaustion.
+ Return 0 if there are more than YYARGN expected tokens, yet fill
+ YYARG up to YYARGN. */
+static int
+yypcontext_expected_tokens (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
+{
+ /* Actual size of YYARG. */
+ int yycount = 0;
+ int yyn = yypact[+*yyctx->yyssp];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (!yyarg)
+ ++yycount;
+ else if (yycount == yyargn)
+ return 0;
+ else
+ yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx);
+ }
+ }
+ if (yyarg && yycount == 0 && 0 < yyargn)
+ yyarg[0] = YYSYMBOL_YYEMPTY;
+ return yycount;
+}
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
+
+
+
+#ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S)))
+# else
/* Return the length of YYSTR. */
-static YYSIZE_T
+static YYPTRDIFF_T
yystrlen (const char *yystr)
{
- YYSIZE_T yylen;
+ YYPTRDIFF_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
continue;
return yylen;
}
-# endif
# endif
+#endif
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
+#ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
static char *
@@ -1069,10 +1149,10 @@ yystpcpy (char *yydest, const char *yysrc)
return yyd - 1;
}
-# endif
# endif
+#endif
-# ifndef yytnamerr
+#ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
quotes and backslashes, so that it's suitable for yyerror. The
heuristic is that double-quoting is unnecessary unless the string
@@ -1080,14 +1160,13 @@ yystpcpy (char *yydest, const char *yysrc)
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
-static YYSIZE_T
+static YYPTRDIFF_T
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
- YYSIZE_T yyn = 0;
+ YYPTRDIFF_T yyn = 0;
char const *yyp = yystr;
-
for (;;)
switch (*++yyp)
{
@@ -1116,36 +1195,20 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ;
}
- if (! yyres)
+ if (yyres)
+ return yystpcpy (yyres, yystr) - yyres;
+ else
return yystrlen (yystr);
-
- return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
-# endif
+#endif
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
+yy_syntax_error_arguments (const yypcontext_t *yyctx,
+ yysymbol_kind_t yyarg[], int yyargn)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = YY_NULLPTR;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
+ /* Actual size of YYARG. */
int yycount = 0;
-
/* There are many possibilities here to consider:
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
@@ -1169,49 +1232,54 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
one exception: it will still contain any token that will not be
accepted due to an error action in a later state.
*/
- if (yytoken != YYEMPTY)
+ if (yyctx->yytoken != YYSYMBOL_YYEMPTY)
{
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- {
- YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
- }
- }
- }
+ int yyn;
+ if (yyarg)
+ yyarg[yycount] = yyctx->yytoken;
+ ++yycount;
+ yyn = yypcontext_expected_tokens (yyctx,
+ yyarg ? yyarg + 1 : yyarg, yyargn - 1);
+ if (yyn == YYENOMEM)
+ return YYENOMEM;
+ else
+ yycount += yyn;
}
+ return yycount;
+}
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
+ const yypcontext_t *yyctx)
+{
+ enum { YYARGS_MAX = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat: reported tokens (one for the "unexpected",
+ one per "expected"). */
+ yysymbol_kind_t yyarg[YYARGS_MAX];
+ /* Cumulated lengths of YYARG. */
+ YYPTRDIFF_T yysize = 0;
+
+ /* Actual size of YYARG. */
+ int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX);
+ if (yycount == YYENOMEM)
+ return YYENOMEM;
switch (yycount)
{
-# define YYCASE_(N, S) \
+#define YYCASE_(N, S) \
case N: \
yyformat = S; \
- break
+ break
default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
@@ -1219,15 +1287,23 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
+#undef YYCASE_
}
+ /* Compute error message size. Don't count the "%s"s, but reserve
+ room for the terminator. */
+ yysize = yystrlen (yyformat) - 2 * yycount + 1;
{
- YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
- yysize = yysize1;
- else
- return 2;
+ int yyi;
+ for (yyi = 0; yyi < yycount; ++yyi)
+ {
+ YYPTRDIFF_T yysize1
+ = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]);
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
+ return YYENOMEM;
+ }
}
if (*yymsg_alloc < yysize)
@@ -1236,7 +1312,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
if (! (yysize <= *yymsg_alloc
&& *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
*yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
+ return -1;
}
/* Avoid sprintf, as that infringes on the user's name space.
@@ -1248,40 +1324,43 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
while ((*yyp = *yyformat) != '\0')
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
- yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]);
yyformat += 2;
}
else
{
- yyp++;
- yyformat++;
+ ++yyp;
+ ++yyformat;
}
}
return 0;
}
-#endif /* YYERROR_VERBOSE */
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+yydestruct (const char *yymsg,
+ yysymbol_kind_t yykind, YYSTYPE *yyvaluep, yyscan_t yyscanner)
{
YYUSE (yyvaluep);
YYUSE (yyscanner);
if (!yymsg)
yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
- YYUSE (yytype);
+ YYUSE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
+
+
/*----------.
| yyparse. |
`----------*/
@@ -1289,7 +1368,7 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner
int
yyparse (yyscan_t yyscanner)
{
-/* The lookahead symbol. */
+/* Lookahead token kind. */
int yychar;
@@ -1300,45 +1379,41 @@ YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
/* Number of syntax errors so far. */
- int yynerrs;
+ int yynerrs = 0;
- int yystate;
+ yy_state_fast_t yystate = 0;
/* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
-
- /* The stacks and their tools:
- 'yyss': related to states.
- 'yyvs': related to semantic values.
+ int yyerrstatus = 0;
- Refer to the stacks through separate pointers, to allow yyoverflow
+ /* Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss;
- yytype_int16 *yyssp;
+ /* Their size. */
+ YYPTRDIFF_T yystacksize = YYINITDEPTH;
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs;
- YYSTYPE *yyvsp;
+ /* The state stack: array, bottom, top. */
+ yy_state_t yyssa[YYINITDEPTH];
+ yy_state_t *yyss = yyssa;
+ yy_state_t *yyssp = yyss;
- YYSIZE_T yystacksize;
+ /* The semantic value stack: array, bottom, top. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp = yyvs;
int yyn;
+ /* The return value of yyparse. */
int yyresult;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
+ /* Lookahead symbol kind. */
+ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
-#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
+ YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
@@ -1346,15 +1421,8 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;
- yystacksize = YYINITDEPTH;
-
YYDPRINTF ((stderr, "Starting parse\n"));
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
@@ -1369,12 +1437,15 @@ yynewstate:
/*--------------------------------------------------------------------.
-| yynewstate -- set current state (the top of the stack) to yystate. |
+| yysetstate -- set current state (the top of the stack) to yystate. |
`--------------------------------------------------------------------*/
yysetstate:
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
- *yyssp = (yytype_int16) yystate;
+ YY_IGNORE_USELESS_CAST_BEGIN
+ *yyssp = YY_CAST (yy_state_t, yystate);
+ YY_IGNORE_USELESS_CAST_END
+ YY_STACK_PRINT (yyss, yyssp);
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
@@ -1382,23 +1453,23 @@ yysetstate:
#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
+ YYPTRDIFF_T yysize = yyssp - yyss + 1;
# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
+ yy_state_t *yyss1 = yyss;
YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
+ &yyss1, yysize * YYSIZEOF (*yyssp),
+ &yyvs1, yysize * YYSIZEOF (*yyvsp),
&yystacksize);
yyss = yyss1;
yyvs = yyvs1;
@@ -1412,14 +1483,15 @@ yysetstate:
yystacksize = YYMAXDEPTH;
{
- yytype_int16 *yyss1 = yyss;
+ yy_state_t *yyss1 = yyss;
union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ YY_CAST (union yyalloc *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
@@ -1428,8 +1500,10 @@ yysetstate:
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long) yystacksize));
+ YY_IGNORE_USELESS_CAST_BEGIN
+ YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+ YY_CAST (long, yystacksize)));
+ YY_IGNORE_USELESS_CAST_END
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
@@ -1456,18 +1530,29 @@ yybackup:
/* Not known => get a lookahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
if (yychar == YYEMPTY)
{
- YYDPRINTF ((stderr, "Reading a token: "));
+ YYDPRINTF ((stderr, "Reading a token\n"));
yychar = yylex (&yylval, yyscanner);
}
if (yychar <= YYEOF)
{
- yychar = yytoken = YYEOF;
+ yychar = YYEOF;
+ yytoken = YYSYMBOL_YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n"));
}
+ else if (yychar == YYerror)
+ {
+ /* The scanner already issued an error message, process directly
+ to error recovery. But do not keep the error token as
+ lookahead, it is too special and may lead us to an endless
+ loop in error recovery. */
+ yychar = YYUNDEF;
+ yytoken = YYSYMBOL_YYerror;
+ goto yyerrlab1;
+ }
else
{
yytoken = YYTRANSLATE (yychar);
@@ -1495,14 +1580,13 @@ yybackup:
/* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token. */
- yychar = YYEMPTY;
-
yystate = yyn;
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
goto yynewstate;
@@ -1537,28 +1621,28 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 4:
-#line 104 "cmFortranParser.y"
- {
+ case 4: /* stmt: INTERFACE EOSTMT */
+#line 102 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
}
-#line 1547 "cmFortranParser.cxx"
+#line 1631 "cmFortranParser.cxx"
break;
- case 5:
-#line 108 "cmFortranParser.y"
- {
+ case 5: /* stmt: USE WORD other EOSTMT */
+#line 106 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1557 "cmFortranParser.cxx"
+#line 1641 "cmFortranParser.cxx"
break;
- case 6:
-#line 113 "cmFortranParser.y"
- {
+ case 6: /* stmt: MODULE WORD other EOSTMT */
+#line 111 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
cmsysString_strcasecmp((yyvsp[-2].string), "procedure") != 0 &&
@@ -1567,64 +1651,64 @@ yyreduce:
}
free((yyvsp[-2].string));
}
-#line 1571 "cmFortranParser.cxx"
+#line 1655 "cmFortranParser.cxx"
break;
- case 7:
-#line 122 "cmFortranParser.y"
- {
+ case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */
+#line 120 "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 1582 "cmFortranParser.cxx"
+#line 1666 "cmFortranParser.cxx"
break;
- case 8:
-#line 128 "cmFortranParser.y"
- {
+ case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */
+#line 126 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
free((yyvsp[-6].string));
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1594 "cmFortranParser.cxx"
+#line 1678 "cmFortranParser.cxx"
break;
- case 9:
-#line 135 "cmFortranParser.y"
- {
+ case 9: /* stmt: INTERFACE WORD other EOSTMT */
+#line 133 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
free((yyvsp[-2].string));
}
-#line 1604 "cmFortranParser.cxx"
+#line 1688 "cmFortranParser.cxx"
break;
- case 10:
-#line 140 "cmFortranParser.y"
- {
+ case 10: /* stmt: END INTERFACE other EOSTMT */
+#line 138 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, false);
}
-#line 1613 "cmFortranParser.cxx"
+#line 1697 "cmFortranParser.cxx"
break;
- case 11:
-#line 144 "cmFortranParser.y"
- {
+ case 11: /* stmt: USE DCOLON WORD other EOSTMT */
+#line 142 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1623 "cmFortranParser.cxx"
+#line 1707 "cmFortranParser.cxx"
break;
- case 12:
-#line 149 "cmFortranParser.y"
- {
+ case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */
+#line 147 "cmFortranParser.y"
+ {
if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
@@ -1632,139 +1716,139 @@ yyreduce:
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1636 "cmFortranParser.cxx"
+#line 1720 "cmFortranParser.cxx"
break;
- case 13:
-#line 157 "cmFortranParser.y"
- {
+ case 13: /* stmt: INCLUDE STRING other EOSTMT */
+#line 155 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1646 "cmFortranParser.cxx"
+#line 1730 "cmFortranParser.cxx"
break;
- case 14:
-#line 162 "cmFortranParser.y"
- {
+ case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */
+#line 160 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1656 "cmFortranParser.cxx"
+#line 1740 "cmFortranParser.cxx"
break;
- case 15:
-#line 167 "cmFortranParser.y"
- {
+ case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */
+#line 165 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1666 "cmFortranParser.cxx"
+#line 1750 "cmFortranParser.cxx"
break;
- case 16:
-#line 172 "cmFortranParser.y"
- {
+ case 16: /* stmt: include STRING other EOSTMT */
+#line 170 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1676 "cmFortranParser.cxx"
+#line 1760 "cmFortranParser.cxx"
break;
- case 17:
-#line 177 "cmFortranParser.y"
- {
+ case 17: /* stmt: define WORD other EOSTMT */
+#line 175 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1686 "cmFortranParser.cxx"
+#line 1770 "cmFortranParser.cxx"
break;
- case 18:
-#line 182 "cmFortranParser.y"
- {
+ case 18: /* stmt: undef WORD other EOSTMT */
+#line 180 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1696 "cmFortranParser.cxx"
+#line 1780 "cmFortranParser.cxx"
break;
- case 19:
-#line 187 "cmFortranParser.y"
- {
+ case 19: /* stmt: ifdef WORD other EOSTMT */
+#line 185 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1706 "cmFortranParser.cxx"
+#line 1790 "cmFortranParser.cxx"
break;
- case 20:
-#line 192 "cmFortranParser.y"
- {
+ case 20: /* stmt: ifndef WORD other EOSTMT */
+#line 190 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1716 "cmFortranParser.cxx"
+#line 1800 "cmFortranParser.cxx"
break;
- case 21:
-#line 197 "cmFortranParser.y"
- {
+ case 21: /* stmt: if other EOSTMT */
+#line 195 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
-#line 1725 "cmFortranParser.cxx"
+#line 1809 "cmFortranParser.cxx"
break;
- case 22:
-#line 201 "cmFortranParser.y"
- {
+ case 22: /* stmt: elif other EOSTMT */
+#line 199 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
-#line 1734 "cmFortranParser.cxx"
+#line 1818 "cmFortranParser.cxx"
break;
- case 23:
-#line 205 "cmFortranParser.y"
- {
+ case 23: /* stmt: else other EOSTMT */
+#line 203 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
-#line 1743 "cmFortranParser.cxx"
+#line 1827 "cmFortranParser.cxx"
break;
- case 24:
-#line 209 "cmFortranParser.y"
- {
+ case 24: /* stmt: endif other EOSTMT */
+#line 207 "cmFortranParser.y"
+ {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
-#line 1752 "cmFortranParser.cxx"
+#line 1836 "cmFortranParser.cxx"
break;
- case 48:
-#line 231 "cmFortranParser.y"
- { free ((yyvsp[0].string)); }
-#line 1758 "cmFortranParser.cxx"
+ case 48: /* misc_code: WORD */
+#line 229 "cmFortranParser.y"
+ { free ((yyvsp[0].string)); }
+#line 1842 "cmFortranParser.cxx"
break;
- case 55:
-#line 238 "cmFortranParser.y"
- { free ((yyvsp[0].string)); }
-#line 1764 "cmFortranParser.cxx"
+ case 55: /* misc_code: STRING */
+#line 236 "cmFortranParser.y"
+ { free ((yyvsp[0].string)); }
+#line 1848 "cmFortranParser.cxx"
break;
-#line 1768 "cmFortranParser.cxx"
+#line 1852 "cmFortranParser.cxx"
default: break;
}
@@ -1779,11 +1863,10 @@ yyreduce:
case of YYERROR or YYBACKUP, subsequent parser actions might lead
to an incorrect destructor call or verbose syntax error message
before the lookahead is translated. */
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);
YYPOPSTACK (yylen);
yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
@@ -1807,50 +1890,44 @@ yyreduce:
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
+ yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (yyscanner, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
{
+ yypcontext_t yyctx
+ = {yyssp, yytoken};
char const *yymsgp = YY_("syntax error");
int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
+ yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
if (yysyntax_error_status == 0)
yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
+ else if (yysyntax_error_status == -1)
{
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
+ yymsg = YY_CAST (char *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc)));
+ if (yymsg)
{
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
+ yysyntax_error_status
+ = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx);
+ yymsgp = yymsg;
}
else
{
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = YYENOMEM;
}
}
yyerror (yyscanner, yymsgp);
- if (yysyntax_error_status == 2)
+ if (yysyntax_error_status == YYENOMEM)
goto yyexhaustedlab;
}
-# undef YYSYNTAX_ERROR
-#endif
}
-
-
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
@@ -1870,7 +1947,6 @@ yyerrlab:
}
}
-#if 0
/* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -1898,16 +1974,16 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
-#endif
yyerrstatus = 3; /* Each real token shifted decrements this. */
+ /* Pop stack until we find a state that shifts the error token. */
for (;;)
{
yyn = yypact[yystate];
if (!yypact_value_is_default (yyn))
{
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ yyn += YYSYMBOL_YYerror;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
{
yyn = yytable[yyn];
if (0 < yyn)
@@ -1921,7 +1997,7 @@ yyerrlab1:
yydestruct ("Error: popping",
- yystos[yystate], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (yystate), yyvsp, yyscanner);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
@@ -1933,7 +2009,7 @@ yyerrlab1:
/* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
yystate = yyn;
goto yynewstate;
@@ -1955,20 +2031,20 @@ yyabortlab:
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if 1
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
yyerror (yyscanner, YY_("memory exhausted"));
yyresult = 2;
- /* Fall through. */
+ goto yyreturn;
#endif
-/*-----------------------------------------------------.
-| yyreturn -- parsing is finished, return the result. |
-`-----------------------------------------------------*/
+/*-------------------------------------------------------.
+| yyreturn -- parsing is finished, clean up and return. |
+`-------------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -1985,19 +2061,18 @@ yyreturn:
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, yyscanner);
+ YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yyscanner);
YYPOPSTACK (1);
}
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
-#if YYERROR_VERBOSE
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
-#endif
return yyresult;
}
-#line 250 "cmFortranParser.y"
+
+#line 248 "cmFortranParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
index 1b54dd9f7..e461160c6 100644
--- a/Source/LexerParser/cmFortranParser.y
+++ b/Source/LexerParser/cmFortranParser.y
@@ -17,13 +17,11 @@ This file must be translated to C and modified to build everywhere.
Run bison like this:
- bison --yacc --name-prefix=cmFortran_yy
+ bison --name-prefix=cmFortran_yy
--defines=cmFortranParserTokens.h
-ocmFortranParser.cxx
cmFortranParser.y
-Modify cmFortranParser.cxx:
- - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
*/
#include "cmConfigure.h" // IWYU pragma: keep
@@ -35,7 +33,6 @@ Modify cmFortranParser.cxx:
/*-------------------------------------------------------------------------*/
#define cmFortranParser_cxx
#include "cmFortranParser.h" /* Interface to parser object. */
-#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */
/* Forward declare the lexer entry point. */
YY_DECL;
@@ -58,6 +55,7 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wfree-nonheap-object"
#endif
%}
diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h
index f66a15cf8..e250110c0 100644
--- a/Source/LexerParser/cmFortranParserTokens.h
+++ b/Source/LexerParser/cmFortranParserTokens.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.4.2. */
+/* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
@@ -31,8 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-/* Undocumented macros, especially those whose name start with YY_,
- are private implementation details. Do not rely on them. */
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
@@ -44,100 +45,66 @@
extern int cmFortran_yydebug;
#endif
-/* Token type. */
+/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
- EOSTMT = 258,
- ASSIGNMENT_OP = 259,
- GARBAGE = 260,
- CPP_LINE_DIRECTIVE = 261,
- CPP_INCLUDE = 262,
- F90PPR_INCLUDE = 263,
- COCO_INCLUDE = 264,
- F90PPR_DEFINE = 265,
- CPP_DEFINE = 266,
- F90PPR_UNDEF = 267,
- CPP_UNDEF = 268,
- CPP_IFDEF = 269,
- CPP_IFNDEF = 270,
- CPP_IF = 271,
- CPP_ELSE = 272,
- CPP_ELIF = 273,
- CPP_ENDIF = 274,
- F90PPR_IFDEF = 275,
- F90PPR_IFNDEF = 276,
- F90PPR_IF = 277,
- F90PPR_ELSE = 278,
- F90PPR_ELIF = 279,
- F90PPR_ENDIF = 280,
- COMMA = 281,
- COLON = 282,
- DCOLON = 283,
- LPAREN = 284,
- RPAREN = 285,
- UNTERMINATED_STRING = 286,
- STRING = 287,
- WORD = 288,
- CPP_INCLUDE_ANGLE = 289,
- END = 290,
- INCLUDE = 291,
- INTERFACE = 292,
- MODULE = 293,
- SUBMODULE = 294,
- USE = 295
+ YYEMPTY = -2,
+ YYEOF = 0, /* "end of file" */
+ YYerror = 256, /* error */
+ YYUNDEF = 257, /* "invalid token" */
+ EOSTMT = 258, /* EOSTMT */
+ ASSIGNMENT_OP = 259, /* ASSIGNMENT_OP */
+ GARBAGE = 260, /* GARBAGE */
+ CPP_LINE_DIRECTIVE = 261, /* CPP_LINE_DIRECTIVE */
+ CPP_INCLUDE = 262, /* CPP_INCLUDE */
+ F90PPR_INCLUDE = 263, /* F90PPR_INCLUDE */
+ COCO_INCLUDE = 264, /* COCO_INCLUDE */
+ F90PPR_DEFINE = 265, /* F90PPR_DEFINE */
+ CPP_DEFINE = 266, /* CPP_DEFINE */
+ F90PPR_UNDEF = 267, /* F90PPR_UNDEF */
+ CPP_UNDEF = 268, /* CPP_UNDEF */
+ CPP_IFDEF = 269, /* CPP_IFDEF */
+ CPP_IFNDEF = 270, /* CPP_IFNDEF */
+ CPP_IF = 271, /* CPP_IF */
+ CPP_ELSE = 272, /* CPP_ELSE */
+ CPP_ELIF = 273, /* CPP_ELIF */
+ CPP_ENDIF = 274, /* CPP_ENDIF */
+ F90PPR_IFDEF = 275, /* F90PPR_IFDEF */
+ F90PPR_IFNDEF = 276, /* F90PPR_IFNDEF */
+ F90PPR_IF = 277, /* F90PPR_IF */
+ F90PPR_ELSE = 278, /* F90PPR_ELSE */
+ F90PPR_ELIF = 279, /* F90PPR_ELIF */
+ F90PPR_ENDIF = 280, /* F90PPR_ENDIF */
+ COMMA = 281, /* COMMA */
+ COLON = 282, /* COLON */
+ DCOLON = 283, /* DCOLON */
+ LPAREN = 284, /* LPAREN */
+ RPAREN = 285, /* RPAREN */
+ UNTERMINATED_STRING = 286, /* UNTERMINATED_STRING */
+ STRING = 287, /* STRING */
+ WORD = 288, /* WORD */
+ CPP_INCLUDE_ANGLE = 289, /* CPP_INCLUDE_ANGLE */
+ END = 290, /* END */
+ INCLUDE = 291, /* INCLUDE */
+ INTERFACE = 292, /* INTERFACE */
+ MODULE = 293, /* MODULE */
+ SUBMODULE = 294, /* SUBMODULE */
+ USE = 295 /* USE */
};
+ typedef enum yytokentype yytoken_kind_t;
#endif
-/* Tokens. */
-#define EOSTMT 258
-#define ASSIGNMENT_OP 259
-#define GARBAGE 260
-#define CPP_LINE_DIRECTIVE 261
-#define CPP_INCLUDE 262
-#define F90PPR_INCLUDE 263
-#define COCO_INCLUDE 264
-#define F90PPR_DEFINE 265
-#define CPP_DEFINE 266
-#define F90PPR_UNDEF 267
-#define CPP_UNDEF 268
-#define CPP_IFDEF 269
-#define CPP_IFNDEF 270
-#define CPP_IF 271
-#define CPP_ELSE 272
-#define CPP_ELIF 273
-#define CPP_ENDIF 274
-#define F90PPR_IFDEF 275
-#define F90PPR_IFNDEF 276
-#define F90PPR_IF 277
-#define F90PPR_ELSE 278
-#define F90PPR_ELIF 279
-#define F90PPR_ENDIF 280
-#define COMMA 281
-#define COLON 282
-#define DCOLON 283
-#define LPAREN 284
-#define RPAREN 285
-#define UNTERMINATED_STRING 286
-#define STRING 287
-#define WORD 288
-#define CPP_INCLUDE_ANGLE 289
-#define END 290
-#define INCLUDE 291
-#define INTERFACE 292
-#define MODULE 293
-#define SUBMODULE 294
-#define USE 295
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
-#line 73 "cmFortranParser.y"
+#line 71 "cmFortranParser.y"
char* string;
-#line 141 "cmFortranParserTokens.h"
+#line 108 "cmFortranParserTokens.h"
};
typedef union YYSTYPE YYSTYPE;
diff --git a/Source/LexerParser/cmGccDepfileLexer.cxx b/Source/LexerParser/cmGccDepfileLexer.cxx
index a98969d59..3630f4ef8 100644
--- a/Source/LexerParser/cmGccDepfileLexer.cxx
+++ b/Source/LexerParser/cmGccDepfileLexer.cxx
@@ -994,7 +994,7 @@ case 5:
YY_RULE_SETUP
{
// A line continuation ends the current file name.
- yyextra->newDependency();
+ yyextra->newRuleOrDependency();
}
YY_BREAK
case 6:
diff --git a/Source/LexerParser/cmGccDepfileLexer.in.l b/Source/LexerParser/cmGccDepfileLexer.in.l
index 08f8577fc..c83cb75e8 100644
--- a/Source/LexerParser/cmGccDepfileLexer.in.l
+++ b/Source/LexerParser/cmGccDepfileLexer.in.l
@@ -42,7 +42,7 @@ NEWLINE \r?\n
}
{WSPACE}*\\{NEWLINE} {
// A line continuation ends the current file name.
- yyextra->newDependency();
+ yyextra->newRuleOrDependency();
}
{NEWLINE} {
// A newline ends the current file name and the current rule.
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 0f0c39a1f..0c263bb75 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -3,20 +3,52 @@
project(QtDialog)
CMake_OPTIONAL_COMPONENT(cmake-gui)
-find_package(Qt5Widgets REQUIRED)
+set (QT_COMPONENTS
+ Core
+ Widgets
+ Gui
+)
+
+set(CMake_QT_MAJOR_VERSION "A" CACHE
+ STRING "Expected Qt major version. Valid values are A (auto-select), 5, 6.")
+set(SUPPORTED_QT_VERSIONS "A" 5 6)
+set_property(CACHE CMake_QT_MAJOR_VERSION PROPERTY STRINGS ${SUPPORTED_QT_VERSIONS})
+if(NOT CMake_QT_MAJOR_VERSION STREQUAL "A")
+ if(NOT CMake_QT_MAJOR_VERSION IN_LIST SUPPORTED_QT_VERSIONS)
+ message(FATAL_ERROR "Supported Qt versions are \"${SUPPORTED_QT_VERSIONS}\"."
+ " But CMake_QT_MAJOR_VERSION is set to ${CMake_QT_MAJOR_VERSION}.")
+ endif()
+ set(INSTALLED_QT_VERSION ${CMake_QT_MAJOR_VERSION})
+else()
+ find_package(Qt6Widgets QUIET)
+ set(INSTALLED_QT_VERSION 6)
+ if(NOT Qt6Widgets_FOUND)
+ find_package(Qt5Widgets QUIET)
+ if(NOT Qt5Widgets_FOUND)
+ message(FATAL_ERROR "Could not find a valid Qt installation.")
+ endif()
+ set(INSTALLED_QT_VERSION 5)
+ endif()
+endif()
+
+find_package(Qt${INSTALLED_QT_VERSION}
+ COMPONENTS ${QT_COMPONENTS}
+ REQUIRED QUIET
+)
set(CMake_QT_EXTRA_LIBRARIES)
# Try to find the package WinExtras for the task bar progress
if(WIN32)
- find_package(Qt5WinExtras QUIET)
- if (Qt5WinExtras_FOUND)
+ find_package(Qt${INSTALLED_QT_VERSION}WinExtras QUIET)
+ if (Qt${INSTALLED_QT_VERSION}WinExtras_FOUND)
add_definitions(-DQT_WINEXTRAS)
- list(APPEND CMake_QT_EXTRA_LIBRARIES Qt5::WinExtras)
+ list(APPEND CMake_QT_EXTRA_LIBRARIES Qt${INSTALLED_QT_VERSION}::WinExtras)
+ list(APPEND QT_COMPONENTS WinExtras)
endif()
endif()
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt${INSTALLED_QT_VERSION}Widgets_EXECUTABLE_COMPILE_FLAGS}")
if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES)
list(APPEND CMake_QT_EXTRA_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES})
@@ -31,11 +63,25 @@ if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
endif()
# We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows.
-# FIXME: This should be part of Qt5 CMake scripts, but unfortunately
-# Qt5 support is missing there.
if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
- macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var)
- get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION)
+ function(_qt_get_plugin_name_with_version target out_var)
+ string(REGEX REPLACE "^Qt::(.+)" "Qt${INSTALLED_QT_VERSION}::\\1"
+ qt_plugin_with_version "${target}")
+ if(TARGET "${qt_plugin_with_version}")
+ set("${out_var}" "${qt_plugin_with_version}" PARENT_SCOPE)
+ else()
+ set("${out_var}" "" PARENT_SCOPE)
+ endif()
+ endfunction()
+ macro(install_qt_plugin _qt_plugin_name _qt_plugins_var)
+ if(TARGET "${_qt_plugin_name}")
+ get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION)
+ else()
+ _qt_get_plugin_name_with_version("Qt::${_qt_plugin_name}" _qt_plugin_with_version_name)
+ if(TARGET "${_qt_plugin_with_version_name}")
+ get_target_property(_qt_plugin_path "${_qt_plugin_with_version_name}" LOCATION)
+ endif()
+ endif()
if(EXISTS "${_qt_plugin_path}")
get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME)
get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH)
@@ -51,14 +97,34 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
${COMPONENT})
set(${_qt_plugins_var}
"${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}")
- else()
- message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found")
endif()
endmacro()
+ macro(install_qt_plugins _comps _plugins_var)
+ foreach(_qt_comp ${${_comps}})
+ if (INSTALLED_QT_VERSION VERSION_LESS 6)
+ set(_qt_module_plugins ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_PLUGINS})
+ else()
+ get_target_property(_qt_module_plugins Qt${INSTALLED_QT_VERSION}::${_qt_comp} QT_PLUGINS)
+ endif()
+ foreach(_qt_plugin ${_qt_module_plugins})
+ if (INSTALLED_QT_VERSION VERSION_GREATER_EQUAL 6)
+ # Qt6 provides the plugins as individual packages that need to be found.
+ find_package(Qt${INSTALLED_QT_VERSION}${_qt_plugin} QUIET
+ PATHS ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_DIR})
+ endif()
+ install_qt_plugin("${_qt_plugin}" "${_plugins_var}")
+ endforeach()
+ endforeach()
+ endmacro()
if(APPLE)
- install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS)
- if(TARGET Qt5::QMacStylePlugin)
- install_qt5_plugin("Qt5::QMacStylePlugin" QT_PLUGINS)
+ if (INSTALLED_QT_VERSION VERSION_EQUAL 5)
+ install_qt_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS)
+ if(TARGET Qt5::QMacStylePlugin)
+ install_qt_plugin("Qt5::QMacStylePlugin" QT_PLUGINS)
+ endif()
+ else()
+ # FIXME: Minimize plugins for Qt6.
+ install_qt_plugins(QT_COMPONENTS QT_PLUGINS)
endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
"[Paths]\nPlugins = ${_qt_plugin_dir}\n")
@@ -66,7 +132,12 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
${COMPONENT})
elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
- install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
+ if (INSTALLED_QT_VERSION VERSION_EQUAL 5)
+ install_qt_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
+ else()
+ # FIXME: Minimize plugins for Qt6.
+ install_qt_plugins(QT_COMPONENTS QT_PLUGINS)
+ endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
"[Paths]\nPlugins = ../${_qt_plugin_dir}\n")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
@@ -75,8 +146,8 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
endif()
endif()
-get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION)
-get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH)
+get_property(_Qt_Core_LOCATION TARGET Qt${INSTALLED_QT_VERSION}::Core PROPERTY LOCATION)
+get_filename_component(Qt_BIN_DIR "${_Qt_Core_LOCATION}" PATH)
if(APPLE)
get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH)
endif()
@@ -108,7 +179,7 @@ set(SRCS
WarningMessagesDialog.cxx
WarningMessagesDialog.h
)
-qt5_wrap_ui(UI_SRCS
+set(UI_SRCS
CMakeSetupDialog.ui
Compilers.ui
CrossCompiler.ui
@@ -117,7 +188,7 @@ qt5_wrap_ui(UI_SRCS
RegexExplorer.ui
WarningMessagesDialog.ui
)
-qt5_wrap_cpp(MOC_SRCS
+set(MOC_SRCS
AddCacheEntry.h
Compilers.h
CMakeSetupDialog.h
@@ -131,8 +202,18 @@ qt5_wrap_cpp(MOC_SRCS
RegexExplorer.h
WarningMessagesDialog.h
)
-qt5_add_resources(RC_SRCS CMakeSetup.qrc)
-add_library(CMakeGUIQRCLib OBJECT ${RC_SRCS})
+set(QRC_SRCS CMakeSetup.qrc)
+
+if (INSTALLED_QT_VERSION VERSION_LESS 6)
+ qt5_wrap_ui(UI_BUILT_SRCS ${UI_SRCS})
+ qt5_wrap_cpp(MOC_BUILT_SRCS ${MOC_SRCS})
+ qt5_add_resources(QRC_BUILT_SRCS ${QRC_SRCS})
+else()
+ qt_wrap_ui(UI_BUILT_SRCS ${UI_SRCS})
+ qt_wrap_cpp(MOC_BUILT_SRCS ${MOC_SRCS})
+ qt_add_resources(QRC_BUILT_SRCS ${QRC_SRCS})
+endif()
+add_library(CMakeGUIQRCLib OBJECT ${QRC_BUILT_SRCS})
if (FALSE) # CMake's bootstrap binary does not support automoc
set(CMAKE_AUTOMOC 1)
@@ -140,8 +221,8 @@ if (FALSE) # CMake's bootstrap binary does not support automoc
set(CMAKE_AUTOUIC 1)
else ()
list(APPEND SRCS
- ${UI_SRCS}
- ${MOC_SRCS})
+ ${UI_BUILT_SRCS}
+ ${MOC_BUILT_SRCS})
endif ()
if(USE_LGPL)
@@ -156,13 +237,14 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(CMakeGUILib STATIC ${SRCS})
# CMake_QT_EXTRA_LIBRARIES have to come before the main libraries on the link line
-target_link_libraries(CMakeGUILib PUBLIC CMakeLib ${CMake_QT_EXTRA_LIBRARIES} Qt5::Core Qt5::Widgets)
+target_link_libraries(CMakeGUILib PUBLIC CMakeLib ${CMake_QT_EXTRA_LIBRARIES}
+ Qt${INSTALLED_QT_VERSION}::Core Qt${INSTALLED_QT_VERSION}::Widgets)
add_library(CMakeGUIMainLib STATIC CMakeSetup.cxx)
target_link_libraries(CMakeGUIMainLib PUBLIC CMakeGUILib)
add_executable(cmake-gui WIN32 MACOSX_BUNDLE CMakeGUIExec.cxx ${MANIFEST_FILE})
-target_link_libraries(cmake-gui CMakeGUIMainLib Qt5::Core)
+target_link_libraries(cmake-gui CMakeGUIMainLib Qt${INSTALLED_QT_VERSION}::Core)
target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeGUIQRCLib>)
if(WIN32)
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index c1555a26e..5debdb89b 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -7,7 +7,6 @@
#include <QDir>
#include <QLocale>
#include <QString>
-#include <QTextCodec>
#include <QTranslator>
#include <QtPlugin>
@@ -122,9 +121,6 @@ int main(int argc, char** argv)
setlocale(LC_NUMERIC, "C");
- QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8");
- QTextCodec::setCodecForLocale(utf8_codec);
-
// tell the cmake library where cmake is
QDir cmExecDir(QApplication::applicationDirPath());
#if defined(Q_OS_MAC)
@@ -146,7 +142,7 @@ int main(int argc, char** argv)
QIcon appIcon;
appIcon.addFile(":/Icons/CMakeSetup32.png");
appIcon.addFile(":/Icons/CMakeSetup128.png");
- QApplication::setWindowIcon(appIcon);
+ QApplication::setWindowIcon(QIcon::fromTheme("cmake-gui", appIcon));
CMakeSetupDialog dialog;
dialog.show();
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 05518a99c..031308891 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -22,7 +22,6 @@
#include <QShortcut>
#include <QStatusBar>
#include <QString>
-#include <QToolButton>
#include <QUrl>
#include <QVector>
@@ -253,7 +252,7 @@ void CMakeSetupDialog::initialize()
&QCMake::propertiesChanged, this->CacheValues->cacheModel(),
&QCMakeCacheModel::setProperties);
- QObject::connect(this->ConfigureButton, &QPushButton::clicked, this,
+ QObject::connect(this->ConfigureButton, &QAbstractButton::clicked, this,
&CMakeSetupDialog::doConfigure);
QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::configureDone,
@@ -261,15 +260,17 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::generateDone,
this, &CMakeSetupDialog::exitLoop);
- QObject::connect(this->GenerateButton, &QPushButton::clicked, this,
+ QObject::connect(this->GenerateButton, &QAbstractButton::clicked, this,
&CMakeSetupDialog::doGenerate);
- QObject::connect(this->OpenProjectButton, &QPushButton::clicked, this,
+ QObject::connect(this->OpenProjectButton, &QAbstractButton::clicked, this,
&CMakeSetupDialog::doOpenProject);
- QObject::connect(this->BrowseSourceDirectoryButton, &QPushButton::clicked,
- this, &CMakeSetupDialog::doSourceBrowse);
- QObject::connect(this->BrowseBinaryDirectoryButton, &QPushButton::clicked,
- this, &CMakeSetupDialog::doBinaryBrowse);
+ QObject::connect(this->BrowseSourceDirectoryButton,
+ &QAbstractButton::clicked, this,
+ &CMakeSetupDialog::doSourceBrowse);
+ QObject::connect(this->BrowseBinaryDirectoryButton,
+ &QAbstractButton::clicked, this,
+ &CMakeSetupDialog::doBinaryBrowse);
QObject::connect(this->BinaryDirectory, &QComboBox::editTextChanged, this,
&CMakeSetupDialog::onBinaryDirectoryChanged);
@@ -324,12 +325,12 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->CacheValues->selectionModel(),
&QItemSelectionModel::selectionChanged, this,
&CMakeSetupDialog::selectionChanged);
- QObject::connect(this->RemoveEntry, &QToolButton::clicked, this,
+ QObject::connect(this->RemoveEntry, &QAbstractButton::clicked, this,
&CMakeSetupDialog::removeSelectedCacheEntries);
- QObject::connect(this->AddEntry, &QToolButton::clicked, this,
+ QObject::connect(this->AddEntry, &QAbstractButton::clicked, this,
&CMakeSetupDialog::addCacheEntry);
- QObject::connect(this->Environment, &QToolButton::clicked, this,
+ QObject::connect(this->Environment, &QAbstractButton::clicked, this,
&CMakeSetupDialog::editEnvironment);
QObject::connect(this->WarnUninitializedAction, &QAction::triggered,
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
index a5c35b1c3..c17c4140b 100644
--- a/Source/QtDialog/CMakeSetupDialog.ui
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -84,14 +84,11 @@
<item row="2" column="1">
<widget class="QComboBox" name="BinaryDirectory">
<property name="sizePolicy">
- <sizepolicy hsizetype="Ignored" vsizetype="Fixed">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="styleSheet">
- <string notr="true">padding-left: 0</string>
- </property>
<property name="editable">
<bool>true</bool>
</property>
@@ -208,7 +205,7 @@
</widget>
</item>
<item>
- <widget class="QToolButton" name="AddEntry">
+ <widget class="QPushButton" name="AddEntry">
<property name="toolTip">
<string>Add New Entry</string>
</property>
@@ -216,16 +213,13 @@
<string>&amp;Add Entry</string>
</property>
<property name="icon">
- <iconset resource="CMakeSetup.qrc">
+ <iconset theme="list-add" resource="CMakeSetup.qrc">
<normaloff>:/Icons/Plus16.png</normaloff>:/Icons/Plus16.png</iconset>
</property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
</widget>
</item>
<item>
- <widget class="QToolButton" name="RemoveEntry">
+ <widget class="QPushButton" name="RemoveEntry">
<property name="toolTip">
<string>Remove Selected Entries</string>
</property>
@@ -233,12 +227,9 @@
<string>&amp;Remove Entry</string>
</property>
<property name="icon">
- <iconset resource="CMakeSetup.qrc">
+ <iconset theme="list-remove" resource="CMakeSetup.qrc">
<normaloff>:/Icons/Delete16.png</normaloff>:/Icons/Delete16.png</iconset>
</property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
</widget>
</item>
<item>
diff --git a/Source/QtDialog/EnvironmentDialog.cxx b/Source/QtDialog/EnvironmentDialog.cxx
index 846456c8e..bf898162c 100644
--- a/Source/QtDialog/EnvironmentDialog.cxx
+++ b/Source/QtDialog/EnvironmentDialog.cxx
@@ -81,7 +81,11 @@ bool EnvironmentSearchFilter::filterAcceptsRow(int row,
auto* model = this->sourceModel();
auto key =
model->data(model->index(row, 0, parent), Qt::DisplayRole).toString();
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ return key.contains(this->filterRegularExpression());
+#else
return key.contains(this->filterRegExp());
+#endif
}
EnvironmentDialog::EnvironmentDialog(const QProcessEnvironment& environment,
@@ -102,12 +106,18 @@ EnvironmentDialog::EnvironmentDialog(const QProcessEnvironment& environment,
this->Environment->setSelectionMode(QAbstractItemView::ExtendedSelection);
this->Environment->setSelectionBehavior(QAbstractItemView::SelectRows);
- QObject::connect(this->AddEntry, &QToolButton::clicked, this,
+ QObject::connect(this->AddEntry, &QAbstractButton::clicked, this,
&EnvironmentDialog::addEntry);
- QObject::connect(this->RemoveEntry, &QToolButton::clicked, this,
+ QObject::connect(this->RemoveEntry, &QAbstractButton::clicked, this,
&EnvironmentDialog::removeSelectedEntries);
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ QObject::connect(this->Search, &QLineEdit::textChanged, this->m_filter,
+ QOverload<const QString&>::of(
+ &EnvironmentSearchFilter::setFilterRegularExpression));
+#else
QObject::connect(this->Search, &QLineEdit::textChanged, this->m_filter,
&EnvironmentSearchFilter::setFilterFixedString);
+#endif
QObject::connect(this->Environment->selectionModel(),
&QItemSelectionModel::selectionChanged, this,
&EnvironmentDialog::selectionChanged);
diff --git a/Source/QtDialog/EnvironmentDialog.ui b/Source/QtDialog/EnvironmentDialog.ui
index dea762446..ed23c2c02 100644
--- a/Source/QtDialog/EnvironmentDialog.ui
+++ b/Source/QtDialog/EnvironmentDialog.ui
@@ -46,31 +46,25 @@
</spacer>
</item>
<item>
- <widget class="QToolButton" name="AddEntry">
+ <widget class="QPushButton" name="AddEntry">
<property name="text">
<string>&amp;Add Entry</string>
</property>
<property name="icon">
- <iconset resource="CMakeSetup.qrc">
+ <iconset theme="list-add" resource="CMakeSetup.qrc">
<normaloff>:/Icons/Plus16.png</normaloff>:/Icons/Plus16.png</iconset>
</property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
</widget>
</item>
<item>
- <widget class="QToolButton" name="RemoveEntry">
+ <widget class="QPushButton" name="RemoveEntry">
<property name="text">
<string>&amp;Remove Entry</string>
</property>
<property name="icon">
- <iconset resource="CMakeSetup.qrc">
+ <iconset theme="list-remove" resource="CMakeSetup.qrc">
<normaloff>:/Icons/Delete16.png</normaloff>:/Icons/Delete16.png</iconset>
</property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
</widget>
</item>
</layout>
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index 2f41f70bf..f593f8358 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -68,9 +68,9 @@ QCMake::QCMake(QObject* p)
connect(&this->LoadPresetsTimer, &QTimer::timeout, this, [this]() {
this->loadPresets();
if (!this->PresetName.isEmpty() &&
- this->CMakePresetsFile.Presets.find(
+ this->CMakePresetsFile.ConfigurePresets.find(
std::string(this->PresetName.toLocal8Bit())) ==
- this->CMakePresetsFile.Presets.end()) {
+ this->CMakePresetsFile.ConfigurePresets.end()) {
this->setPreset(QString{});
}
});
@@ -158,7 +158,7 @@ void QCMake::setPreset(const QString& name, bool setBinary)
if (!name.isNull()) {
std::string presetName(name.toLocal8Bit());
auto const& expandedPreset =
- this->CMakePresetsFile.Presets[presetName].Expanded;
+ this->CMakePresetsFile.ConfigurePresets[presetName].Expanded;
if (expandedPreset) {
if (setBinary) {
QString binaryDir =
@@ -420,7 +420,8 @@ QCMakePropertyList QCMake::properties() const
if (!this->PresetName.isNull()) {
std::string presetName(this->PresetName.toLocal8Bit());
- auto const& p = this->CMakePresetsFile.Presets.at(presetName).Expanded;
+ auto const& p =
+ this->CMakePresetsFile.ConfigurePresets.at(presetName).Expanded;
if (p) {
for (auto const& v : p->CacheVariables) {
if (!v.second) {
@@ -535,8 +536,8 @@ void QCMake::loadPresets()
this->LastLoadPresetsResult = result;
QVector<QCMakePreset> presets;
- for (auto const& name : this->CMakePresetsFile.PresetOrder) {
- auto const& it = this->CMakePresetsFile.Presets[name];
+ for (auto const& name : this->CMakePresetsFile.ConfigurePresetOrder) {
+ auto const& it = this->CMakePresetsFile.ConfigurePresets[name];
auto const& p = it.Unexpanded;
if (p.Hidden) {
continue;
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index 22f5be19f..994df78a8 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -47,7 +47,11 @@ protected:
// check all strings for a match
foreach (QString const& str, strs) {
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ if (str.contains(this->filterRegularExpression())) {
+#else
if (str.contains(this->filterRegExp())) {
+#endif
return true;
}
}
@@ -166,7 +170,11 @@ bool QCMakeCacheView::showAdvanced() const
void QCMakeCacheView::setSearchFilter(const QString& s)
{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ this->SearchFilter->setFilterRegularExpression(s);
+#else
this->SearchFilter->setFilterFixedString(s);
+#endif
}
QCMakeCacheModel::QCMakeCacheModel(QObject* p)
diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx
index e68faba52..03d6ed140 100644
--- a/Source/QtDialog/QCMakeWidgets.cxx
+++ b/Source/QtDialog/QCMakeWidgets.cxx
@@ -1,20 +1,23 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-// FIXME: Port to QFileSystemModel from the deprecated QDirModel.
-// Be sure completion works when incrementally editing existing paths.
#define QT_DEPRECATED_WARNINGS_SINCE QT_VERSION_CHECK(5, 14, 0)
#include "QCMakeWidgets.h"
#include <utility>
-#include <QDirModel>
#include <QFileDialog>
#include <QFileInfo>
#include <QResizeEvent>
#include <QToolButton>
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
+# include <QFileSystemModel>
+#else
+# include <QDirModel>
+#endif
+
QCMakeFileEditor::QCMakeFileEditor(QWidget* p, QString var)
: QLineEdit(p)
, Variable(std::move(var))
@@ -22,7 +25,7 @@ QCMakeFileEditor::QCMakeFileEditor(QWidget* p, QString var)
this->ToolButton = new QToolButton(this);
this->ToolButton->setText("...");
this->ToolButton->setCursor(QCursor(Qt::ArrowCursor));
- QObject::connect(this->ToolButton, &QToolButton::clicked, this,
+ QObject::connect(this->ToolButton, &QAbstractButton::clicked, this,
&QCMakeFileEditor::chooseFile);
}
@@ -93,8 +96,30 @@ void QCMakePathEditor::chooseFile()
}
}
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
+// use same QFileSystemModel for all completers
+static QFileSystemModel* fileDirModel()
+
+{
+ static QFileSystemModel* m = nullptr;
+ if (!m) {
+ m = new QFileSystemModel();
+ }
+ return m;
+}
+static QFileSystemModel* pathDirModel()
+{
+ static QFileSystemModel* m = nullptr;
+ if (!m) {
+ m = new QFileSystemModel();
+ m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot);
+ }
+ return m;
+}
+#else
// use same QDirModel for all completers
static QDirModel* fileDirModel()
+
{
static QDirModel* m = nullptr;
if (!m) {
@@ -111,12 +136,19 @@ static QDirModel* pathDirModel()
}
return m;
}
+#endif
QCMakeFileCompleter::QCMakeFileCompleter(QObject* o, bool dirs)
: QCompleter(o)
{
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
+ QFileSystemModel* m = dirs ? pathDirModel() : fileDirModel();
+ this->setModel(m);
+ m->setRootPath(QString());
+#else
QDirModel* m = dirs ? pathDirModel() : fileDirModel();
this->setModel(m);
+#endif
}
QString QCMakeFileCompleter::pathFromIndex(const QModelIndex& idx) const
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
index 843574013..0dc954aa4 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -467,7 +467,7 @@ bool DumpFile(std::string const& nmPath, const char* filename,
bool bindexplib::AddObjectFile(const char* filename)
{
- return DumpFile(NmPath, filename, this->Symbols, this->DataSymbols);
+ return DumpFile(this->NmPath, filename, this->Symbols, this->DataSymbols);
}
bool bindexplib::AddDefinitionFile(const char* filename)
@@ -511,5 +511,5 @@ void bindexplib::WriteFile(FILE* file)
void bindexplib::SetNmPath(std::string const& nm)
{
- NmPath = nm;
+ this->NmPath = nm;
}
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 231a2d630..a7ce3a60e 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -5,11 +5,11 @@
#include <sstream>
#include <unordered_set>
-#include "cmCheckCustomOutputs.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmCustomCommandTypes.h"
#include "cmExecutionStatus.h"
+#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -188,17 +188,10 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
case doing_output:
case doing_outputs:
case doing_byproducts:
- if (!cmSystemTools::FileIsFullPath(copy)) {
+ if (!cmSystemTools::FileIsFullPath(copy) &&
+ cmGeneratorExpression::Find(copy) != 0) {
// This is an output to be generated, so it should be
- // under the build tree. CMake 2.4 placed this under the
- // source tree. However the only case that this change
- // will break is when someone writes
- //
- // add_custom_command(OUTPUT out.txt ...)
- //
- // and later references "${CMAKE_CURRENT_SOURCE_DIR}/out.txt".
- // This is fairly obscure so we can wait for someone to
- // complain.
+ // under the build tree.
filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
}
filename += copy;
@@ -215,8 +208,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
}
if (cmSystemTools::FileIsFullPath(filename)) {
- filename = cmSystemTools::CollapseFullPath(
- filename, status.GetMakefile().GetHomeOutputDirectory());
+ filename = cmSystemTools::CollapseFullPath(filename);
}
switch (doing) {
case doing_depfile:
@@ -304,26 +296,18 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
status.SetError("given APPEND option with no OUTPUT.");
return false;
}
-
- // Make sure the output names and locations are safe.
- if (!cmCheckCustomOutputs(output, "OUTPUT", status) ||
- !cmCheckCustomOutputs(outputs, "OUTPUTS", status) ||
- !cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
+ if (!implicit_depends.empty() && !depfile.empty() &&
+ mf.GetGlobalGenerator()->GetName() != "Ninja") {
+ // Makefiles generators does not support both at the same time
+ status.SetError("IMPLICIT_DEPENDS and DEPFILE can not both be specified.");
return false;
}
// Check for an append request.
if (append) {
- if (mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends,
- commandLines)) {
- return true;
- }
-
- // No command for this output exists.
- status.SetError(
- cmStrCat("given APPEND option with output\n ", output[0],
- "\nwhich is not already a custom command output."));
- return false;
+ mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends,
+ commandLines);
+ return true;
}
if (uses_terminal && !job_pool.empty()) {
@@ -336,15 +320,16 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
if (source.empty() && output.empty()) {
// Source is empty, use the target.
std::vector<std::string> no_depends;
- mf.AddCustomCommandToTarget(target, byproducts, no_depends, commandLines,
- cctype, comment, working.c_str(),
- escapeOldStyle, uses_terminal, depfile,
- job_pool, command_expand_lists);
+ mf.AddCustomCommandToTarget(
+ target, byproducts, no_depends, commandLines, cctype, comment,
+ working.c_str(), mf.GetPolicyStatus(cmPolicies::CMP0116), escapeOldStyle,
+ uses_terminal, depfile, job_pool, command_expand_lists);
} else if (target.empty()) {
// Target is empty, use the output.
mf.AddCustomCommandToOutput(
output, byproducts, depends, main_dependency, implicit_depends,
- commandLines, comment, working.c_str(), nullptr, false, escapeOldStyle,
+ commandLines, comment, working.c_str(),
+ mf.GetPolicyStatus(cmPolicies::CMP0116), nullptr, false, escapeOldStyle,
uses_terminal, command_expand_lists, depfile, job_pool);
} else if (!byproducts.empty()) {
status.SetError("BYPRODUCTS may not be specified with SOURCE signatures");
@@ -381,7 +366,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
// Use the old-style mode for backward compatibility.
mf.AddCustomCommandOldStyle(target, outputs, depends, source, commandLines,
- comment);
+ comment,
+ mf.GetPolicyStatus(cmPolicies::CMP0116));
}
return true;
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index aa98d8949..2b19aad4f 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -4,13 +4,13 @@
#include <utility>
-#include "cmCheckCustomOutputs.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -120,12 +120,16 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
break;
case doing_byproducts: {
std::string filename;
- if (!cmSystemTools::FileIsFullPath(copy)) {
+ if (!cmSystemTools::FileIsFullPath(copy) &&
+ cmGeneratorExpression::Find(copy) != 0) {
filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
}
filename += copy;
cmSystemTools::ConvertToUnixSlashes(filename);
- byproducts.push_back(cmSystemTools::CollapseFullPath(filename));
+ if (cmSystemTools::FileIsFullPath(filename)) {
+ filename = cmSystemTools::CollapseFullPath(filename);
+ }
+ byproducts.push_back(filename);
} break;
case doing_depends: {
std::string dep = copy;
@@ -206,17 +210,12 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
return false;
}
- // Make sure the byproduct names and locations are safe.
- if (!cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
- return false;
- }
-
// Add the utility target to the makefile.
bool escapeOldStyle = !verbatim;
cmTarget* target = mf.AddUtilityCommand(
targetName, excludeFromAll, working_directory.c_str(), byproducts, depends,
- commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists,
- job_pool);
+ commandLines, mf.GetPolicyStatus(cmPolicies::CMP0116), escapeOldStyle,
+ comment, uses_terminal, command_expand_lists, job_pool);
// Add additional user-specified source files to the target.
target->AddSources(sources);
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index f262facc3..92e04e43c 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -238,16 +238,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
status.SetError("called with IMPORTED argument but no library type.");
return false;
}
- if (type == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!mf.GetGlobalGenerator()->HasKnownObjectFileLocation(&reason)) {
- mf.IssueMessage(
- MessageType::FATAL_ERROR,
- "The OBJECT library type may not be used for IMPORTED libraries" +
- reason + ".");
- return true;
- }
- }
if (type == cmStateEnums::INTERFACE_LIBRARY) {
if (!cmGeneratorExpression::IsValidTargetName(libName)) {
status.SetError(cmStrCat(
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 87000da52..c192e2a7b 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -47,7 +47,8 @@ struct BinarySearcher
bool operator()(argument_type const& item) const
{
- return std::binary_search(m_range.begin(), m_range.end(), item);
+ return std::binary_search(this->m_range.begin(), this->m_range.end(),
+ item);
}
private:
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 356089b83..b685b73af 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmArchiveWrite.h"
+#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
@@ -81,7 +82,8 @@ struct cmArchiveWrite::Callback
};
cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
- std::string const& format, int compressionLevel)
+ std::string const& format, int compressionLevel,
+ int numThreads)
: Stream(os)
, Archive(archive_write_new())
, Disk(archive_read_disk_new())
@@ -142,6 +144,18 @@ 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_write_set_filter_option(this->Archive, "xz", "threads",
+ sNumThreads) != ARCHIVE_OK) {
+ this->Error = cmStrCat("archive_compressor_xz_options: ",
+ cm_archive_error_string(this->Archive));
+ return;
+ }
+ }
+
break;
case CompressZstd:
if (archive_write_add_filter_zstd(this->Archive) != ARCHIVE_OK) {
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index 0d33758d8..34aafe905 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -26,7 +26,7 @@ public:
}
void Clear() { this->IsValueSet = false; }
bool IsSet() const { return this->IsValueSet; }
- T Get() const { return Value; }
+ T Get() const { return this->Value; }
private:
T Value;
@@ -54,7 +54,8 @@ public:
/** Construct with output stream to which to write archive. */
cmArchiveWrite(std::ostream& os, Compress c = CompressNone,
- std::string const& format = "paxr", int compressionLevel = 0);
+ std::string const& format = "paxr", int compressionLevel = 0,
+ int numThreads = 1);
~cmArchiveWrite();
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 15edcc566..35f4c8881 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -51,7 +51,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
if (dotpos != std::string::npos) {
auto ext = cm::string_view(file).substr(dotpos + 1);
// Process only source files
- auto cm = mf.GetCMakeInstance();
+ auto* cm = mf.GetCMakeInstance();
if (dotpos > 0 && cm->IsACLikeSourceExtension(ext)) {
std::string fullname = cmStrCat(templateDirectory, '/', file);
// add the file as a class file so
diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx
index 80ada4766..a9c15c2dd 100644
--- a/Source/cmBase32.cxx
+++ b/Source/cmBase32.cxx
@@ -36,8 +36,6 @@ void Base32Encode5(const unsigned char src[5], char dst[8])
cmBase32Encoder::cmBase32Encoder() = default;
-cmBase32Encoder::~cmBase32Encoder() = default;
-
std::string cmBase32Encoder::encodeString(const unsigned char* input,
size_t len, bool padding)
{
diff --git a/Source/cmBase32.h b/Source/cmBase32.h
index 726f45d51..d70a0629e 100644
--- a/Source/cmBase32.h
+++ b/Source/cmBase32.h
@@ -17,9 +17,8 @@ class cmBase32Encoder
public:
static const char paddingChar = '=';
-public:
cmBase32Encoder();
- ~cmBase32Encoder();
+ ~cmBase32Encoder() = default;
// Encodes the given input byte sequence into a string
// @arg input Input data pointer
diff --git a/Source/cmCMakePath.cxx b/Source/cmCMakePath.cxx
index b8215dfcf..73321c68c 100644
--- a/Source/cmCMakePath.cxx
+++ b/Source/cmCMakePath.cxx
@@ -88,7 +88,8 @@ bool cmCMakePath::IsPrefix(const cmCMakePath& path) const
++prefix_it;
++path_it;
}
- return prefix_it == prefix_end;
+ return (prefix_it == prefix_end) ||
+ (prefix_it->empty() && path_it != path_end);
}
std::string cmCMakePath::FormatPath(std::string path, format fmt)
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index 720f582f9..962fdcc9b 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -37,7 +37,7 @@ public:
template <typename T>
CMakePathArgumentParser& Bind(cm::static_string_view name, T Result::*member)
{
- cmArgumentParser<Result>::Bind(name, member);
+ this->cmArgumentParser<Result>::Bind(name, member);
return *this;
}
@@ -48,12 +48,12 @@ public:
{
this->Inputs.clear();
- return cmArgumentParser<Result>::Parse(cmMakeRange(args).advance(Advance),
- &this->Inputs, keywordsMissingValue,
- parsedKeywords);
+ return this->cmArgumentParser<Result>::Parse(
+ cmMakeRange(args).advance(Advance), &this->Inputs, keywordsMissingValue,
+ parsedKeywords);
}
- const std::vector<std::string>& GetInputs() const { return Inputs; }
+ const std::vector<std::string>& GetInputs() const { return this->Inputs; }
protected:
mutable std::vector<std::string> Inputs;
@@ -74,7 +74,7 @@ public:
ArgumentParserWithOutputVariable& Bind(cm::static_string_view name,
T Result::*member)
{
- cmArgumentParser<Result>::Bind(name, member);
+ this->cmArgumentParser<Result>::Bind(name, member);
return *this;
}
@@ -84,7 +84,7 @@ public:
this->KeywordsMissingValue.clear();
this->ParsedKeywords.clear();
- return CMakePathArgumentParser<Result>::template Parse<Advance>(
+ return this->CMakePathArgumentParser<Result>::template Parse<Advance>(
args, &this->KeywordsMissingValue, &this->ParsedKeywords);
}
@@ -149,7 +149,7 @@ public:
bool getInputPath(const std::string& arg, cmExecutionStatus& status,
std::string& path)
{
- auto def = status.GetMakefile().GetDefinition(arg);
+ const auto* def = status.GetMakefile().GetDefinition(arg);
if (def == nullptr) {
status.SetError("undefined variable for input path.");
return false;
@@ -194,7 +194,7 @@ bool HandleGetCommand(std::vector<std::string> const& args,
}
return path.GetNarrowStem();
} },
- { "RELATIVE_PATH"_s,
+ { "RELATIVE_PART"_s,
[](const cmCMakePath& path, bool) -> cmCMakePath {
return path.GetRelativePath();
} },
@@ -250,9 +250,48 @@ bool HandleGetCommand(std::vector<std::string> const& args,
return true;
}
+bool HandleSetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3 || args.size() > 4) {
+ status.SetError("SET must be called with two or three arguments.");
+ return false;
+ }
+
+ if (args[1].empty()) {
+ status.SetError("Invalid name for path variable.");
+ return false;
+ }
+
+ static NormalizeParser const parser;
+
+ const auto arguments = parser.Parse(args);
+
+ if (parser.GetInputs().size() != 1) {
+ status.SetError("SET called with unexpected arguments.");
+ return false;
+ }
+
+ auto path =
+ cmCMakePath(parser.GetInputs().front(), cmCMakePath::native_format);
+
+ if (arguments.Normalize) {
+ path = path.Normal();
+ }
+
+ status.GetMakefile().AddDefinition(args[1], path.GenericString());
+
+ return true;
+}
+
bool HandleAppendCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
+ if (args[1].empty()) {
+ status.SetError("Invalid name for path variable.");
+ return false;
+ }
+
static OutputVariableParser const parser{};
const auto arguments = parser.Parse(args);
@@ -272,8 +311,8 @@ bool HandleAppendCommand(std::vector<std::string> const& args,
return true;
}
-bool HandleConcatCommand(std::vector<std::string> const& args,
- cmExecutionStatus& status)
+bool HandleAppendStringCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
static OutputVariableParser const parser{};
@@ -546,16 +585,6 @@ bool HandleRelativePathCommand(std::vector<std::string> const& args,
});
}
-bool HandleProximatePathCommand(std::vector<std::string> const& args,
- cmExecutionStatus& status)
-{
- return HandleTransformPathCommand(
- args, status,
- [](const cmCMakePath& path, const std::string& base) -> cmCMakePath {
- return path.Proximate(base);
- });
-}
-
bool HandleAbsolutePathCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -567,40 +596,6 @@ bool HandleAbsolutePathCommand(std::vector<std::string> const& args,
true);
}
-bool HandleCMakePathCommand(std::vector<std::string> const& args,
- cmExecutionStatus& status)
-{
- if (args.size() < 3 || args.size() > 4) {
- status.SetError("CMAKE_PATH must be called with two or three arguments.");
- return false;
- }
-
- static NormalizeParser const parser;
-
- const auto arguments = parser.Parse(args);
-
- if (parser.GetInputs().size() != 1) {
- status.SetError("CMAKE_PATH called with unexpected arguments.");
- return false;
- }
-
- if (args[1].empty()) {
- status.SetError("Invalid name for output variable.");
- return false;
- }
-
- auto path =
- cmCMakePath(parser.GetInputs().front(), cmCMakePath::native_format);
-
- if (arguments.Normalize) {
- path = path.Normal();
- }
-
- status.GetMakefile().AddDefinition(args[1], path.GenericString());
-
- return true;
-}
-
bool HandleNativePathCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -737,12 +732,7 @@ bool HandleCompareCommand(std::vector<std::string> const& args,
return false;
}
- std::string inputPath;
- if (!getInputPath(args[1], status, inputPath)) {
- return false;
- }
-
- cmCMakePath path1(inputPath);
+ cmCMakePath path1(args[1]);
cmCMakePath path2(args[3]);
auto result = op->second(path1, path2);
@@ -827,7 +817,7 @@ bool HandleHasStemCommand(std::vector<std::string> const& args,
[](const cmCMakePath& path) -> bool { return path.HasStem(); });
}
-bool HandleHasRelativePathCommand(std::vector<std::string> const& args,
+bool HandleHasRelativePartCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
return HandleHasItemCommand(
@@ -939,17 +929,8 @@ bool HandleIsPrefixCommand(std::vector<std::string> const& args,
bool HandleHashCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- if (args.size() < 3 || args.size() > 4) {
- status.SetError("HASH must be called with two or three arguments.");
- return false;
- }
-
- static NormalizeParser const parser;
-
- const auto arguments = parser.Parse(args);
-
- if (parser.GetInputs().size() != 1) {
- status.SetError("HASH called with unexpected arguments.");
+ if (args.size() != 3) {
+ status.SetError("HASH must be called with two arguments.");
return false;
}
@@ -958,15 +939,14 @@ bool HandleHashCommand(std::vector<std::string> const& args,
return false;
}
- const auto& output = parser.GetInputs().front();
+ const auto& output = args[2];
if (output.empty()) {
status.SetError("Invalid name for output variable.");
return false;
}
- auto hash = hash_value(arguments.Normalize ? cmCMakePath(inputPath).Normal()
- : cmCMakePath(inputPath));
+ auto hash = hash_value(cmCMakePath(inputPath).Normal());
std::ostringstream out;
out << std::setbase(16) << hash;
@@ -987,17 +967,16 @@ bool cmCMakePathCommand(std::vector<std::string> const& args,
static cmSubcommandTable const subcommand{
{ "GET"_s, HandleGetCommand },
+ { "SET"_s, HandleSetCommand },
{ "APPEND"_s, HandleAppendCommand },
- { "CONCAT"_s, HandleConcatCommand },
+ { "APPEND_STRING"_s, HandleAppendStringCommand },
{ "REMOVE_FILENAME"_s, HandleRemoveFilenameCommand },
{ "REPLACE_FILENAME"_s, HandleReplaceFilenameCommand },
{ "REMOVE_EXTENSION"_s, HandleRemoveExtensionCommand },
{ "REPLACE_EXTENSION"_s, HandleReplaceExtensionCommand },
{ "NORMAL_PATH"_s, HandleNormalPathCommand },
{ "RELATIVE_PATH"_s, HandleRelativePathCommand },
- { "PROXIMATE_PATH"_s, HandleProximatePathCommand },
{ "ABSOLUTE_PATH"_s, HandleAbsolutePathCommand },
- { "CMAKE_PATH"_s, HandleCMakePathCommand },
{ "NATIVE_PATH"_s, HandleNativePathCommand },
{ "CONVERT"_s, HandleConvertCommand },
{ "COMPARE"_s, HandleCompareCommand },
@@ -1007,7 +986,7 @@ bool cmCMakePathCommand(std::vector<std::string> const& args,
{ "HAS_FILENAME"_s, HandleHasFilenameCommand },
{ "HAS_EXTENSION"_s, HandleHasExtensionCommand },
{ "HAS_STEM"_s, HandleHasStemCommand },
- { "HAS_RELATIVE_PATH"_s, HandleHasRelativePathCommand },
+ { "HAS_RELATIVE_PART"_s, HandleHasRelativePartCommand },
{ "HAS_PARENT_PATH"_s, HandleHasParentPathCommand },
{ "IS_ABSOLUTE"_s, HandleIsAbsoluteCommand },
{ "IS_RELATIVE"_s, HandleIsRelativeCommand },
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index b7f08d2dd..1f9904364 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -191,8 +191,7 @@ bool HandleVersionMode(std::vector<std::string> const& args,
return false;
}
- status.GetMakefile().SetPolicyVersion(version_min, version_max);
- return true;
+ return status.GetMakefile().SetPolicyVersion(version_min, version_max);
}
bool HandleGetWarningMode(std::vector<std::string> const& args,
diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx
index 872cb4e63..dda366146 100644
--- a/Source/cmCMakePresetsFile.cxx
+++ b/Source/cmCMakePresetsFile.cxx
@@ -2,8 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakePresetsFile.h"
+#include <algorithm>
#include <cstdlib>
#include <functional>
+#include <iostream>
+#include <iterator>
#include <utility>
#include <cmext/string_view>
@@ -18,6 +21,26 @@
#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) \
+ { \
+ switch (ExpandMacros(field, expanders)) { \
+ case ExpandMacroResult::Error: \
+ return false; \
+ case ExpandMacroResult::Ignore: \
+ out.reset(); \
+ return true; \
+ case ExpandMacroResult::Ok: \
+ break; \
+ } \
+ }
+
namespace {
enum class CycleStatus
{
@@ -28,12 +51,13 @@ enum class CycleStatus
using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
using CacheVariable = cmCMakePresetsFile::CacheVariable;
-using UnexpandedPreset = cmCMakePresetsFile::UnexpandedPreset;
-using ExpandedPreset = cmCMakePresetsFile::ExpandedPreset;
+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 = 1;
+constexpr int MAX_VERSION = 2;
struct CMakeVersion
{
@@ -45,7 +69,9 @@ struct CMakeVersion
struct RootPresets
{
CMakeVersion CMakeMinimumRequired;
- std::vector<cmCMakePresetsFile::UnexpandedPreset> Presets;
+ std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets;
+ std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets;
+ std::vector<cmCMakePresetsFile::TestPreset> TestPresets;
};
cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
@@ -181,35 +207,43 @@ 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<UnexpandedPreset, ReadFileResult>(
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &UnexpandedPreset::WarnDev, PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &UnexpandedPreset::WarnDeprecated,
+ .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
PresetOptionalBoolHelper, false)
- .Bind("uninitialized"_s, &UnexpandedPreset::WarnUninitialized,
+ .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
PresetOptionalBoolHelper, false)
- .Bind("unusedCli"_s, &UnexpandedPreset::WarnUnusedCli,
+ .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
PresetOptionalBoolHelper, false)
- .Bind("systemVars"_s, &UnexpandedPreset::WarnSystemVars,
+ .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
PresetOptionalBoolHelper, false);
auto const PresetErrorsHelper =
- cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &UnexpandedPreset::ErrorDev, PresetOptionalBoolHelper,
- false)
- .Bind("deprecated"_s, &UnexpandedPreset::ErrorDeprecated,
+ .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
PresetOptionalBoolHelper, false);
auto const PresetDebugHelper =
- cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("output"_s, &UnexpandedPreset::DebugOutput, PresetOptionalBoolHelper,
+ .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper,
false)
- .Bind("tryCompile"_s, &UnexpandedPreset::DebugTryCompile,
+ .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
PresetOptionalBoolHelper, false)
- .Bind("find"_s, &UnexpandedPreset::DebugFind, PresetOptionalBoolHelper,
+ .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper,
false);
ReadFileResult ArchToolsetStrategyHelper(
@@ -237,18 +271,18 @@ ReadFileResult ArchToolsetStrategyHelper(
return ReadFileResult::INVALID_PRESET;
}
-std::function<ReadFileResult(UnexpandedPreset&, const Json::Value*)>
+std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
ArchToolsetHelper(
- std::string UnexpandedPreset::*valueField,
- cm::optional<ArchToolsetStrategy> UnexpandedPreset::*strategyField)
+ std::string ConfigurePreset::*valueField,
+ cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
{
auto const objectHelper =
- cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
.Bind("value", valueField, PresetStringHelper, false)
.Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
return [valueField, strategyField, objectHelper](
- UnexpandedPreset& out, const Json::Value* value) -> ReadFileResult {
+ ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
if (!value) {
(out.*valueField).clear();
out.*strategyField = cm::nullopt;
@@ -270,41 +304,395 @@ ArchToolsetHelper(
}
auto const ArchitectureHelper = ArchToolsetHelper(
- &UnexpandedPreset::Architecture, &UnexpandedPreset::ArchitectureStrategy);
+ &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy);
auto const ToolsetHelper = ArchToolsetHelper(
- &UnexpandedPreset::Toolset, &UnexpandedPreset::ToolsetStrategy);
+ &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
-auto const PresetHelper =
- cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+auto const ConfigurePresetHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &UnexpandedPreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &UnexpandedPreset::Inherits, PresetInheritsHelper,
+ .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &ConfigurePreset::Inherits, PresetInheritsHelper,
false)
- .Bind("hidden"_s, &UnexpandedPreset::Hidden, PresetBoolHelper, false)
+ .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false)
.Bind<std::nullptr_t>("vendor"_s, nullptr,
VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &UnexpandedPreset::DisplayName, PresetStringHelper,
+ .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper,
false)
- .Bind("description"_s, &UnexpandedPreset::Description, PresetStringHelper,
+ .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper,
false)
- .Bind("generator"_s, &UnexpandedPreset::Generator, PresetStringHelper,
+ .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper,
false)
.Bind("architecture"_s, ArchitectureHelper, false)
.Bind("toolset"_s, ToolsetHelper, false)
- .Bind("binaryDir"_s, &UnexpandedPreset::BinaryDir, PresetStringHelper,
+ .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper,
false)
.Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
- .Bind("cacheVariables"_s, &UnexpandedPreset::CacheVariables,
+ .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables,
VariablesHelper, false)
- .Bind("environment"_s, &UnexpandedPreset::Environment,
- EnvironmentMapHelper, 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 PresetsHelper =
- cmJSONVectorHelper<UnexpandedPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, PresetHelper);
+auto const BuildPresetHelper =
+ cmJSONObjectHelper<BuildPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &BuildPreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &BuildPreset::Inherits, PresetInheritsHelper, 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, PresetVectorStringHelper, 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, PresetInheritsHelper, 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);
@@ -320,7 +708,11 @@ auto const RootPresetsHelper =
cmJSONObjectHelper<RootPresets, ReadFileResult>(
ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
.Bind<int>("version"_s, nullptr, VersionHelper)
- .Bind("configurePresets"_s, &RootPresets::Presets, PresetsHelper, false)
+ .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,
@@ -333,23 +725,33 @@ void InheritString(std::string& child, const std::string& parent)
}
}
-void InheritOptionalBool(cm::optional<bool>& child,
- const cm::optional<bool>& parent)
+template <typename T>
+void InheritOptionalValue(cm::optional<T>& child,
+ const cm::optional<T>& parent)
{
if (!child) {
child = parent;
}
}
+template <typename T>
+void InheritVector(std::vector<T>& child, const std::vector<T>& parent)
+{
+ if (child.empty()) {
+ child = parent;
+ }
+}
+
/**
* Check preset inheritance for cycles (using a DAG check algorithm) while
* also bubbling up fields through the inheritance hierarchy, then verify
* that each preset has the required fields, either directly or through
* inheritance.
*/
+template <class T>
ReadFileResult VisitPreset(
- std::map<std::string, cmCMakePresetsFile::PresetPair>& presets,
- UnexpandedPreset& preset, std::map<std::string, CycleStatus> cycleStatus)
+ T& preset, std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets,
+ std::map<std::string, CycleStatus> cycleStatus)
{
switch (cycleStatus[preset.Name]) {
case CycleStatus::InProgress:
@@ -362,80 +764,44 @@ ReadFileResult VisitPreset(
cycleStatus[preset.Name] = CycleStatus::InProgress;
- if (preset.CacheVariables.count("") != 0) {
- return ReadFileResult::INVALID_PRESET;
- }
if (preset.Environment.count("") != 0) {
return ReadFileResult::INVALID_PRESET;
}
+ CHECK_OK(preset.VisitPresetBeforeInherit())
+
for (auto const& i : preset.Inherits) {
auto parent = presets.find(i);
if (parent == presets.end()) {
return ReadFileResult::INVALID_PRESET;
}
- if (!preset.User && parent->second.Unexpanded.User) {
+ auto& parentPreset = parent->second.Unexpanded;
+ if (!preset.User && parentPreset.User) {
return ReadFileResult::USER_PRESET_INHERITANCE;
}
- auto result = VisitPreset(presets, parent->second.Unexpanded, cycleStatus);
+ auto result = VisitPreset(parentPreset, presets, cycleStatus);
if (result != ReadFileResult::READ_OK) {
return result;
}
- InheritString(preset.Generator, parent->second.Unexpanded.Generator);
- InheritString(preset.Architecture, parent->second.Unexpanded.Architecture);
- InheritString(preset.Toolset, parent->second.Unexpanded.Toolset);
- if (!preset.ArchitectureStrategy) {
- preset.ArchitectureStrategy =
- parent->second.Unexpanded.ArchitectureStrategy;
- }
- if (!preset.ToolsetStrategy) {
- preset.ToolsetStrategy = parent->second.Unexpanded.ToolsetStrategy;
- }
- InheritString(preset.BinaryDir, parent->second.Unexpanded.BinaryDir);
- InheritOptionalBool(preset.WarnDev, parent->second.Unexpanded.WarnDev);
- InheritOptionalBool(preset.ErrorDev, parent->second.Unexpanded.ErrorDev);
- InheritOptionalBool(preset.WarnDeprecated,
- parent->second.Unexpanded.WarnDeprecated);
- InheritOptionalBool(preset.ErrorDeprecated,
- parent->second.Unexpanded.ErrorDeprecated);
- InheritOptionalBool(preset.WarnUninitialized,
- parent->second.Unexpanded.WarnUninitialized);
- InheritOptionalBool(preset.WarnUnusedCli,
- parent->second.Unexpanded.WarnUnusedCli);
- InheritOptionalBool(preset.WarnSystemVars,
- parent->second.Unexpanded.WarnSystemVars);
- for (auto const& v : parent->second.Unexpanded.CacheVariables) {
- preset.CacheVariables.insert(v);
- }
- for (auto const& v : parent->second.Unexpanded.Environment) {
+ CHECK_OK(preset.VisitPresetInherit(parentPreset))
+
+ for (auto const& v : parentPreset.Environment) {
preset.Environment.insert(v);
}
}
- if (!preset.Hidden) {
- 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;
- }
- if (preset.WarnDeprecated == false && preset.ErrorDeprecated == true) {
- return ReadFileResult::INVALID_PRESET;
- }
- }
+ CHECK_OK(preset.VisitPresetAfterInherit())
cycleStatus[preset.Name] = CycleStatus::Verified;
return ReadFileResult::READ_OK;
}
+template <class T>
ReadFileResult ComputePresetInheritance(
- std::map<std::string, cmCMakePresetsFile::PresetPair>& presets)
+ std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets)
{
std::map<std::string, CycleStatus> cycleStatus;
for (auto const& it : presets) {
@@ -443,7 +809,7 @@ ReadFileResult ComputePresetInheritance(
}
for (auto& it : presets) {
- auto result = VisitPreset(presets, it.second.Unexpanded, cycleStatus);
+ auto result = VisitPreset<T>(it.second.Unexpanded, presets, cycleStatus);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -461,22 +827,16 @@ constexpr const char* ValidPrefixes[] = {
bool PrefixesValidMacroNamespace(const std::string& str)
{
- for (auto const& prefix : ValidPrefixes) {
- if (cmHasPrefix(prefix, str)) {
- return true;
- }
- }
- return false;
+ return std::any_of(
+ std::begin(ValidPrefixes), std::end(ValidPrefixes),
+ [&str](const char* prefix) -> bool { return cmHasPrefix(prefix, str); });
}
bool IsValidMacroNamespace(const std::string& str)
{
- for (auto const& prefix : ValidPrefixes) {
- if (str == prefix) {
- return true;
- }
- }
- return false;
+ return std::any_of(
+ std::begin(ValidPrefixes), std::end(ValidPrefixes),
+ [&str](const char* prefix) -> bool { return str == prefix; });
}
enum class ExpandMacroResult
@@ -486,65 +846,186 @@ enum class ExpandMacroResult
Error,
};
-ExpandMacroResult VisitEnv(const cmCMakePresetsFile& file,
- cmCMakePresetsFile::ExpandedPreset& preset,
- std::map<std::string, CycleStatus>& envCycles,
- std::string& value, CycleStatus& status);
-ExpandMacroResult ExpandMacros(const cmCMakePresetsFile& file,
- cmCMakePresetsFile::ExpandedPreset& preset,
- std::map<std::string, CycleStatus>& envCycles,
- std::string& out);
-ExpandMacroResult ExpandMacro(const cmCMakePresetsFile& file,
- cmCMakePresetsFile::ExpandedPreset& preset,
- std::map<std::string, CycleStatus>& envCycles,
- std::string& out,
- const std::string& macroNamespace,
- const std::string& macroName);
+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);
+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);
bool ExpandMacros(const cmCMakePresetsFile& file,
- const UnexpandedPreset& preset,
- cm::optional<ExpandedPreset>& out)
+ const ConfigurePreset& preset,
+ cm::optional<ConfigurePreset>& out,
+ const std::vector<MacroExpander>& macroExpanders)
{
- out = preset;
+ std::string binaryDir = preset.BinaryDir;
+ CHECK_EXPAND(out, binaryDir, macroExpanders)
- std::map<std::string, CycleStatus> envCycles;
- for (auto const& v : out->Environment) {
- envCycles[v.first] = CycleStatus::Unvisited;
+ if (!cmSystemTools::FileIsFullPath(binaryDir)) {
+ binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
}
+ out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
+ cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
- for (auto& v : out->Environment) {
- if (v.second) {
- switch (VisitEnv(file, *out, envCycles, *v.second, envCycles[v.first])) {
- case ExpandMacroResult::Error:
- return false;
- case ExpandMacroResult::Ignore:
- out.reset();
- return true;
- case ExpandMacroResult::Ok:
- break;
+ for (auto& variable : out->CacheVariables) {
+ if (variable.second) {
+ CHECK_EXPAND(out, variable.second->Value, macroExpanders)
+ }
+ }
+
+ return true;
+}
+
+bool ExpandMacros(const cmCMakePresetsFile&, const BuildPreset&,
+ cm::optional<BuildPreset>& out,
+ const std::vector<MacroExpander>& macroExpanders)
+{
+ for (auto& target : out->Targets) {
+ CHECK_EXPAND(out, target, macroExpanders)
+ }
+
+ for (auto& nativeToolOption : out->NativeToolOptions) {
+ CHECK_EXPAND(out, nativeToolOption, macroExpanders)
+ }
+
+ return true;
+}
+
+bool ExpandMacros(const cmCMakePresetsFile&, const TestPreset&,
+ cm::optional<TestPreset>& out,
+ const std::vector<MacroExpander>& macroExpanders)
+{
+ for (auto& overwrite : out->OverwriteConfigurationFile) {
+ CHECK_EXPAND(out, overwrite, macroExpanders);
+ }
+
+ if (out->Output) {
+ CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders)
+ }
+
+ if (out->Filter) {
+ if (out->Filter->Include) {
+ CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders)
+
+ if (out->Filter->Include->Index) {
+ CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile,
+ macroExpanders);
+ }
+ }
+
+ if (out->Filter->Exclude) {
+ CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders)
+
+ if (out->Filter->Exclude->Fixtures) {
+ CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup,
+ macroExpanders)
+ CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup,
+ macroExpanders)
}
}
}
- std::string binaryDir = preset.BinaryDir;
- switch (ExpandMacros(file, *out, envCycles, binaryDir)) {
- case ExpandMacroResult::Error:
- return false;
- case ExpandMacroResult::Ignore:
- out.reset();
- return true;
- case ExpandMacroResult::Ok:
- break;
+ if (out->Execution) {
+ CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders)
}
- if (!cmSystemTools::FileIsFullPath(binaryDir)) {
- binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
+
+ return true;
+}
+
+template <class T>
+bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
+ cm::optional<T>& out)
+{
+ out.emplace(preset);
+
+ std::map<std::string, CycleStatus> envCycles;
+ for (auto const& v : out->Environment) {
+ envCycles[v.first] = CycleStatus::Unvisited;
}
- out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
- cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
- for (auto& variable : out->CacheVariables) {
- if (variable.second) {
- switch (ExpandMacros(file, *out, envCycles, variable.second->Value)) {
+ std::vector<MacroExpander> macroExpanders;
+
+ MacroExpander defaultMacroExpander =
+ [&file, &preset](const std::string& macroNamespace,
+ const std::string& macroName,
+ std::string& macroOut) -> ExpandMacroResult {
+ if (macroNamespace.empty()) {
+ if (macroName == "sourceDir") {
+ macroOut += file.SourceDir;
+ return ExpandMacroResult::Ok;
+ }
+ if (macroName == "sourceParentDir") {
+ macroOut += cmSystemTools::GetParentDirectory(file.SourceDir);
+ return ExpandMacroResult::Ok;
+ }
+ if (macroName == "sourceDirName") {
+ macroOut += cmSystemTools::GetFilenameName(file.SourceDir);
+ return ExpandMacroResult::Ok;
+ }
+ if (macroName == "presetName") {
+ macroOut += preset.Name;
+ return ExpandMacroResult::Ok;
+ }
+ if (macroName == "generator") {
+ // Generator only makes sense if preset is not hidden.
+ if (!preset.Hidden) {
+ macroOut += file.GetGeneratorForPreset(preset.Name);
+ }
+ return ExpandMacroResult::Ok;
+ }
+ if (macroName == "dollar") {
+ macroOut += '$';
+ return ExpandMacroResult::Ok;
+ }
+ }
+
+ return ExpandMacroResult::Ignore;
+ };
+
+ MacroExpander environmentMacroExpander =
+ [&macroExpanders, &out, &envCycles](
+ const std::string& macroNamespace, const std::string& macroName,
+ std::string& result) -> 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);
+ if (e != ExpandMacroResult::Ok) {
+ return e;
+ }
+ result += *v->second;
+ return ExpandMacroResult::Ok;
+ }
+ }
+
+ if (macroNamespace == "env" || macroNamespace == "penv") {
+ if (macroName.empty()) {
+ return ExpandMacroResult::Error;
+ }
+ const char* value = std::getenv(macroName.c_str());
+ if (value) {
+ result += value;
+ }
+ return ExpandMacroResult::Ok;
+ }
+
+ return ExpandMacroResult::Ignore;
+ };
+
+ macroExpanders.push_back(defaultMacroExpander);
+ macroExpanders.push_back(environmentMacroExpander);
+
+ for (auto& v : out->Environment) {
+ if (v.second) {
+ switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders)) {
case ExpandMacroResult::Error:
return false;
case ExpandMacroResult::Ignore:
@@ -556,13 +1037,11 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
}
}
- return true;
+ return ExpandMacros(file, preset, out, macroExpanders);
}
-ExpandMacroResult VisitEnv(const cmCMakePresetsFile& file,
- cmCMakePresetsFile::ExpandedPreset& preset,
- std::map<std::string, CycleStatus>& envCycles,
- std::string& value, CycleStatus& status)
+ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
+ const std::vector<MacroExpander>& macroExpanders)
{
if (status == CycleStatus::Verified) {
return ExpandMacroResult::Ok;
@@ -572,7 +1051,7 @@ ExpandMacroResult VisitEnv(const cmCMakePresetsFile& file,
}
status = CycleStatus::InProgress;
- auto e = ExpandMacros(file, preset, envCycles, value);
+ auto e = ExpandMacros(value, macroExpanders);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -580,10 +1059,8 @@ ExpandMacroResult VisitEnv(const cmCMakePresetsFile& file,
return ExpandMacroResult::Ok;
}
-ExpandMacroResult ExpandMacros(const cmCMakePresetsFile& file,
- cmCMakePresetsFile::ExpandedPreset& preset,
- std::map<std::string, CycleStatus>& envCycles,
- std::string& out)
+ExpandMacroResult ExpandMacros(
+ std::string& out, const std::vector<MacroExpander>& macroExpanders)
{
std::string result;
std::string macroNamespace;
@@ -630,8 +1107,8 @@ ExpandMacroResult ExpandMacros(const cmCMakePresetsFile& file,
case State::MacroName:
if (c == '}') {
- auto e = ExpandMacro(file, preset, envCycles, result, macroNamespace,
- macroName);
+ auto e =
+ ExpandMacro(result, macroNamespace, macroName, macroExpanders);
if (e != ExpandMacroResult::Ok) {
return e;
}
@@ -660,70 +1137,232 @@ ExpandMacroResult ExpandMacros(const cmCMakePresetsFile& file,
return ExpandMacroResult::Ok;
}
-ExpandMacroResult ExpandMacro(const cmCMakePresetsFile& file,
- cmCMakePresetsFile::ExpandedPreset& preset,
- std::map<std::string, CycleStatus>& envCycles,
- std::string& out,
+ExpandMacroResult ExpandMacro(std::string& out,
const std::string& macroNamespace,
- const std::string& macroName)
+ const std::string& macroName,
+ const std::vector<MacroExpander>& macroExpanders)
{
- if (macroNamespace.empty()) {
- if (macroName == "sourceDir") {
- out += file.SourceDir;
- return ExpandMacroResult::Ok;
+ for (auto const& macroExpander : macroExpanders) {
+ auto result = macroExpander(macroNamespace, macroName, out);
+ if (result != ExpandMacroResult::Ignore) {
+ return result;
}
- if (macroName == "sourceParentDir") {
- out += cmSystemTools::GetParentDirectory(file.SourceDir);
- return ExpandMacroResult::Ok;
+ }
+
+ if (macroNamespace == "vendor") {
+ return ExpandMacroResult::Ignore;
+ }
+
+ return ExpandMacroResult::Error;
+}
+}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit(
+ const cmCMakePresetsFile::Preset& parentPreset)
+{
+ auto& preset = *this;
+ const ConfigurePreset& parent =
+ static_cast<const ConfigurePreset&>(parentPreset);
+ InheritString(preset.Generator, parent.Generator);
+ InheritString(preset.Architecture, parent.Architecture);
+ InheritString(preset.Toolset, parent.Toolset);
+ if (!preset.ArchitectureStrategy) {
+ preset.ArchitectureStrategy = parent.ArchitectureStrategy;
+ }
+ if (!preset.ToolsetStrategy) {
+ preset.ToolsetStrategy = parent.ToolsetStrategy;
+ }
+ InheritString(preset.BinaryDir, parent.BinaryDir);
+ InheritOptionalValue(preset.WarnDev, parent.WarnDev);
+ InheritOptionalValue(preset.ErrorDev, parent.ErrorDev);
+ InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated);
+ InheritOptionalValue(preset.ErrorDeprecated, parent.ErrorDeprecated);
+ InheritOptionalValue(preset.WarnUninitialized, parent.WarnUninitialized);
+ InheritOptionalValue(preset.WarnUnusedCli, parent.WarnUnusedCli);
+ InheritOptionalValue(preset.WarnSystemVars, parent.WarnSystemVars);
+
+ for (auto const& v : parent.CacheVariables) {
+ preset.CacheVariables.insert(v);
+ }
+
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::ConfigurePreset::VisitPresetBeforeInherit()
+{
+ auto& preset = *this;
+ if (preset.Environment.count("") != 0) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit()
+{
+ auto& preset = *this;
+ if (!preset.Hidden) {
+ if (preset.Generator.empty()) {
+ return ReadFileResult::INVALID_PRESET;
}
- if (macroName == "sourceDirName") {
- out += cmSystemTools::GetFilenameName(file.SourceDir);
- return ExpandMacroResult::Ok;
+ if (preset.BinaryDir.empty()) {
+ return ReadFileResult::INVALID_PRESET;
}
- if (macroName == "presetName") {
- out += preset.Name;
- return ExpandMacroResult::Ok;
+ if (preset.WarnDev == false && preset.ErrorDev == true) {
+ return ReadFileResult::INVALID_PRESET;
}
- if (macroName == "generator") {
- out += preset.Generator;
- return ExpandMacroResult::Ok;
+ if (preset.WarnDeprecated == false && preset.ErrorDeprecated == true) {
+ return ReadFileResult::INVALID_PRESET;
}
- if (macroName == "dollar") {
- out += '$';
- return ExpandMacroResult::Ok;
+ if (preset.CacheVariables.count("") != 0) {
+ return ReadFileResult::INVALID_PRESET;
}
}
- if (macroNamespace == "env" && !macroName.empty()) {
- auto v = preset.Environment.find(macroName);
- if (v != preset.Environment.end() && v->second) {
- auto e =
- VisitEnv(file, preset, envCycles, *v->second, envCycles[macroName]);
- if (e != ExpandMacroResult::Ok) {
- return e;
- }
- out += *v->second;
- return ExpandMacroResult::Ok;
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::BuildPreset::VisitPresetInherit(
+ const cmCMakePresetsFile::Preset& parentPreset)
+{
+ auto& preset = *this;
+ const BuildPreset& parent = static_cast<const BuildPreset&>(parentPreset);
+
+ InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
+ InheritOptionalValue(preset.InheritConfigureEnvironment,
+ parent.InheritConfigureEnvironment);
+ InheritOptionalValue(preset.Jobs, parent.Jobs);
+ InheritVector(preset.Targets, parent.Targets);
+ InheritString(preset.Configuration, parent.Configuration);
+ InheritOptionalValue(preset.CleanFirst, parent.CleanFirst);
+ InheritOptionalValue(preset.Verbose, parent.Verbose);
+ InheritVector(preset.NativeToolOptions, parent.NativeToolOptions);
+
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit()
+{
+ auto& preset = *this;
+ if (!preset.Hidden && preset.ConfigurePreset.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ return ReadFileResult::READ_OK;
+}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::TestPreset::VisitPresetInherit(
+ const cmCMakePresetsFile::Preset& parentPreset)
+{
+ auto& preset = *this;
+ const TestPreset& parent = static_cast<const TestPreset&>(parentPreset);
+
+ InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
+ InheritOptionalValue(preset.InheritConfigureEnvironment,
+ parent.InheritConfigureEnvironment);
+ InheritString(preset.Configuration, parent.Configuration);
+ InheritVector(preset.OverwriteConfigurationFile,
+ parent.OverwriteConfigurationFile);
+
+ if (parent.Output) {
+ if (preset.Output) {
+ auto& output = preset.Output.value();
+ const auto& parentOutput = parent.Output.value();
+ InheritOptionalValue(output.ShortProgress, parentOutput.ShortProgress);
+ InheritOptionalValue(output.Verbosity, parentOutput.Verbosity);
+ InheritOptionalValue(output.Debug, parentOutput.Debug);
+ InheritOptionalValue(output.OutputOnFailure,
+ parentOutput.OutputOnFailure);
+ InheritOptionalValue(output.Quiet, parentOutput.Quiet);
+ InheritString(output.OutputLogFile, parentOutput.OutputLogFile);
+ InheritOptionalValue(output.LabelSummary, parentOutput.LabelSummary);
+ InheritOptionalValue(output.SubprojectSummary,
+ parentOutput.SubprojectSummary);
+ InheritOptionalValue(output.MaxPassedTestOutputSize,
+ parentOutput.MaxPassedTestOutputSize);
+ InheritOptionalValue(output.MaxFailedTestOutputSize,
+ parentOutput.MaxFailedTestOutputSize);
+ InheritOptionalValue(output.MaxTestNameWidth,
+ parentOutput.MaxTestNameWidth);
+ } else {
+ preset.Output = parent.Output;
}
}
- if (macroNamespace == "env" || macroNamespace == "penv") {
- if (macroName.empty()) {
- return ExpandMacroResult::Error;
+ if (parent.Filter) {
+ if (parent.Filter->Include) {
+ if (preset.Filter && preset.Filter->Include) {
+ auto& include = *preset.Filter->Include;
+ const auto& parentInclude = *parent.Filter->Include;
+ InheritString(include.Name, parentInclude.Name);
+ InheritString(include.Label, parentInclude.Label);
+ InheritOptionalValue(include.Index, parentInclude.Index);
+ } else {
+ if (!preset.Filter) {
+ preset.Filter.emplace();
+ }
+ preset.Filter->Include = parent.Filter->Include;
+ }
}
- const char* value = std::getenv(macroName.c_str());
- if (value) {
- out += value;
+
+ if (parent.Filter->Exclude) {
+ if (preset.Filter && preset.Filter->Exclude) {
+ auto& exclude = *preset.Filter->Exclude;
+ const auto& parentExclude = *parent.Filter->Exclude;
+ InheritString(exclude.Name, parentExclude.Name);
+ InheritString(exclude.Label, parentExclude.Label);
+ InheritOptionalValue(exclude.Fixtures, parentExclude.Fixtures);
+ } else {
+ if (!preset.Filter) {
+ preset.Filter.emplace();
+ }
+ preset.Filter->Exclude = parent.Filter->Exclude;
+ }
}
- return ExpandMacroResult::Ok;
}
- if (macroNamespace == "vendor") {
- return ExpandMacroResult::Ignore;
+ if (parent.Execution) {
+ if (preset.Execution) {
+ auto& execution = *preset.Execution;
+ const auto& parentExecution = *parent.Execution;
+ InheritOptionalValue(execution.StopOnFailure,
+ parentExecution.StopOnFailure);
+ InheritOptionalValue(execution.EnableFailover,
+ parentExecution.EnableFailover);
+ InheritOptionalValue(execution.Jobs, parentExecution.Jobs);
+ InheritString(execution.ResourceSpecFile,
+ parentExecution.ResourceSpecFile);
+ InheritOptionalValue(execution.TestLoad, parentExecution.TestLoad);
+ InheritOptionalValue(execution.ShowOnly, parentExecution.ShowOnly);
+ InheritOptionalValue(execution.Repeat, parentExecution.Repeat);
+ InheritOptionalValue(execution.InteractiveDebugging,
+ parentExecution.InteractiveDebugging);
+ InheritOptionalValue(execution.ScheduleRandom,
+ parentExecution.ScheduleRandom);
+ InheritOptionalValue(execution.Timeout, parentExecution.Timeout);
+ InheritOptionalValue(execution.NoTestsAction,
+ parentExecution.NoTestsAction);
+ } else {
+ preset.Execution = parent.Execution;
+ }
}
- return ExpandMacroResult::Error;
+ return ReadFileResult::READ_OK;
}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit()
+{
+ auto& preset = *this;
+ if (!preset.Hidden && preset.ConfigurePreset.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ return ReadFileResult::READ_OK;
}
std::string cmCMakePresetsFile::GetFilename(const std::string& sourceDir)
@@ -739,17 +1378,25 @@ std::string cmCMakePresetsFile::GetUserFilename(const std::string& sourceDir)
cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadProjectPresets(
const std::string& sourceDir, bool allowNoFiles)
{
- bool haveOneFile = false;
this->SourceDir = sourceDir;
- this->Presets.clear();
- this->PresetOrder.clear();
+ this->ClearPresets();
- std::vector<std::string> presetOrder;
- std::map<std::string, PresetPair> presetMap;
+ auto result = this->ReadProjectPresetsInternal(allowNoFiles);
+ if (result != ReadFileResult::READ_OK) {
+ this->ClearPresets();
+ }
+
+ return result;
+}
+
+cmCMakePresetsFile::ReadFileResult
+cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles)
+{
+ bool haveOneFile = false;
std::string filename = GetUserFilename(this->SourceDir);
if (cmSystemTools::FileExists(filename)) {
- auto result = this->ReadJSONFile(filename, presetOrder, presetMap, true);
+ auto result = this->ReadJSONFile(filename, true);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -758,7 +1405,7 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadProjectPresets(
filename = GetFilename(this->SourceDir);
if (cmSystemTools::FileExists(filename)) {
- auto result = this->ReadJSONFile(filename, presetOrder, presetMap, false);
+ auto result = this->ReadJSONFile(filename, false);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -770,19 +1417,56 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadProjectPresets(
: ReadFileResult::FILE_NOT_FOUND;
}
- auto result = ComputePresetInheritance(presetMap);
- if (result != ReadFileResult::READ_OK) {
- return result;
+ CHECK_OK(ComputePresetInheritance(this->ConfigurePresets))
+ CHECK_OK(ComputePresetInheritance(this->BuildPresets))
+ CHECK_OK(ComputePresetInheritance(this->TestPresets))
+
+ for (auto& it : this->ConfigurePresets) {
+ if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ return ReadFileResult::INVALID_MACRO_EXPANSION;
+ }
}
- for (auto& it : presetMap) {
+ for (auto& it : this->BuildPresets) {
+ if (!it.second.Unexpanded.Hidden) {
+ const auto configurePreset =
+ this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
+ if (configurePreset == this->ConfigurePresets.end()) {
+ return ReadFileResult::INVALID_CONFIGURE_PRESET;
+ }
+
+ if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
+ it.second.Unexpanded.Environment.insert(
+ configurePreset->second.Unexpanded.Environment.begin(),
+ configurePreset->second.Unexpanded.Environment.end());
+ }
+ }
+
+ if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
+ return ReadFileResult::INVALID_MACRO_EXPANSION;
+ }
+ }
+
+ for (auto& it : this->TestPresets) {
+ if (!it.second.Unexpanded.Hidden) {
+ const auto configurePreset =
+ this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
+ if (configurePreset == this->ConfigurePresets.end()) {
+ return ReadFileResult::INVALID_CONFIGURE_PRESET;
+ }
+
+ if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
+ it.second.Unexpanded.Environment.insert(
+ configurePreset->second.Unexpanded.Environment.begin(),
+ configurePreset->second.Unexpanded.Environment.end());
+ }
+ }
+
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
return ReadFileResult::INVALID_MACRO_EXPANSION;
}
}
- this->PresetOrder = std::move(presetOrder);
- this->Presets = std::move(presetMap);
return ReadFileResult::READ_OK;
}
@@ -821,14 +1505,18 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result)
return "Project preset inherits from user preset";
case ReadFileResult::INVALID_MACRO_EXPANSION:
return "Invalid macro expansion";
+ case ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED:
+ return "File version must be 2 or higher for build and test preset "
+ "support.";
+ case ReadFileResult::INVALID_CONFIGURE_PRESET:
+ return "Invalid \"configurePreset\" field";
}
return "Unknown error";
}
cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
- const std::string& filename, std::vector<std::string>& presetOrder,
- std::map<std::string, PresetPair>& presetMap, bool user)
+ const std::string& filename, bool user)
{
cmsys::ifstream fin(filename.c_str());
if (!fin) {
@@ -853,6 +1541,12 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
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) {
@@ -871,16 +1565,158 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
}
- for (auto& preset : presets.Presets) {
+ for (auto& preset : presets.ConfigurePresets) {
preset.User = user;
if (preset.Name.empty()) {
return ReadFileResult::INVALID_PRESET;
}
- if (!presetMap.insert({ preset.Name, { preset, cm::nullopt } }).second) {
+
+ 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;
}
- presetOrder.push_back(preset.Name);
+ 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();
+ this->BuildPresets.clear();
+ this->TestPresets.clear();
+
+ this->ConfigurePresetOrder.clear();
+ this->BuildPresetOrder.clear();
+ this->TestPresetOrder.clear();
+}
+
+void cmCMakePresetsFile::PrintPresets(
+ const std::vector<const cmCMakePresetsFile::Preset*>& presets)
+{
+ if (presets.empty()) {
+ return;
+ }
+
+ auto longestPresetName =
+ std::max_element(presets.begin(), presets.end(),
+ [](const cmCMakePresetsFile::Preset* a,
+ const cmCMakePresetsFile::Preset* b) {
+ return a->Name.length() < b->Name.length();
+ });
+ auto longestLength = (*longestPresetName)->Name.length();
+
+ for (const auto* preset : presets) {
+ std::cout << " \"" << preset->Name << '"';
+ const auto& description = preset->DisplayName;
+ if (!description.empty()) {
+ for (std::size_t i = 0; i < longestLength - preset->Name.length(); ++i) {
+ std::cout << ' ';
+ }
+ std::cout << " - " << description;
+ }
+ std::cout << '\n';
+ }
+}
+
+void cmCMakePresetsFile::PrintConfigurePresetList() const
+{
+ PrintConfigurePresetList([](const ConfigurePreset&) { return true; });
+}
+
+void cmCMakePresetsFile::PrintConfigurePresetList(
+ const std::function<bool(const ConfigurePreset&)>& filter) const
+{
+ std::vector<const cmCMakePresetsFile::Preset*> presets;
+ for (auto const& p : this->ConfigurePresetOrder) {
+ auto const& preset = this->ConfigurePresets.at(p);
+ if (!preset.Unexpanded.Hidden && preset.Expanded &&
+ filter(preset.Unexpanded)) {
+ presets.push_back(
+ static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
+ }
+ }
+
+ if (!presets.empty()) {
+ std::cout << "Available configure presets:\n\n";
+ cmCMakePresetsFile::PrintPresets(presets);
+ }
+}
+
+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) {
+ presets.push_back(
+ static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
+ }
+ }
+
+ if (!presets.empty()) {
+ std::cout << "Available build presets:\n\n";
+ cmCMakePresetsFile::PrintPresets(presets);
+ }
+}
+
+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) {
+ presets.push_back(
+ static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
+ }
+ }
+
+ if (!presets.empty()) {
+ std::cout << "Available test presets:\n\n";
+ cmCMakePresetsFile::PrintPresets(presets);
+ }
+}
+
+void cmCMakePresetsFile::PrintAllPresets() const
+{
+ this->PrintConfigurePresetList();
+ std::cout << std::endl;
+ this->PrintBuildPresetList();
+ std::cout << std::endl;
+ this->PrintTestPresetList();
+}
diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h
index f6b159a02..3067d5e07 100644
--- a/Source/cmCMakePresetsFile.h
+++ b/Source/cmCMakePresetsFile.h
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <functional>
#include <map>
#include <string>
#include <utility>
@@ -12,6 +13,28 @@
class cmCMakePresetsFile
{
public:
+ enum class ReadFileResult
+ {
+ READ_OK,
+ FILE_NOT_FOUND,
+ JSON_PARSE_ERROR,
+ INVALID_ROOT,
+ NO_VERSION,
+ INVALID_VERSION,
+ UNRECOGNIZED_VERSION,
+ INVALID_CMAKE_VERSION,
+ UNRECOGNIZED_CMAKE_VERSION,
+ INVALID_PRESETS,
+ INVALID_PRESET,
+ INVALID_VARIABLE,
+ DUPLICATE_PRESETS,
+ CYCLIC_PRESET_INHERITANCE,
+ USER_PRESET_INHERITANCE,
+ INVALID_MACRO_EXPANSION,
+ BUILD_TEST_PRESETS_UNSUPPORTED,
+ INVALID_CONFIGURE_PRESET,
+ };
+
enum class ArchToolsetStrategy
{
Set,
@@ -29,25 +52,51 @@ public:
{
public:
#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
- Preset() = default;
- Preset(const Preset& /*other*/) = default;
- Preset(Preset&& /*other*/) = default;
-
- Preset& operator=(const Preset& /*other*/) = default;
-
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
// assignment operator throwing an exception when it shouldn't. Disable the
// move assignment operator until C++17 is enabled.
- Preset& operator=(Preset&& /*other*/) = delete;
+ // Explicitly defining a copy assignment operator prevents the compiler
+ // from automatically generating a move assignment operator.
+ Preset& operator=(const Preset& /*other*/) = default;
#endif
+ virtual ~Preset() = default;
+
std::string Name;
std::vector<std::string> Inherits;
bool Hidden;
bool User;
std::string DisplayName;
std::string Description;
+
+ std::map<std::string, cm::optional<std::string>> Environment;
+
+ virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0;
+ virtual ReadFileResult VisitPresetBeforeInherit()
+ {
+ return ReadFileResult::READ_OK;
+ }
+
+ virtual ReadFileResult VisitPresetAfterInherit()
+ {
+ return ReadFileResult::READ_OK;
+ }
+ };
+
+ class ConfigurePreset : public Preset
+ {
+ public:
+#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't. Disable the
+ // move assignment operator until C++17 is enabled.
+ // Explicitly defining a copy assignment operator prevents the compiler
+ // from automatically generating a move assignment operator.
+ ConfigurePreset& operator=(const ConfigurePreset& /*other*/) = default;
+#endif
+
std::string Generator;
std::string Architecture;
cm::optional<ArchToolsetStrategy> ArchitectureStrategy;
@@ -56,7 +105,6 @@ public:
std::string BinaryDir;
std::map<std::string, cm::optional<CacheVariable>> CacheVariables;
- std::map<std::string, cm::optional<std::string>> Environment;
cm::optional<bool> WarnDev;
cm::optional<bool> ErrorDev;
@@ -69,70 +117,182 @@ public:
cm::optional<bool> DebugOutput;
cm::optional<bool> DebugTryCompile;
cm::optional<bool> DebugFind;
+
+ ReadFileResult VisitPresetInherit(const Preset& parent) override;
+ ReadFileResult VisitPresetBeforeInherit() override;
+ ReadFileResult VisitPresetAfterInherit() override;
};
- class UnexpandedPreset : public Preset
+ class BuildPreset : public Preset
{
public:
- using Preset::Preset;
+#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't. Disable the
+ // move assignment operator until C++17 is enabled.
+ // Explicitly defining a copy assignment operator prevents the compiler
+ // from automatically generating a move assignment operator.
+ BuildPreset& operator=(const BuildPreset& /*other*/) = default;
+#endif
- UnexpandedPreset() = default;
- UnexpandedPreset(const Preset& preset)
- : Preset(preset)
- {
- }
- UnexpandedPreset(Preset&& preset)
- : Preset(std::move(preset))
- {
- }
+ std::string ConfigurePreset;
+ cm::optional<bool> InheritConfigureEnvironment;
+ cm::optional<int> Jobs;
+ std::vector<std::string> Targets;
+ std::string Configuration;
+ cm::optional<bool> CleanFirst;
+ cm::optional<bool> Verbose;
+ std::vector<std::string> NativeToolOptions;
+
+ ReadFileResult VisitPresetInherit(const Preset& parent) override;
+ ReadFileResult VisitPresetAfterInherit() override;
};
- class ExpandedPreset : public Preset
+ class TestPreset : public Preset
{
public:
- using Preset::Preset;
+#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't. Disable the
+ // move assignment operator until C++17 is enabled.
+ // Explicitly defining a copy assignment operator prevents the compiler
+ // from automatically generating a move assignment operator.
+ TestPreset& operator=(const TestPreset& /*other*/) = default;
+#endif
- ExpandedPreset() = default;
- ExpandedPreset(const Preset& preset)
- : Preset(preset)
+ struct OutputOptions
{
- }
- ExpandedPreset(Preset&& preset)
- : Preset(std::move(preset))
+ enum class VerbosityEnum
+ {
+ Default,
+ Verbose,
+ Extra
+ };
+
+ cm::optional<bool> ShortProgress;
+ cm::optional<VerbosityEnum> Verbosity;
+ cm::optional<bool> Debug;
+ cm::optional<bool> OutputOnFailure;
+ cm::optional<bool> Quiet;
+ std::string OutputLogFile;
+ cm::optional<bool> LabelSummary;
+ cm::optional<bool> SubprojectSummary;
+ cm::optional<int> MaxPassedTestOutputSize;
+ cm::optional<int> MaxFailedTestOutputSize;
+ cm::optional<int> MaxTestNameWidth;
+ };
+
+ struct IncludeOptions
{
- }
+ struct IndexOptions
+ {
+ cm::optional<int> Start;
+ cm::optional<int> End;
+ cm::optional<int> Stride;
+ std::vector<int> SpecificTests;
+
+ std::string IndexFile;
+ };
+
+ std::string Name;
+ std::string Label;
+ cm::optional<IndexOptions> Index;
+ cm::optional<bool> UseUnion;
+ };
+
+ struct ExcludeOptions
+ {
+ struct FixturesOptions
+ {
+ std::string Any;
+ std::string Setup;
+ std::string Cleanup;
+ };
+
+ std::string Name;
+ std::string Label;
+ cm::optional<FixturesOptions> Fixtures;
+ };
+
+ struct FilterOptions
+ {
+ cm::optional<IncludeOptions> Include;
+ cm::optional<ExcludeOptions> Exclude;
+ };
+
+ struct ExecutionOptions
+ {
+ enum class ShowOnlyEnum
+ {
+ Human,
+ JsonV1
+ };
+
+ struct RepeatOptions
+ {
+ enum class ModeEnum
+ {
+ UntilFail,
+ UntilPass,
+ AfterTimeout
+ };
+
+ ModeEnum Mode;
+ int Count;
+ };
+
+ enum class NoTestsActionEnum
+ {
+ Default,
+ Error,
+ Ignore
+ };
+
+ cm::optional<bool> StopOnFailure;
+ cm::optional<bool> EnableFailover;
+ cm::optional<int> Jobs;
+ std::string ResourceSpecFile;
+ cm::optional<int> TestLoad;
+ cm::optional<ShowOnlyEnum> ShowOnly;
+
+ cm::optional<RepeatOptions> Repeat;
+ cm::optional<bool> InteractiveDebugging;
+ cm::optional<bool> ScheduleRandom;
+ cm::optional<int> Timeout;
+ cm::optional<NoTestsActionEnum> NoTestsAction;
+ };
+
+ std::string ConfigurePreset;
+ cm::optional<bool> InheritConfigureEnvironment;
+ std::string Configuration;
+ std::vector<std::string> OverwriteConfigurationFile;
+ cm::optional<OutputOptions> Output;
+ cm::optional<FilterOptions> Filter;
+ cm::optional<ExecutionOptions> Execution;
+
+ ReadFileResult VisitPresetInherit(const Preset& parent) override;
+ ReadFileResult VisitPresetAfterInherit() override;
};
+ template <class T>
class PresetPair
{
public:
- UnexpandedPreset Unexpanded;
- cm::optional<ExpandedPreset> Expanded;
+ T Unexpanded;
+ cm::optional<T> Expanded;
};
- std::string SourceDir;
- std::map<std::string, PresetPair> Presets;
- std::vector<std::string> PresetOrder;
+ std::map<std::string, PresetPair<ConfigurePreset>> ConfigurePresets;
+ std::map<std::string, PresetPair<BuildPreset>> BuildPresets;
+ std::map<std::string, PresetPair<TestPreset>> TestPresets;
- enum class ReadFileResult
- {
- READ_OK,
- FILE_NOT_FOUND,
- JSON_PARSE_ERROR,
- INVALID_ROOT,
- NO_VERSION,
- INVALID_VERSION,
- UNRECOGNIZED_VERSION,
- INVALID_CMAKE_VERSION,
- UNRECOGNIZED_CMAKE_VERSION,
- INVALID_PRESETS,
- INVALID_PRESET,
- INVALID_VARIABLE,
- DUPLICATE_PRESETS,
- CYCLIC_PRESET_INHERITANCE,
- USER_PRESET_INHERITANCE,
- INVALID_MACRO_EXPANSION,
- };
+ std::vector<std::string> ConfigurePresetOrder;
+ std::vector<std::string> BuildPresetOrder;
+ std::vector<std::string> TestPresetOrder;
+
+ std::string SourceDir;
static std::string GetFilename(const std::string& sourceDir);
static std::string GetUserFilename(const std::string& sourceDir);
@@ -140,9 +300,44 @@ public:
bool allowNoFiles = false);
static const char* ResultToString(ReadFileResult result);
+ std::string GetGeneratorForPreset(const std::string& presetName) const
+ {
+ auto configurePresetName = presetName;
+
+ auto buildPresetIterator = this->BuildPresets.find(presetName);
+ if (buildPresetIterator != this->BuildPresets.end()) {
+ configurePresetName =
+ buildPresetIterator->second.Unexpanded.ConfigurePreset;
+ } else {
+ auto testPresetIterator = this->TestPresets.find(presetName);
+ if (testPresetIterator != this->TestPresets.end()) {
+ configurePresetName =
+ testPresetIterator->second.Unexpanded.ConfigurePreset;
+ }
+ }
+
+ auto configurePresetIterator =
+ this->ConfigurePresets.find(configurePresetName);
+ if (configurePresetIterator != this->ConfigurePresets.end()) {
+ return configurePresetIterator->second.Unexpanded.Generator;
+ }
+
+ // This should only happen if the preset is hidden
+ // or (for build or test presets) if ConfigurePreset is invalid.
+ return "";
+ }
+
+ static void PrintPresets(
+ const std::vector<const cmCMakePresetsFile::Preset*>& presets);
+ void PrintConfigurePresetList() const;
+ void PrintConfigurePresetList(
+ const std::function<bool(const ConfigurePreset&)>& filter) const;
+ void PrintBuildPresetList() const;
+ void PrintTestPresetList() const;
+ void PrintAllPresets() const;
+
private:
- ReadFileResult ReadJSONFile(const std::string& filename,
- std::vector<std::string>& presetOrder,
- std::map<std::string, PresetPair>& presetMap,
- bool user);
+ ReadFileResult ReadProjectPresetsInternal(bool allowNoFiles);
+ ReadFileResult ReadJSONFile(const std::string& filename, bool user);
+ void ClearPresets();
};
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 8ebf6d293..438a0779a 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -221,8 +221,9 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName,
// Pass the call to the makefile instance.
std::vector<std::string> no_byproducts;
- mf->AddUtilityCommand(utilityName, (all ? false : true), nullptr,
- no_byproducts, depends2, commandLines);
+ mf->AddUtilityCommand(utilityName, !all, nullptr, no_byproducts, depends2,
+ commandLines,
+ mf->GetPolicyStatus(cmPolicies::CMP0116));
}
void CCONV cmAddCustomCommand(void* arg, const char* source,
@@ -263,7 +264,8 @@ void CCONV cmAddCustomCommand(void* arg, const char* source,
// Pass the call to the makefile instance.
const char* no_comment = nullptr;
mf->AddCustomCommandOldStyle(target, outputs2, depends2, source,
- commandLines, no_comment);
+ commandLines, no_comment,
+ mf->GetPolicyStatus(cmPolicies::CMP0116));
}
void CCONV cmAddCustomCommandToOutput(void* arg, const char* output,
@@ -298,7 +300,8 @@ void CCONV cmAddCustomCommandToOutput(void* arg, const char* output,
const char* no_comment = nullptr;
const char* no_working_dir = nullptr;
mf->AddCustomCommandToOutput(output, depends2, main_dependency, commandLines,
- no_comment, no_working_dir);
+ no_comment, no_working_dir,
+ mf->GetPolicyStatus(cmPolicies::CMP0116));
}
void CCONV cmAddCustomCommandToTarget(void* arg, const char* target,
@@ -340,7 +343,8 @@ void CCONV cmAddCustomCommandToTarget(void* arg, const char* target,
const char* no_comment = nullptr;
const char* no_working_dir = nullptr;
mf->AddCustomCommandToTarget(target, no_byproducts, no_depends, commandLines,
- cctype, no_comment, no_working_dir);
+ cctype, no_comment, no_working_dir,
+ mf->GetPolicyStatus(cmPolicies::CMP0116));
}
static void addLinkLibrary(cmMakefile* mf, std::string const& target,
@@ -550,6 +554,11 @@ void* CCONV cmAddSource(void* arg, void* arg2)
// Create the real cmSourceFile instance and copy over saved information.
cmSourceFile* rsf = mf->GetOrCreateSource(osf->FullPath);
rsf->SetProperties(osf->Properties);
+ // In case the properties contain the GENERATED property,
+ // mark the real cmSourceFile as generated.
+ if (rsf->GetIsGenerated()) {
+ rsf->MarkAsGenerated();
+ }
for (std::string const& d : osf->Depends) {
rsf->AddDepend(d);
}
@@ -562,7 +571,7 @@ void* CCONV cmAddSource(void* arg, void* arg2)
sf->SourceExtension = osf->SourceExtension;
// Store the proxy in the map so it can be re-used and deleted later.
- auto value = sf.get();
+ auto* value = sf.get();
cmCPluginAPISourceFiles[rsf] = std::move(sf);
return value;
}
@@ -583,14 +592,12 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (cmSourceFile* rsf = sf->RealSourceFile) {
- cmProp p = rsf->GetProperty(prop);
- return cmToCStr(p);
+ return cmToCStr(rsf->GetProperty(prop));
}
if (!strcmp(prop, "LOCATION")) {
return sf->FullPath.c_str();
}
- cmProp retVal = sf->Properties.GetPropertyValue(prop);
- return cmToCStr(retVal);
+ return cmToCStr(sf->Properties.GetPropertyValue(prop));
}
int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop)
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 8cf5ae9aa..620ba1979 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -4,6 +4,7 @@
#include <algorithm>
#include <cctype>
+#include <cerrno>
#include <chrono>
#include <cstdio>
#include <cstdlib>
@@ -17,6 +18,7 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/string_view>
@@ -37,6 +39,7 @@
# include <unistd.h> // IWYU pragma: keep
#endif
+#include "cmCMakePresetsFile.h"
#include "cmCTestBuildAndTestHandler.h"
#include "cmCTestBuildHandler.h"
#include "cmCTestConfigureHandler.h"
@@ -179,6 +182,7 @@ struct cmCTest::Private
// information for the --build-and-test options
std::string BinaryDir;
+ std::string TestDir;
std::string NotesFiles;
@@ -1017,6 +1021,17 @@ int cmCTest::ProcessSteps()
}
if (res != 0) {
cmCTestLog(this, ERROR_MESSAGE, "Errors while running CTest" << std::endl);
+ if (!this->Impl->OutputTestOutputOnTestFailure) {
+ const std::string lastTestLog =
+ this->GetBinaryDir() + "/Testing/Temporary/LastTest.log";
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Output from these tests are in: " << lastTestLog
+ << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Use \"--rerun-failed --output-on-failure\" to re-run the "
+ "failed cases verbosely."
+ << std::endl);
+ }
}
return res;
}
@@ -1313,11 +1328,11 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
if (result == cmsysProcess_State_Exited) {
*retVal = cmsysProcess_GetExitValue(cp);
if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) {
- OutputTestErrors(tempOutput);
+ this->OutputTestErrors(tempOutput);
}
} else if (result == cmsysProcess_State_Exception) {
if (this->Impl->OutputTestOutputOnTestFailure) {
- OutputTestErrors(tempOutput);
+ this->OutputTestErrors(tempOutput);
}
*retVal = cmsysProcess_GetExitException(cp);
std::string outerr = cmStrCat("\n*** Exception executing: ",
@@ -2048,6 +2063,13 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
i++;
this->SetNotesFiles(args[i]);
return true;
+ } else if (this->CheckArgument(arg, "--test-dir"_s)) {
+ if (i >= args.size() - 1) {
+ errormsg = "'--test-dir' requires an argument";
+ return false;
+ }
+ i++;
+ this->Impl->TestDir = std::string(args[i]);
}
cm::string_view noTestsPrefix = "--no-tests=";
@@ -2237,6 +2259,306 @@ bool cmCTest::AddVariableDefinition(const std::string& arg)
return false;
}
+void cmCTest::SetPersistentOptionIfNotEmpty(const std::string& value,
+ const std::string& optionName)
+{
+ if (!value.empty()) {
+ this->GetTestHandler()->SetPersistentOption(optionName, value.c_str());
+ this->GetMemCheckHandler()->SetPersistentOption(optionName, value.c_str());
+ }
+}
+
+bool cmCTest::SetArgsFromPreset(const std::string& presetName,
+ bool listPresets)
+{
+ const auto workingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+
+ cmCMakePresetsFile settingsFile;
+ auto result = settingsFile.ReadProjectPresets(workingDirectory);
+ if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+ cmSystemTools::Error(cmStrCat("Could not read presets from ",
+ workingDirectory, ": ",
+ cmCMakePresetsFile::ResultToString(result)));
+ return false;
+ }
+
+ if (listPresets) {
+ settingsFile.PrintTestPresetList();
+ return true;
+ }
+
+ auto presetPair = settingsFile.TestPresets.find(presetName);
+ if (presetPair == settingsFile.TestPresets.end()) {
+ cmSystemTools::Error(cmStrCat("No such test preset in ", workingDirectory,
+ ": \"", presetName, '"'));
+ settingsFile.PrintTestPresetList();
+ return false;
+ }
+
+ if (presetPair->second.Unexpanded.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden test preset in ",
+ workingDirectory, ": \"", presetName, '"'));
+ settingsFile.PrintTestPresetList();
+ return false;
+ }
+
+ auto const& expandedPreset = presetPair->second.Expanded;
+ if (!expandedPreset) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate test preset \"",
+ presetName, "\": Invalid macro expansion"));
+ settingsFile.PrintTestPresetList();
+ return false;
+ }
+
+ auto configurePresetPair =
+ settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);
+ if (configurePresetPair == settingsFile.ConfigurePresets.end()) {
+ cmSystemTools::Error(cmStrCat("No such configure preset in ",
+ workingDirectory, ": \"",
+ expandedPreset->ConfigurePreset, '"'));
+ settingsFile.PrintConfigurePresetList();
+ return false;
+ }
+
+ if (configurePresetPair->second.Unexpanded.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden configure preset in ",
+ workingDirectory, ": \"",
+ expandedPreset->ConfigurePreset, '"'));
+ settingsFile.PrintConfigurePresetList();
+ return false;
+ }
+
+ auto const& expandedConfigurePreset = configurePresetPair->second.Expanded;
+ if (!expandedConfigurePreset) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate configure preset \"",
+ expandedPreset->ConfigurePreset,
+ "\": Invalid macro expansion"));
+ return false;
+ }
+
+ auto presetEnvironment = expandedPreset->Environment;
+ for (auto const& var : presetEnvironment) {
+ if (var.second) {
+ cmSystemTools::PutEnv(cmStrCat(var.first, '=', *var.second));
+ }
+ }
+
+ if (!expandedPreset->Configuration.empty()) {
+ this->SetConfigType(expandedPreset->Configuration);
+ }
+
+ // Set build directory to value specified by the configure preset.
+ this->AddCTestConfigurationOverwrite(
+ cmStrCat("BuildDirectory=", expandedConfigurePreset->BinaryDir));
+ for (const auto& kvp : expandedPreset->OverwriteConfigurationFile) {
+ this->AddCTestConfigurationOverwrite(kvp);
+ }
+
+ if (expandedPreset->Output) {
+ this->Impl->TestProgressOutput =
+ expandedPreset->Output->ShortProgress.value_or(false);
+
+ if (expandedPreset->Output->Verbosity) {
+ const auto& verbosity = *expandedPreset->Output->Verbosity;
+ switch (verbosity) {
+ case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
+ Extra:
+ this->Impl->ExtraVerbose = true;
+ // intentional fallthrough
+ case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
+ Verbose:
+ this->Impl->Verbose = true;
+ break;
+ case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
+ Default:
+ default:
+ // leave default settings
+ break;
+ }
+ }
+
+ this->Impl->Debug = expandedPreset->Output->Debug.value_or(false);
+ this->Impl->ShowLineNumbers =
+ expandedPreset->Output->Debug.value_or(false);
+ this->Impl->OutputTestOutputOnTestFailure =
+ expandedPreset->Output->OutputOnFailure.value_or(false);
+ this->Impl->Quiet = expandedPreset->Output->Quiet.value_or(false);
+
+ if (!expandedPreset->Output->OutputLogFile.empty()) {
+ this->SetOutputLogFileName(expandedPreset->Output->OutputLogFile);
+ }
+
+ this->Impl->LabelSummary =
+ expandedPreset->Output->LabelSummary.value_or(true);
+ this->Impl->SubprojectSummary =
+ expandedPreset->Output->SubprojectSummary.value_or(true);
+
+ if (expandedPreset->Output->MaxPassedTestOutputSize) {
+ this->Impl->TestHandler.SetTestOutputSizePassed(
+ *expandedPreset->Output->MaxPassedTestOutputSize);
+ }
+
+ if (expandedPreset->Output->MaxFailedTestOutputSize) {
+ this->Impl->TestHandler.SetTestOutputSizeFailed(
+ *expandedPreset->Output->MaxFailedTestOutputSize);
+ }
+
+ if (expandedPreset->Output->MaxTestNameWidth) {
+ this->Impl->MaxTestNameWidth = *expandedPreset->Output->MaxTestNameWidth;
+ }
+ }
+
+ if (expandedPreset->Filter) {
+ if (expandedPreset->Filter->Include) {
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Include->Name, "IncludeRegularExpression");
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Include->Label, "LabelRegularExpression");
+
+ if (expandedPreset->Filter->Include->Index) {
+ if (expandedPreset->Filter->Include->Index->IndexFile.empty()) {
+ const auto& start = expandedPreset->Filter->Include->Index->Start;
+ const auto& end = expandedPreset->Filter->Include->Index->End;
+ const auto& stride = expandedPreset->Filter->Include->Index->Stride;
+ std::string indexOptions;
+ indexOptions += (start ? std::to_string(*start) : "") + ",";
+ indexOptions += (end ? std::to_string(*end) : "") + ",";
+ indexOptions += (stride ? std::to_string(*stride) : "") + ",";
+ indexOptions +=
+ cmJoin(expandedPreset->Filter->Include->Index->SpecificTests, ",");
+
+ this->SetPersistentOptionIfNotEmpty(indexOptions,
+ "TestsToRunInformation");
+ } else {
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Include->Index->IndexFile,
+ "TestsToRunInformation");
+ }
+ }
+
+ if (expandedPreset->Filter->Include->UseUnion.value_or(false)) {
+ this->GetTestHandler()->SetPersistentOption("UseUnion", "true");
+ this->GetMemCheckHandler()->SetPersistentOption("UseUnion", "true");
+ }
+ }
+
+ if (expandedPreset->Filter->Exclude) {
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Exclude->Name, "ExcludeRegularExpression");
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Exclude->Label,
+ "ExcludeLabelRegularExpression");
+
+ if (expandedPreset->Filter->Exclude->Fixtures) {
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Exclude->Fixtures->Any,
+ "ExcludeFixtureRegularExpression");
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Exclude->Fixtures->Setup,
+ "ExcludeFixtureSetupRegularExpression");
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Filter->Exclude->Fixtures->Cleanup,
+ "ExcludeFixtureCleanupRegularExpression");
+ }
+ }
+ }
+
+ if (expandedPreset->Execution) {
+ this->Impl->StopOnFailure =
+ expandedPreset->Execution->StopOnFailure.value_or(false);
+ this->Impl->Failover =
+ expandedPreset->Execution->EnableFailover.value_or(false);
+
+ if (expandedPreset->Execution->Jobs) {
+ auto jobs = *expandedPreset->Execution->Jobs;
+ this->SetParallelLevel(jobs);
+ this->Impl->ParallelLevelSetInCli = true;
+ }
+
+ this->SetPersistentOptionIfNotEmpty(
+ expandedPreset->Execution->ResourceSpecFile, "ResourceSpecFile");
+
+ if (expandedPreset->Execution->TestLoad) {
+ auto testLoad = *expandedPreset->Execution->TestLoad;
+ this->SetTestLoad(testLoad);
+ }
+
+ if (expandedPreset->Execution->ShowOnly) {
+ this->Impl->ShowOnly = true;
+
+ switch (*expandedPreset->Execution->ShowOnly) {
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::ShowOnlyEnum::
+ JsonV1:
+ this->Impl->Quiet = true;
+ this->Impl->OutputAsJson = true;
+ this->Impl->OutputAsJsonVersion = 1;
+ break;
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::ShowOnlyEnum::
+ Human:
+ // intentional fallthrough (human is the default)
+ default:
+ break;
+ }
+ }
+
+ if (expandedPreset->Execution->Repeat) {
+ this->Impl->RepeatCount = expandedPreset->Execution->Repeat->Count;
+ switch (expandedPreset->Execution->Repeat->Mode) {
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::RepeatOptions::
+ ModeEnum::UntilFail:
+ this->Impl->RepeatMode = cmCTest::Repeat::UntilFail;
+ break;
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::RepeatOptions::
+ ModeEnum::UntilPass:
+ this->Impl->RepeatMode = cmCTest::Repeat::UntilPass;
+ break;
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::RepeatOptions::
+ ModeEnum::AfterTimeout:
+ this->Impl->RepeatMode = cmCTest::Repeat::AfterTimeout;
+ break;
+ default:
+ // should never default since mode is required
+ return false;
+ }
+ }
+
+ if (expandedPreset->Execution->InteractiveDebugging) {
+ this->Impl->InteractiveDebugMode =
+ *expandedPreset->Execution->InteractiveDebugging;
+ }
+
+ if (expandedPreset->Execution->ScheduleRandom.value_or(false)) {
+ this->Impl->ScheduleType = "Random";
+ }
+
+ if (expandedPreset->Execution->Timeout) {
+ this->Impl->GlobalTimeout =
+ cmDuration(*expandedPreset->Execution->Timeout);
+ }
+
+ if (expandedPreset->Execution->NoTestsAction) {
+ switch (*expandedPreset->Execution->NoTestsAction) {
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::
+ NoTestsActionEnum::Error:
+ this->Impl->NoTestsMode = cmCTest::NoTests::Error;
+ break;
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::
+ NoTestsActionEnum::Ignore:
+ this->Impl->NoTestsMode = cmCTest::NoTests::Ignore;
+ break;
+ case cmCMakePresetsFile::TestPreset::ExecutionOptions::
+ NoTestsActionEnum::Default:
+ break;
+ default:
+ // should never default
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
// the main entry point of ctest, called from main
int cmCTest::Run(std::vector<std::string>& args, std::string* output)
{
@@ -2248,6 +2570,43 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
// copy the command line
cm::append(this->Impl->InitialCommandLineArguments, args);
+ // check if a test preset was specified
+
+ bool listPresets =
+ find(args.begin(), args.end(), "--list-presets") != args.end();
+ auto it =
+ std::find_if(args.begin(), args.end(), [](std::string const& arg) -> bool {
+ return arg == "--preset" || cmHasLiteralPrefix(arg, "--preset=");
+ });
+ if (listPresets || it != args.end()) {
+ std::string errormsg;
+ bool success;
+
+ if (listPresets) {
+ // If listing presets we don't need a presetName
+ success = this->SetArgsFromPreset("", listPresets);
+ } else {
+ if (cmHasLiteralPrefix(*it, "--preset=")) {
+ auto presetName = it->substr(9);
+ success = this->SetArgsFromPreset(presetName, listPresets);
+ } else if (++it != args.end()) {
+ auto presetName = *it;
+ success = this->SetArgsFromPreset(presetName, listPresets);
+ } else {
+ cmSystemTools::Error("'--preset' requires an argument");
+ success = false;
+ }
+ }
+
+ if (listPresets) {
+ return success ? 0 : 1;
+ }
+
+ if (!success) {
+ return 1;
+ }
+ }
+
// process the command line arguments
for (size_t i = 1; i < args.size(); ++i) {
// handle the simple commandline arguments
@@ -2319,7 +2678,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
this->Impl->ScheduleType = "Random";
}
- // pass the argument to all the handlers as well, but i may no longer be
+ // pass the argument to all the handlers as well, but it may no longer be
// set to what it was originally so I'm not sure this is working as
// intended
for (auto& handler : this->Impl->GetTestingHandlers()) {
@@ -2456,8 +2815,26 @@ int cmCTest::ExecuteTests()
handler->SetVerbose(this->Impl->Verbose);
handler->SetSubmitIndex(this->Impl->SubmitIndex);
}
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- if (!this->Initialize(cwd.c_str(), nullptr)) {
+
+ const std::string currDir = cmSystemTools::GetCurrentWorkingDirectory();
+ std::string workDir = currDir;
+ if (!this->Impl->TestDir.empty()) {
+ workDir = cmSystemTools::CollapseFullPath(this->Impl->TestDir);
+ }
+
+ 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);
+ return 1;
+ }
+ }
+
+ if (!this->Initialize(workDir.c_str(), nullptr)) {
res = 12;
cmCTestLog(this, ERROR_MESSAGE,
"Problem initializing the dashboard." << std::endl);
@@ -2465,6 +2842,10 @@ int cmCTest::ExecuteTests()
res = this->ProcessSteps();
}
this->Finalize();
+
+ if (currDir != workDir) {
+ cmSystemTools::ChangeDirectory(currDir);
+ }
}
if (res != 0) {
cmCTestLog(this, DEBUG,
@@ -2859,7 +3240,7 @@ bool cmCTest::GetFailover() const
bool cmCTest::GetTestProgressOutput() const
{
- return this->Impl->TestProgressOutput;
+ return this->Impl->TestProgressOutput && !GetExtraVerbose();
}
bool cmCTest::GetVerbose() const
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index e12f8b055..4669a1cc2 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -461,6 +461,9 @@ public:
void SetRunCurrentScript(bool value);
private:
+ void SetPersistentOptionIfNotEmpty(const std::string& value,
+ const std::string& optionName);
+
int GenerateNotesFile(const std::string& files);
void BlockTestErrorDiagnostics();
@@ -484,6 +487,9 @@ private:
/** add a variable definition from a command line -D value */
bool AddVariableDefinition(const std::string& arg);
+ /** set command line arguments read from a test preset */
+ bool SetArgsFromPreset(const std::string& presetName, bool listPresets);
+
/** parse and process most common command line arguments */
bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args,
std::string& errormsg);
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 8d1a5fd3f..1a950dfb0 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -183,7 +183,7 @@ bool cmCacheManager::ReadPropertyEntry(const std::string& entryKey,
if (entryKey.size() > plen && *(end - plen) == '-' &&
strcmp(end - plen + 1, p) == 0) {
std::string key = entryKey.substr(0, entryKey.size() - plen);
- if (auto entry = this->GetCacheEntry(key)) {
+ if (auto* entry = this->GetCacheEntry(key)) {
// Store this property on its entry.
entry->SetProperty(p, e.Value.c_str());
} else {
@@ -498,7 +498,7 @@ const cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry(
cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (const auto* entry = this->GetCacheEntry(key)) {
if (entry->Initialized) {
return &entry->GetValue();
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index 9aebffc0d..7a9a7dc41 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -74,7 +74,7 @@ public:
cmProp GetCacheEntryValue(const std::string& key) const
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (const auto* entry = this->GetCacheEntry(key)) {
return &entry->GetValue();
}
return nullptr;
@@ -82,14 +82,14 @@ public:
void SetCacheEntryValue(std::string const& key, std::string const& value)
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (auto* entry = this->GetCacheEntry(key)) {
entry->SetValue(value.c_str());
}
}
cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) const
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (const auto* entry = this->GetCacheEntry(key)) {
return entry->GetType();
}
return cmStateEnums::UNINITIALIZED;
@@ -98,7 +98,7 @@ public:
std::vector<std::string> GetCacheEntryPropertyList(
std::string const& key) const
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (const auto* entry = this->GetCacheEntry(key)) {
return entry->GetPropertyList();
}
return {};
@@ -107,7 +107,7 @@ public:
cmProp GetCacheEntryProperty(std::string const& key,
std::string const& propName) const
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (const auto* entry = this->GetCacheEntry(key)) {
return entry->GetProperty(propName);
}
return nullptr;
@@ -116,7 +116,7 @@ public:
bool GetCacheEntryPropertyAsBool(std::string const& key,
std::string const& propName) const
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (const auto* entry = this->GetCacheEntry(key)) {
return entry->GetPropertyAsBool(propName);
}
return false;
@@ -126,7 +126,7 @@ public:
std::string const& propName,
std::string const& value)
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (auto* entry = this->GetCacheEntry(key)) {
entry->SetProperty(propName, value.c_str());
}
}
@@ -134,7 +134,7 @@ public:
void SetCacheEntryBoolProperty(std::string const& key,
std::string const& propName, bool value)
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (auto* entry = this->GetCacheEntry(key)) {
entry->SetProperty(propName, value);
}
}
@@ -142,7 +142,7 @@ public:
void RemoveCacheEntryProperty(std::string const& key,
std::string const& propName)
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (auto* entry = this->GetCacheEntry(key)) {
entry->SetProperty(propName, nullptr);
}
}
@@ -152,7 +152,7 @@ public:
std::string const& value,
bool asString = false)
{
- if (auto entry = this->GetCacheEntry(key)) {
+ if (auto* entry = this->GetCacheEntry(key)) {
entry->AppendProperty(propName, value, asString);
}
}
diff --git a/Source/cmCheckCustomOutputs.cxx b/Source/cmCheckCustomOutputs.cxx
deleted file mode 100644
index 7645c8808..000000000
--- a/Source/cmCheckCustomOutputs.cxx
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCheckCustomOutputs.h"
-
-#include "cmExecutionStatus.h"
-#include "cmMakefile.h"
-#include "cmStringAlgorithms.h"
-#include "cmSystemTools.h"
-
-bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
- cm::string_view keyword, cmExecutionStatus& status)
-{
- cmMakefile& mf = status.GetMakefile();
-
- for (std::string const& o : outputs) {
- // Make sure the file will not be generated into the source
- // directory during an out of source build.
- if (!mf.CanIWriteThisFile(o)) {
- status.SetError(
- cmStrCat("attempted to have a file\n ", o,
- "\nin a source directory as an output of custom command."));
- cmSystemTools::SetFatalErrorOccured();
- return false;
- }
-
- // Make sure the output file name has no invalid characters.
- std::string::size_type pos = o.find_first_of("#<>");
- if (pos != std::string::npos) {
- status.SetError(cmStrCat("called with ", keyword, " containing a \"",
- o[pos], "\". This character is not allowed."));
- return false;
- }
- }
-
- return true;
-}
diff --git a/Source/cmCheckCustomOutputs.h b/Source/cmCheckCustomOutputs.h
deleted file mode 100644
index 2752ed468..000000000
--- a/Source/cmCheckCustomOutputs.h
+++ /dev/null
@@ -1,15 +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>
-#include <vector>
-
-#include <cm/string_view>
-
-class cmExecutionStatus;
-
-bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
- cm::string_view keyword, cmExecutionStatus& status);
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index d4f502226..deddba8ef 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -228,7 +228,7 @@ int cmCommandArgumentParserHelper::ParseString(std::string const& str,
yyscan_t yyscanner;
cmCommandArgument_yylex_init(&yyscanner);
- auto scanBuf = cmCommandArgument_yy_scan_string(str.c_str(), yyscanner);
+ auto* scanBuf = cmCommandArgument_yy_scan_string(str.c_str(), yyscanner);
cmCommandArgument_yyset_extra(this, yyscanner);
cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode);
int res = cmCommandArgument_yyparse(yyscanner);
@@ -240,7 +240,7 @@ int cmCommandArgumentParserHelper::ParseString(std::string const& str,
this->CleanupParser();
- if (Verbose) {
+ if (this->Verbose) {
std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
<< std::endl;
}
diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h
new file mode 100644
index 000000000..cbedf0a9c
--- /dev/null
+++ b/Source/cmCommandLineArgument.h
@@ -0,0 +1,159 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+template <typename FunctionSignature>
+struct cmCommandLineArgument
+{
+ enum class Values
+ {
+ Zero,
+ One,
+ Two,
+ ZeroOrOne,
+ OneOrMore
+ };
+
+ std::string InvalidSyntaxMessage;
+ std::string InvalidValueMessage;
+ std::string Name;
+ Values Type;
+ std::function<FunctionSignature> StoreCall;
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, Values t, FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n))
+ , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
+ , Name(std::move(n))
+ , Type(t)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
+ FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n))
+ , InvalidValueMessage(std::move(failedMsg))
+ , Name(std::move(n))
+ , Type(t)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ bool matches(std::string const& input) const
+ {
+ return (this->Type == Values::Zero) ? (input == this->Name)
+ : cmHasPrefix(input, this->Name);
+ }
+
+ template <typename T, typename... CallState>
+ bool parse(std::string const& input, T& index,
+ 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) {
+ if (input.size() == this->Name.size()) {
+ parseState =
+ this->StoreCall(std::string{}, std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ } else {
+ parseState = ParseMode::SyntaxError;
+ }
+
+ } else if (this->Type == Values::One || this->Type == Values::ZeroOrOne) {
+ if (input.size() == this->Name.size()) {
+ ++index;
+ if (index >= allArgs.size() || allArgs[index][0] == '-') {
+ if (this->Type == Values::ZeroOrOne) {
+ parseState =
+ this->StoreCall(std::string{}, std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ } else {
+ parseState = ParseMode::ValueError;
+ }
+ } else {
+ parseState =
+ this->StoreCall(allArgs[index], std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
+ } 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::SyntaxError;
+ parseState = ParseMode::ValueError;
+ } else if (possible_value[0] == '=') {
+ possible_value.remove_prefix(1);
+ if (possible_value.empty()) {
+ parseState = ParseMode::ValueError;
+ } else {
+ parseState = this->StoreCall(std::string(possible_value),
+ std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
+ }
+ if (parseState == ParseMode::Valid) {
+ parseState = this->StoreCall(std::string(possible_value),
+ std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
+ }
+ } else if (this->Type == Values::Two) {
+ if (input.size() == this->Name.size()) {
+ if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' ||
+ allArgs[index + 2][0] == '-') {
+ parseState = ParseMode::ValueError;
+ } else {
+ index += 2;
+ parseState =
+ this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]),
+ std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
+ }
+ } else if (this->Type == Values::OneOrMore) {
+ if (input.size() == this->Name.size()) {
+ auto nextValueIndex = index + 1;
+ if (nextValueIndex >= allArgs.size() || allArgs[index + 1][0] == '-') {
+ parseState = ParseMode::ValueError;
+ } else {
+ std::string buffer = allArgs[nextValueIndex++];
+ while (nextValueIndex < allArgs.size() &&
+ allArgs[nextValueIndex][0] != '-') {
+ buffer = cmStrCat(buffer, ";", allArgs[nextValueIndex++]);
+ }
+ parseState =
+ this->StoreCall(buffer, std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
+ }
+ }
+
+ if (parseState == ParseMode::SyntaxError) {
+ cmSystemTools::Error(this->InvalidSyntaxMessage);
+ } else if (parseState == ParseMode::ValueError) {
+ cmSystemTools::Error(this->InvalidValueMessage);
+ }
+ return (parseState == ParseMode::Valid);
+ }
+};
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index c94f12886..9e5b78351 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -17,6 +17,7 @@
#include "cmBreakCommand.h"
#include "cmBuildCommand.h"
#include "cmCMakeMinimumRequired.h"
+#include "cmCMakePathCommand.h"
#include "cmCMakePolicyCommand.h"
#include "cmCommand.h"
#include "cmConfigureFileCommand.h"
@@ -118,11 +119,19 @@
void GetScriptingCommands(cmState* state)
{
- state->AddBuiltinCommand("break", cmBreakCommand);
+ state->AddFlowControlCommand("break", cmBreakCommand);
+ state->AddFlowControlCommand("continue", cmContinueCommand);
+ state->AddFlowControlCommand("foreach", cmForEachCommand);
+ state->AddFlowControlCommand("function", cmFunctionCommand);
+ state->AddFlowControlCommand("if", cmIfCommand);
+ state->AddFlowControlCommand("macro", cmMacroCommand);
+ state->AddFlowControlCommand("return", cmReturnCommand);
+ state->AddFlowControlCommand("while", cmWhileCommand);
+
state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired);
+ state->AddBuiltinCommand("cmake_path", cmCMakePathCommand);
state->AddBuiltinCommand("cmake_policy", cmCMakePolicyCommand);
state->AddBuiltinCommand("configure_file", cmConfigureFileCommand);
- state->AddBuiltinCommand("continue", cmContinueCommand);
state->AddBuiltinCommand("exec_program", cmExecProgramCommand);
state->AddBuiltinCommand("execute_process", cmExecuteProcessCommand);
state->AddBuiltinCommand("file", cmFileCommand);
@@ -131,26 +140,21 @@ void GetScriptingCommands(cmState* state)
state->AddBuiltinCommand("find_package", cmFindPackage);
state->AddBuiltinCommand("find_path", cmFindPath);
state->AddBuiltinCommand("find_program", cmFindProgram);
- state->AddBuiltinCommand("foreach", cmForEachCommand);
- state->AddBuiltinCommand("function", cmFunctionCommand);
state->AddBuiltinCommand("get_cmake_property", cmGetCMakePropertyCommand);
state->AddBuiltinCommand("get_directory_property",
cmGetDirectoryPropertyCommand);
state->AddBuiltinCommand("get_filename_component",
cmGetFilenameComponentCommand);
state->AddBuiltinCommand("get_property", cmGetPropertyCommand);
- state->AddBuiltinCommand("if", cmIfCommand);
state->AddBuiltinCommand("include", cmIncludeCommand);
state->AddBuiltinCommand("include_guard", cmIncludeGuardCommand);
state->AddBuiltinCommand("list", cmListCommand);
- state->AddBuiltinCommand("macro", cmMacroCommand);
state->AddBuiltinCommand("make_directory", cmMakeDirectoryCommand);
state->AddBuiltinCommand("mark_as_advanced", cmMarkAsAdvancedCommand);
state->AddBuiltinCommand("math", cmMathCommand);
state->AddBuiltinCommand("message", cmMessageCommand);
state->AddBuiltinCommand("option", cmOptionCommand);
state->AddBuiltinCommand("cmake_parse_arguments", cmParseArgumentsCommand);
- state->AddBuiltinCommand("return", cmReturnCommand);
state->AddBuiltinCommand("separate_arguments", cmSeparateArgumentsCommand);
state->AddBuiltinCommand("set", cmSetCommand);
state->AddBuiltinCommand("set_directory_properties",
@@ -159,7 +163,6 @@ void GetScriptingCommands(cmState* state)
state->AddBuiltinCommand("site_name", cmSiteNameCommand);
state->AddBuiltinCommand("string", cmStringCommand);
state->AddBuiltinCommand("unset", cmUnsetCommand);
- state->AddBuiltinCommand("while", cmWhileCommand);
state->AddUnexpectedCommand(
"else",
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 2b7c9f683..228cff7ae 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -27,7 +27,7 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
, GlobalCommonGenerator(static_cast<cmGlobalCommonGenerator*>(
gt->LocalGenerator->GetGlobalGenerator()))
- , ConfigNames(LocalCommonGenerator->GetConfigNames())
+ , ConfigNames(this->LocalCommonGenerator->GetConfigNames())
{
}
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index b9f15b70e..6225a4a9e 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -957,6 +957,9 @@ void cmComputeLinkInformation::AddLinkExtension(std::string const& e,
}
}
+// XXX(clang-tidy): This method's const-ness is platform dependent, so we
+// cannot make it `const` as `clang-tidy` wants us to.
+// NOLINTNEXTLINE(readability-make-member-function-const)
std::string cmComputeLinkInformation::CreateExtensionRegex(
std::vector<std::string> const& exts, LinkType type)
{
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 1f22ce634..85a9d9cf1 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -525,7 +525,7 @@ void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
void cmComputeTargetDepends::DisplaySideEffects()
{
fprintf(stderr, "The side effects are:\n");
- int n = static_cast<int>(SideEffects.size());
+ int n = static_cast<int>(this->SideEffects.size());
for (int depender_index = 0; depender_index < n; ++depender_index) {
cmGeneratorTarget const* depender = this->Targets[depender_index];
fprintf(stderr, "target %d is [%s]\n", depender_index,
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 14f10bd74..62bc52691 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -271,10 +271,10 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
{
// Use the policy if it is set.
if (this->Policy12Status == cmPolicies::NEW) {
- return GetBooleanValue(newArg);
+ return this->GetBooleanValue(newArg);
}
if (this->Policy12Status == cmPolicies::OLD) {
- return GetBooleanValueOld(newArg, oneArg);
+ return this->GetBooleanValueOld(newArg, oneArg);
}
// Check policy only if old and new results differ.
@@ -367,7 +367,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
reducible = 0;
auto arg = newArgs.begin();
while (arg != newArgs.end()) {
- if (IsKeyword(keyParenL, *arg)) {
+ if (this->IsKeyword(keyParenL, *arg)) {
// search for the closing paren for this opening one
cmArgumentList::iterator argClose;
argClose = arg;
@@ -531,7 +531,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
argP1 = arg;
this->IncrementArguments(newArgs, argP1, argP2);
if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- IsKeyword(keyMATCHES, *argP1)) {
+ this->IsKeyword(keyMATCHES, *argP1)) {
def = this->GetDefinitionIfUnquoted(*arg);
if (!def) {
def = &arg->GetValue();
@@ -707,8 +707,8 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs,
cmArgumentList::iterator argP2;
while (arg != newArgs.end()) {
argP1 = arg;
- IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && IsKeyword(keyNOT, *arg)) {
+ this->IncrementArguments(newArgs, argP1, argP2);
+ if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) {
bool rhs = this->GetBooleanValueWithAutoDereference(
*argP1, errorString, status);
this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2);
@@ -735,8 +735,8 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs,
cmArgumentList::iterator argP2;
while (arg != newArgs.end()) {
argP1 = arg;
- IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && IsKeyword(keyAND, *argP1) &&
+ this->IncrementArguments(newArgs, argP1, argP2);
+ if (argP1 != newArgs.end() && this->IsKeyword(keyAND, *argP1) &&
argP2 != newArgs.end()) {
lhs =
this->GetBooleanValueWithAutoDereference(*arg, errorString, status);
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index cf32b051d..aeca6b42a 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -16,8 +16,9 @@
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
#cmakedefine HAVE_UNSETENV
-#cmakedefine CMAKE_USE_ELF_PARSER
-#cmakedefine CMAKE_USE_MACH_PARSER
+#cmakedefine CMake_USE_ELF_PARSER
+#cmakedefine CMake_USE_MACH_PARSER
+#cmakedefine CMake_USE_XCOFF_PARSER
#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
#define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index 68322cc0e..edd261d9d 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -3,11 +3,15 @@
#include "cmConfigureFileCommand.h"
#include <set>
+#include <sstream>
#include <cm/string_view>
#include <cmext/string_view>
+#include <sys/types.h>
+
#include "cmExecutionStatus.h"
+#include "cmFSPermissions.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmNewLineStyle.h"
@@ -60,7 +64,19 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
}
bool copyOnly = false;
bool escapeQuotes = false;
- bool use_source_permissions = true;
+ bool useSourcePermissions = false;
+ bool noSourcePermissions = false;
+ bool filePermissions = false;
+ std::vector<std::string> filePermissionOptions;
+
+ enum class Doing
+ {
+ DoingNone,
+ DoingFilePermissions,
+ DoneFilePermissions
+ };
+
+ Doing doing = Doing::DoingNone;
static std::set<cm::string_view> noopOptions = {
/* Legacy. */
@@ -78,6 +94,9 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
bool atOnly = false;
for (unsigned int i = 2; i < args.size(); ++i) {
if (args[i] == "COPYONLY") {
+ if (doing == Doing::DoingFilePermissions) {
+ doing = Doing::DoneFilePermissions;
+ }
copyOnly = true;
if (newLineStyle.IsValid()) {
status.SetError("COPYONLY could not be used in combination "
@@ -85,13 +104,49 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
return false;
}
} else if (args[i] == "ESCAPE_QUOTES") {
+ if (doing == Doing::DoingFilePermissions) {
+ doing = Doing::DoneFilePermissions;
+ }
escapeQuotes = true;
} else if (args[i] == "@ONLY") {
+ if (doing == Doing::DoingFilePermissions) {
+ doing = Doing::DoneFilePermissions;
+ }
atOnly = true;
} else if (args[i] == "NO_SOURCE_PERMISSIONS") {
- use_source_permissions = false;
+ if (doing == Doing::DoingFilePermissions) {
+ status.SetError(" given both FILE_PERMISSIONS and "
+ "NO_SOURCE_PERMISSIONS. Only one option allowed.");
+ return false;
+ }
+ noSourcePermissions = true;
+ } else if (args[i] == "USE_SOURCE_PERMISSIONS") {
+ if (doing == Doing::DoingFilePermissions) {
+ status.SetError(" given both FILE_PERMISSIONS and "
+ "USE_SOURCE_PERMISSIONS. Only one option allowed.");
+ return false;
+ }
+ useSourcePermissions = true;
+ } else if (args[i] == "FILE_PERMISSIONS") {
+ if (useSourcePermissions) {
+ status.SetError(" given both FILE_PERMISSIONS and "
+ "USE_SOURCE_PERMISSIONS. Only one option allowed.");
+ return false;
+ }
+ if (noSourcePermissions) {
+ status.SetError(" given both FILE_PERMISSIONS and "
+ "NO_SOURCE_PERMISSIONS. Only one option allowed.");
+ return false;
+ }
+
+ if (doing == Doing::DoingNone) {
+ doing = Doing::DoingFilePermissions;
+ filePermissions = true;
+ }
} else if (noopOptions.find(args[i]) != noopOptions.end()) {
/* Ignore no-op options. */
+ } else if (doing == Doing::DoingFilePermissions) {
+ filePermissionOptions.push_back(args[i]);
} else {
unknown_args += " ";
unknown_args += args[i];
@@ -104,9 +159,53 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, msg);
}
- if (!status.GetMakefile().ConfigureFile(
- inputFile, outputFile, copyOnly, atOnly, escapeQuotes,
- use_source_permissions, newLineStyle)) {
+ if (useSourcePermissions && noSourcePermissions) {
+ status.SetError(" given both USE_SOURCE_PERMISSIONS and "
+ "NO_SOURCE_PERMISSIONS. Only one option allowed.");
+ return false;
+ }
+
+ mode_t permisiions = 0;
+
+ if (filePermissions) {
+ if (filePermissionOptions.empty()) {
+ status.SetError(" given FILE_PERMISSIONS without any options.");
+ return false;
+ }
+
+ std::vector<std::string> invalidOptions;
+ for (auto const& e : filePermissionOptions) {
+ if (!cmFSPermissions::stringToModeT(e, permisiions)) {
+ invalidOptions.push_back(e);
+ }
+ }
+
+ if (!invalidOptions.empty()) {
+ std::ostringstream oss;
+ oss << " given invalid permission ";
+ for (auto i = 0u; i < invalidOptions.size(); i++) {
+ if (i == 0u) {
+ oss << "\"" << invalidOptions[i] << "\"";
+ } else {
+ oss << ",\"" << invalidOptions[i] << "\"";
+ }
+ }
+ oss << ".";
+ status.SetError(oss.str());
+ return false;
+ }
+ }
+
+ if (noSourcePermissions) {
+ permisiions |= cmFSPermissions::mode_owner_read;
+ permisiions |= cmFSPermissions::mode_owner_write;
+ permisiions |= cmFSPermissions::mode_group_read;
+ permisiions |= cmFSPermissions::mode_world_read;
+ }
+
+ if (!status.GetMakefile().ConfigureFile(inputFile, outputFile, copyOnly,
+ atOnly, escapeQuotes, permisiions,
+ newLineStyle)) {
status.SetError("Problem configuring file");
return false;
}
diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx
deleted file mode 100644
index e4d0cf11b..000000000
--- a/Source/cmConnection.cxx
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmConnection.h"
-
-#include <cassert>
-#include <cstring>
-
-#include <cm3p/uv.h>
-
-#include "cmServer.h"
-
-struct write_req_t
-{
- uv_write_t req;
- uv_buf_t buf;
-};
-
-void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle,
- size_t suggested_size,
- uv_buf_t* buf)
-{
- (void)(handle);
-#ifndef __clang_analyzer__
- char* rawBuffer = new char[suggested_size];
- *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
-#else
- (void)(suggested_size);
- (void)(buf);
-#endif /* __clang_analyzer__ */
-}
-
-void cmEventBasedConnection::on_read(uv_stream_t* stream, ssize_t nread,
- const uv_buf_t* buf)
-{
- auto conn = static_cast<cmEventBasedConnection*>(stream->data);
- if (conn) {
- if (nread >= 0) {
- conn->ReadData(std::string(buf->base, buf->base + nread));
- } else {
- conn->OnDisconnect(static_cast<int>(nread));
- }
- }
-
- delete[](buf->base);
-}
-
-void cmEventBasedConnection::on_close(uv_handle_t* /*handle*/)
-{
-}
-
-void cmEventBasedConnection::on_write(uv_write_t* req, int status)
-{
- (void)(status);
-
- // Free req and buffer
- write_req_t* wr = reinterpret_cast<write_req_t*>(req);
- delete[](wr->buf.base);
- delete wr;
-}
-
-void cmEventBasedConnection::on_new_connection(uv_stream_t* stream, int status)
-{
- (void)(status);
- auto conn = static_cast<cmEventBasedConnection*>(stream->data);
-
- if (conn) {
- conn->Connect(stream);
- }
-}
-
-bool cmEventBasedConnection::IsOpen() const
-{
- return this->WriteStream != nullptr;
-}
-
-void cmEventBasedConnection::WriteData(const std::string& _data)
-{
-#ifndef NDEBUG
- auto curr_thread_id = uv_thread_self();
- assert(this->Server);
- assert(uv_thread_equal(&curr_thread_id, &this->Server->ServeThreadId));
-#endif
-
-#ifndef __clang_analyzer__
- auto data = _data;
- assert(this->WriteStream.get());
- if (BufferStrategy) {
- data = BufferStrategy->BufferOutMessage(data);
- }
-
- auto ds = data.size();
-
- write_req_t* req = new write_req_t;
- req->req.data = this;
- req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds));
- memcpy(req->buf.base, data.c_str(), ds);
- uv_write(reinterpret_cast<uv_write_t*>(req), this->WriteStream, &req->buf, 1,
- on_write);
-#else
- (void)(_data);
-#endif /* __clang_analyzer__ */
-}
-
-void cmEventBasedConnection::ReadData(const std::string& data)
-{
- this->RawReadBuffer += data;
- if (BufferStrategy) {
- std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
- while (!packet.empty()) {
- ProcessRequest(packet);
- packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
- }
- } else {
- ProcessRequest(this->RawReadBuffer);
- this->RawReadBuffer.clear();
- }
-}
-
-cmEventBasedConnection::cmEventBasedConnection(
- cmConnectionBufferStrategy* bufferStrategy)
- : BufferStrategy(bufferStrategy)
-{
-}
-
-void cmEventBasedConnection::Connect(uv_stream_t* server)
-{
- (void)server;
- Server->OnConnected(nullptr);
-}
-
-void cmEventBasedConnection::OnDisconnect(int onerror)
-{
- (void)onerror;
- this->OnConnectionShuttingDown();
- if (this->Server) {
- this->Server->OnDisconnect(this);
- }
-}
-
-cmConnection::~cmConnection() = default;
-
-bool cmConnection::OnConnectionShuttingDown()
-{
- this->Server = nullptr;
- return true;
-}
-
-void cmConnection::SetServer(cmServerBase* s)
-{
- Server = s;
-}
-
-void cmConnection::ProcessRequest(const std::string& request)
-{
- Server->ProcessRequest(this, request);
-}
-
-bool cmConnection::OnServeStart(std::string* errString)
-{
- (void)errString;
- return true;
-}
-
-bool cmEventBasedConnection::OnConnectionShuttingDown()
-{
- if (this->WriteStream.get()) {
- this->WriteStream->data = nullptr;
- }
-
- WriteStream.reset();
-
- return true;
-}
diff --git a/Source/cmConnection.h b/Source/cmConnection.h
deleted file mode 100644
index 5335a7f3c..000000000
--- a/Source/cmConnection.h
+++ /dev/null
@@ -1,137 +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 <cstddef>
-#include <memory>
-#include <string>
-
-#include <cm3p/uv.h>
-
-#include "cmUVHandlePtr.h"
-
-class cmServerBase;
-
-/***
- * Given a sequence of bytes with any kind of buffering, instances of this
- * class arrange logical chunks according to whatever the use case is for
- * the connection.
- */
-class cmConnectionBufferStrategy
-{
-public:
- virtual ~cmConnectionBufferStrategy();
-
- /***
- * Called whenever with an active raw buffer. If a logical chunk
- * becomes available, that chunk is returned and that portion is
- * removed from the rawBuffer
- *
- * @param rawBuffer in/out parameter. Receive buffer; the buffer strategy is
- * free to manipulate this buffer anyway it needs to.
- *
- * @return Next chunk from the stream. Returns the empty string if a chunk
- * isn't ready yet. Users of this interface should repeatedly call this
- * function until an empty string is returned since its entirely possible
- * multiple chunks come in a single raw buffer.
- */
- virtual std::string BufferMessage(std::string& rawBuffer) = 0;
-
- /***
- * Called to properly buffer an outgoing message.
- *
- * @param rawBuffer Message to format in the correct way
- *
- * @return Formatted message
- */
- virtual std::string BufferOutMessage(const std::string& rawBuffer) const
- {
- return rawBuffer;
- };
- /***
- * Resets the internal state of the buffering
- */
- virtual void clear();
-
- // TODO: There should be a callback / flag set for errors
-};
-
-class cmConnection
-{
-public:
- cmConnection() = default;
-
- cmConnection(cmConnection const&) = delete;
- cmConnection& operator=(cmConnection const&) = delete;
-
- virtual void WriteData(const std::string& data) = 0;
-
- virtual ~cmConnection();
-
- virtual bool OnConnectionShuttingDown();
-
- virtual bool IsOpen() const = 0;
-
- virtual void SetServer(cmServerBase* s);
-
- virtual void ProcessRequest(const std::string& request);
-
- virtual bool OnServeStart(std::string* pString);
-
-protected:
- cmServerBase* Server = nullptr;
-};
-
-/***
- * Abstraction of a connection; ties in event callbacks from libuv and notifies
- * the server when appropriate
- */
-class cmEventBasedConnection : public cmConnection
-{
-
-public:
- /***
- * @param bufferStrategy If no strategy is given, it will process the raw
- * chunks as they come in. The connection
- * owns the pointer given.
- */
- cmEventBasedConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr);
-
- virtual void Connect(uv_stream_t* server);
-
- virtual void ReadData(const std::string& data);
-
- bool IsOpen() const override;
-
- void WriteData(const std::string& data) override;
- bool OnConnectionShuttingDown() override;
-
- virtual void OnDisconnect(int errorCode);
-
- static void on_close(uv_handle_t* handle);
-
- template <typename T>
- static void on_close_delete(uv_handle_t* handle)
- {
- delete reinterpret_cast<T*>(handle);
- }
-
-protected:
- cm::uv_stream_ptr WriteStream;
-
- std::string RawReadBuffer;
-
- std::unique_ptr<cmConnectionBufferStrategy> BufferStrategy;
-
- static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
-
- static void on_write(uv_write_t* req, int status);
-
- static void on_new_connection(uv_stream_t* stream, int status);
-
- static void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size,
- uv_buf_t* buf);
-};
diff --git a/Source/cmConsoleBuf.cxx b/Source/cmConsoleBuf.cxx
index 70be481cb..8ce9ebc6c 100644
--- a/Source/cmConsoleBuf.cxx
+++ b/Source/cmConsoleBuf.cxx
@@ -12,8 +12,6 @@ cmConsoleBuf::cmConsoleBuf()
cmConsoleBuf::cmConsoleBuf() = default;
#endif
-cmConsoleBuf::~cmConsoleBuf() = default;
-
void cmConsoleBuf::SetUTF8Pipes()
{
#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
diff --git a/Source/cmConsoleBuf.h b/Source/cmConsoleBuf.h
index 356459810..0a6d3b52f 100644
--- a/Source/cmConsoleBuf.h
+++ b/Source/cmConsoleBuf.h
@@ -16,7 +16,7 @@ class cmConsoleBuf
#endif
public:
cmConsoleBuf();
- ~cmConsoleBuf();
+ ~cmConsoleBuf() = default;
cmConsoleBuf(cmConsoleBuf const&) = delete;
cmConsoleBuf& operator=(cmConsoleBuf const&) = delete;
void SetUTF8Pipes();
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index 9c4deea1e..3001ae09a 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -125,9 +125,9 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args,
mf.AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION", function);
}
mf.AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", forwardDeclareCode);
- mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES", functionMapCode);
+ mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTRIES", functionMapCode);
bool res = true;
- if (!mf.ConfigureFile(configFile, driver, false, true, false, true)) {
+ if (!mf.ConfigureFile(configFile, driver, false, true, false)) {
res = false;
}
diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx
index b1e63ba65..b33186213 100644
--- a/Source/cmCryptoHash.cxx
+++ b/Source/cmCryptoHash.cxx
@@ -36,7 +36,7 @@ static rhash cmCryptoHash_rhash_init(unsigned int id)
cmCryptoHash::cmCryptoHash(Algo algo)
: Id(cmCryptoHashAlgoToId[algo])
- , CTX(cmCryptoHash_rhash_init(Id))
+ , CTX(cmCryptoHash_rhash_init(this->Id))
{
}
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 149f5e99e..f6b998984 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -140,3 +140,13 @@ void cmCustomCommand::SetJobPool(const std::string& job_pool)
{
this->JobPool = job_pool;
}
+
+cmPolicies::PolicyStatus cmCustomCommand::GetCMP0116Status() const
+{
+ return this->CMP0116Status;
+}
+
+void cmCustomCommand::SetCMP0116Status(cmPolicies::PolicyStatus cmp0116)
+{
+ this->CMP0116Status = cmp0116;
+}
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 2036e90b7..e22c7a406 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -10,6 +10,7 @@
#include "cmCustomCommandLines.h"
#include "cmListFileCache.h"
+#include "cmPolicies.h"
class cmImplicitDependsList
: public std::vector<std::pair<std::string, std::string>>
@@ -95,6 +96,10 @@ public:
const std::string& GetJobPool() const;
void SetJobPool(const std::string& job_pool);
+ /** Set/Get the CMP0116 status (used by the Ninja generator) */
+ cmPolicies::PolicyStatus GetCMP0116Status() const;
+ void SetCMP0116Status(cmPolicies::PolicyStatus cmp0116);
+
private:
std::vector<std::string> Outputs;
std::vector<std::string> Byproducts;
@@ -112,4 +117,5 @@ private:
bool UsesTerminal = false;
bool CommandExpandLists = false;
bool StdPipesUTF8 = false;
+ cmPolicies::PolicyStatus CMP0116Status = cmPolicies::WARN;
};
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 60504bab7..4329cafc4 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -6,45 +6,147 @@
#include <memory>
#include <utility>
+#include <cm/optional>
+#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
+#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTransformDepfile.h"
namespace {
-void AppendPaths(const std::vector<std::string>& inputs,
- cmGeneratorExpression const& ge, cmLocalGenerator* lg,
- std::string const& config, std::vector<std::string>& output)
+std::string EvaluateSplitConfigGenex(
+ cm::string_view input, cmGeneratorExpression const& ge, cmLocalGenerator* lg,
+ bool useOutputConfig, std::string const& outputConfig,
+ std::string const& commandConfig,
+ std::set<BT<std::pair<std::string, bool>>>* utils = nullptr)
{
- for (std::string const& in : inputs) {
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(in);
- std::vector<std::string> result =
- cmExpandedList(cge->Evaluate(lg, config));
- for (std::string& it : result) {
- cmSystemTools::ConvertToUnixSlashes(it);
- if (cmSystemTools::FileIsFullPath(it)) {
- it = cmSystemTools::CollapseFullPath(
- it, lg->GetMakefile()->GetHomeOutputDirectory());
+ std::string result;
+
+ while (!input.empty()) {
+ // Copy non-genex content directly to the result.
+ std::string::size_type pos = input.find("$<");
+ result += input.substr(0, pos);
+ if (pos == std::string::npos) {
+ break;
+ }
+ input = input.substr(pos);
+
+ // Find the balanced end of this regex.
+ size_t nestingLevel = 1;
+ for (pos = 2; pos < input.size(); ++pos) {
+ cm::string_view cur = input.substr(pos);
+ if (cmHasLiteralPrefix(cur, "$<")) {
+ ++nestingLevel;
+ ++pos;
+ continue;
+ }
+ if (cmHasLiteralPrefix(cur, ">")) {
+ --nestingLevel;
+ if (nestingLevel == 0) {
+ ++pos;
+ break;
+ }
+ }
+ }
+
+ // Split this genex from following input.
+ cm::string_view genex = input.substr(0, pos);
+ input = input.substr(pos);
+
+ // Convert an outer COMMAND_CONFIG or OUTPUT_CONFIG to the matching config.
+ std::string const* config =
+ useOutputConfig ? &outputConfig : &commandConfig;
+ if (nestingLevel == 0) {
+ static cm::string_view const COMMAND_CONFIG = "$<COMMAND_CONFIG:"_s;
+ static cm::string_view const OUTPUT_CONFIG = "$<OUTPUT_CONFIG:"_s;
+ if (cmHasPrefix(genex, COMMAND_CONFIG)) {
+ genex.remove_prefix(COMMAND_CONFIG.size());
+ genex.remove_suffix(1);
+ useOutputConfig = false;
+ config = &commandConfig;
+ } else if (cmHasPrefix(genex, OUTPUT_CONFIG)) {
+ genex.remove_prefix(OUTPUT_CONFIG.size());
+ genex.remove_suffix(1);
+ useOutputConfig = true;
+ config = &outputConfig;
+ }
+ }
+
+ // Evaluate this genex in the selected configuration.
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(std::string(genex));
+ result += cge->Evaluate(lg, *config);
+
+ // Record targets referenced by the genex.
+ if (utils) {
+ // FIXME: What is the proper condition for a cross-dependency?
+ bool const cross = !useOutputConfig;
+ for (cmGeneratorTarget* gt : cge->GetTargets()) {
+ utils->emplace(BT<std::pair<std::string, bool>>(
+ { gt->GetName(), cross }, cge->GetBacktrace()));
}
}
- cm::append(output, result);
}
+
+ return result;
}
+
+std::vector<std::string> EvaluateDepends(std::vector<std::string> const& paths,
+ cmGeneratorExpression const& ge,
+ cmLocalGenerator* lg,
+ std::string const& outputConfig,
+ std::string const& commandConfig)
+{
+ std::vector<std::string> depends;
+ for (std::string const& p : paths) {
+ std::string const& ep =
+ EvaluateSplitConfigGenex(p, ge, lg, /*useOutputConfig=*/true,
+ /*outputConfig=*/outputConfig,
+ /*commandConfig=*/commandConfig);
+ cm::append(depends, cmExpandedList(ep));
+ }
+ for (std::string& p : depends) {
+ if (cmSystemTools::FileIsFullPath(p)) {
+ p = cmSystemTools::CollapseFullPath(p);
+ } else {
+ cmSystemTools::ConvertToUnixSlashes(p);
+ }
+ }
+ return depends;
}
-cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
- std::string config,
- cmLocalGenerator* lg)
- : CC(cc)
- , Config(std::move(config))
+std::vector<std::string> EvaluateOutputs(std::vector<std::string> const& paths,
+ cmGeneratorExpression const& ge,
+ cmLocalGenerator* lg,
+ std::string const& config)
+{
+ std::vector<std::string> outputs;
+ for (std::string const& p : paths) {
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(p);
+ cm::append(outputs, lg->ExpandCustomCommandOutputPaths(*cge, config));
+ }
+ return outputs;
+}
+}
+
+cmCustomCommandGenerator::cmCustomCommandGenerator(
+ cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg,
+ bool transformDepfile, cm::optional<std::string> crossConfig)
+ : CC(&cc)
+ , OutputConfig(crossConfig ? *crossConfig : config)
+ , CommandConfig(std::move(config))
, LG(lg)
, OldStyle(cc.GetEscapeOldStyle())
, MakeVars(cc.GetEscapeAllowMakeVars())
@@ -52,38 +154,83 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
{
cmGeneratorExpression ge(cc.GetBacktrace());
- const cmCustomCommandLines& cmdlines = this->CC.GetCommandLines();
+ const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines();
for (cmCustomCommandLine const& cmdline : cmdlines) {
cmCustomCommandLine argv;
+ // For the command itself, we default to the COMMAND_CONFIG.
+ bool useOutputConfig = false;
for (std::string const& clarg : cmdline) {
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(clarg);
- std::string parsed_arg = cge->Evaluate(this->LG, this->Config);
- if (this->CC.GetCommandExpandLists()) {
+ std::string parsed_arg = EvaluateSplitConfigGenex(
+ clarg, ge, this->LG, useOutputConfig, this->OutputConfig,
+ this->CommandConfig, &this->Utilities);
+ if (this->CC->GetCommandExpandLists()) {
cm::append(argv, cmExpandedList(parsed_arg));
} else {
argv.push_back(std::move(parsed_arg));
}
+
+ // For remaining arguments, we default to the OUTPUT_CONFIG.
+ useOutputConfig = true;
}
- // Later code assumes at least one entry exists, but expanding
- // lists on an empty command may have left this empty.
- // FIXME: Should we define behavior for removing empty commands?
- if (argv.empty()) {
+ if (!argv.empty()) {
+ // If the command references an executable target by name,
+ // collect the target to add a target-level dependency on it.
+ cmGeneratorTarget* gt = this->LG->FindGeneratorTargetToUse(argv.front());
+ if (gt && gt->GetType() == cmStateEnums::EXECUTABLE) {
+ // FIXME: What is the proper condition for a cross-dependency?
+ bool const cross = true;
+ this->Utilities.emplace(BT<std::pair<std::string, bool>>(
+ { gt->GetName(), cross }, cc.GetBacktrace()));
+ }
+ } else {
+ // Later code assumes at least one entry exists, but expanding
+ // lists on an empty command may have left this empty.
+ // FIXME: Should we define behavior for removing empty commands?
argv.emplace_back();
}
this->CommandLines.push_back(std::move(argv));
}
- AppendPaths(cc.GetByproducts(), ge, this->LG, this->Config,
- this->Byproducts);
- AppendPaths(cc.GetDepends(), ge, this->LG, this->Config, this->Depends);
+ if (transformDepfile && !this->CommandLines.empty() &&
+ !cc.GetDepfile().empty() &&
+ this->LG->GetGlobalGenerator()->DepfileFormat()) {
+ cmCustomCommandLine argv;
+ argv.push_back(cmSystemTools::GetCMakeCommand());
+ argv.emplace_back("-E");
+ argv.emplace_back("cmake_transform_depfile");
+ argv.push_back(this->LG->GetGlobalGenerator()->GetName());
+ switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
+ case cmDepfileFormat::GccDepfile:
+ argv.emplace_back("gccdepfile");
+ break;
+ case cmDepfileFormat::VsTlog:
+ argv.emplace_back("vstlog");
+ break;
+ }
+ argv.push_back(this->LG->GetSourceDirectory());
+ argv.push_back(this->LG->GetCurrentSourceDirectory());
+ argv.push_back(this->LG->GetBinaryDirectory());
+ argv.push_back(this->LG->GetCurrentBinaryDirectory());
+ argv.push_back(this->GetFullDepfile());
+ argv.push_back(this->GetInternalDepfile());
- const std::string& workingdirectory = this->CC.GetWorkingDirectory();
+ this->CommandLines.push_back(std::move(argv));
+ }
+
+ this->Outputs =
+ EvaluateOutputs(cc.GetOutputs(), ge, this->LG, this->OutputConfig);
+ this->Byproducts =
+ EvaluateOutputs(cc.GetByproducts(), ge, this->LG, this->OutputConfig);
+ this->Depends = EvaluateDepends(cc.GetDepends(), ge, this->LG,
+ this->OutputConfig, this->CommandConfig);
+
+ const std::string& workingdirectory = this->CC->GetWorkingDirectory();
if (!workingdirectory.empty()) {
- std::unique_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(workingdirectory);
- this->WorkingDirectory = cge->Evaluate(this->LG, this->Config);
+ this->WorkingDirectory =
+ EvaluateSplitConfigGenex(workingdirectory, ge, this->LG, true,
+ this->OutputConfig, this->CommandConfig);
// Convert working directory to a full path.
if (!this->WorkingDirectory.empty()) {
std::string const& build_dir = this->LG->GetCurrentBinaryDirectory();
@@ -97,7 +244,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
{
- return static_cast<unsigned int>(this->CC.GetCommandLines().size());
+ return static_cast<unsigned int>(this->CommandLines.size());
}
void cmCustomCommandGenerator::FillEmulatorsWithArguments()
@@ -140,7 +287,7 @@ const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
(target->IsImported() ||
target->GetProperty("CROSSCOMPILING_EMULATOR") ||
!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) {
- return target->GetLocation(this->Config).c_str();
+ return target->GetLocation(this->CommandConfig).c_str();
}
return nullptr;
}
@@ -234,9 +381,43 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
}
}
+std::string cmCustomCommandGenerator::GetFullDepfile() const
+{
+ std::string depfile = this->CC->GetDepfile();
+ if (depfile.empty()) {
+ return "";
+ }
+
+ if (!cmSystemTools::FileIsFullPath(depfile)) {
+ depfile = cmStrCat(this->LG->GetCurrentBinaryDirectory(), '/', depfile);
+ }
+ return cmSystemTools::CollapseFullPath(depfile);
+}
+
+std::string cmCustomCommandGenerator::GetInternalDepfile() const
+{
+ std::string depfile = this->GetFullDepfile();
+ if (depfile.empty()) {
+ return "";
+ }
+
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ std::string extension;
+ switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
+ case cmDepfileFormat::GccDepfile:
+ extension = ".d";
+ break;
+ case cmDepfileFormat::VsTlog:
+ extension = ".tlog";
+ break;
+ }
+ return cmStrCat(this->LG->GetBinaryDirectory(), "/CMakeFiles/d/",
+ hash.HashString(depfile), extension);
+}
+
const char* cmCustomCommandGenerator::GetComment() const
{
- return this->CC.GetComment();
+ return this->CC->GetComment();
}
std::string cmCustomCommandGenerator::GetWorkingDirectory() const
@@ -246,7 +427,7 @@ std::string cmCustomCommandGenerator::GetWorkingDirectory() const
std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
{
- return this->CC.GetOutputs();
+ return this->Outputs;
}
std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
@@ -258,3 +439,9 @@ std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
{
return this->Depends;
}
+
+std::set<BT<std::pair<std::string, bool>>> const&
+cmCustomCommandGenerator::GetUtilities() const
+{
+ return this->Utilities;
+}
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 412eba8dd..4be5b3fd2 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -4,26 +4,34 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <set>
#include <string>
+#include <utility>
#include <vector>
+#include <cm/optional>
+
#include "cmCustomCommandLines.h"
+#include "cmListFileCache.h"
class cmCustomCommand;
class cmLocalGenerator;
class cmCustomCommandGenerator
{
- cmCustomCommand const& CC;
- std::string Config;
+ cmCustomCommand const* CC;
+ std::string OutputConfig;
+ std::string CommandConfig;
cmLocalGenerator* LG;
bool OldStyle;
bool MakeVars;
cmCustomCommandLines CommandLines;
std::vector<std::vector<std::string>> EmulatorsWithArguments;
+ std::vector<std::string> Outputs;
std::vector<std::string> Byproducts;
std::vector<std::string> Depends;
std::string WorkingDirectory;
+ std::set<BT<std::pair<std::string, bool>>> Utilities;
void FillEmulatorsWithArguments();
std::vector<std::string> GetCrossCompilingEmulator(unsigned int c) const;
@@ -31,11 +39,14 @@ class cmCustomCommandGenerator
public:
cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config,
- cmLocalGenerator* lg);
+ cmLocalGenerator* lg, bool transformDepfile = true,
+ cm::optional<std::string> crossConfig = {});
cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete;
+ cmCustomCommandGenerator(cmCustomCommandGenerator&&) = default;
cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) =
delete;
- cmCustomCommand const& GetCC() const { return this->CC; }
+ cmCustomCommandGenerator& operator=(cmCustomCommandGenerator&&) = default;
+ cmCustomCommand const& GetCC() const { return *(this->CC); }
unsigned int GetNumberOfCommands() const;
std::string GetCommand(unsigned int c) const;
void AppendArguments(unsigned int c, std::string& cmd) const;
@@ -44,5 +55,11 @@ public:
std::vector<std::string> const& GetOutputs() const;
std::vector<std::string> const& GetByproducts() const;
std::vector<std::string> const& GetDepends() const;
+ std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
bool HasOnlyEmptyCommandLines() const;
+ std::string GetFullDepfile() const;
+ std::string GetInternalDepfile() const;
+
+ const std::string& GetOutputConfig() const { return this->OutputConfig; }
+ const std::string& GetCommandConfig() const { return this->CommandConfig; }
};
diff --git a/Source/cmCustomCommandTypes.h b/Source/cmCustomCommandTypes.h
index 5c900ce1e..324da9ef2 100644
--- a/Source/cmCustomCommandTypes.h
+++ b/Source/cmCustomCommandTypes.h
@@ -27,10 +27,3 @@ enum class cmObjectLibraryCommands
Reject,
Accept
};
-
-/** Utility target output source file name. */
-struct cmUtilityOutput
-{
- std::string Name;
- std::string NameCMP0049;
-};
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index d092f4f23..566c3bf78 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -77,7 +77,7 @@ bool cmDepends::Check(const std::string& makeFile,
return okay;
}
-void cmDepends::Clear(const std::string& file)
+void cmDepends::Clear(const std::string& file) const
{
// Print verbose output.
if (this->Verbose) {
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index 0240da90b..76af4db20 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -25,7 +25,6 @@ class cmDepends
public:
using DependencyMap = std::map<std::string, std::vector<std::string>>;
-public:
/** Instances need to know the build directory name and the relative
path from the build directory to the target file. */
cmDepends(cmLocalUnixMakefileGenerator3* lg = nullptr,
@@ -70,7 +69,7 @@ public:
DependencyMap& validDeps);
/** Clear dependencies for the target file so they will be regenerated. */
- void Clear(const std::string& file);
+ void Clear(const std::string& file) const;
/** Set the file comparison object */
void SetFileTimeCache(cmFileTimeCache* fc) { this->FileTimeCache = fc; }
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index e6aef9289..60e8cbf2c 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -7,6 +7,7 @@
#include "cmsys/FStream.hxx"
#include "cmFileTime.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmProperty.h"
@@ -215,16 +216,28 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// directory. We must do the same here.
std::string obj_m = this->LocalGenerator->ConvertToMakefilePath(obj_i);
internalDepends << obj_i << '\n';
-
- for (std::string const& dep : dependencies) {
- makeDepends << obj_m << ": "
- << this->LocalGenerator->ConvertToMakefilePath(
- this->LocalGenerator->MaybeConvertToRelativePath(binDir,
- dep))
- << '\n';
- internalDepends << ' ' << dep << '\n';
+ if (!dependencies.empty()) {
+ const auto& lineContinue = static_cast<cmGlobalUnixMakefileGenerator3*>(
+ this->LocalGenerator->GetGlobalGenerator())
+ ->LineContinueDirective;
+ bool supportLongLineDepend = static_cast<cmGlobalUnixMakefileGenerator3*>(
+ this->LocalGenerator->GetGlobalGenerator())
+ ->SupportsLongLineDependencies();
+ if (supportLongLineDepend) {
+ makeDepends << obj_m << ':';
+ }
+ for (std::string const& dep : dependencies) {
+ std::string dependee = this->LocalGenerator->ConvertToMakefilePath(
+ this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
+ if (supportLongLineDepend) {
+ makeDepends << ' ' << lineContinue << ' ' << dependee;
+ } else {
+ makeDepends << obj_m << ": " << dependee << '\n';
+ }
+ internalDepends << ' ' << dep << '\n';
+ }
+ makeDepends << '\n';
}
- makeDepends << '\n';
return true;
}
diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx
new file mode 100644
index 000000000..2b48df969
--- /dev/null
+++ b/Source/cmDependsCompiler.cxx
@@ -0,0 +1,252 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDependsCompiler.h"
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <utility>
+
+#include <cm/optional>
+#include <cm/string_view>
+#include <cm/vector>
+#include <cmext/string_view>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmFileTime.h"
+#include "cmGccDepfileReader.h"
+#include "cmGccDepfileReaderTypes.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+bool cmDependsCompiler::CheckDependencies(
+ const std::string& internalDepFile, const std::vector<std::string>& depFiles,
+ cmDepends::DependencyMap& dependencies,
+ const std::function<bool(const std::string&)>& isValidPath)
+{
+ bool status = true;
+ bool forceReadDeps = true;
+
+ cmFileTime internalDepFileTime;
+ // read cached dependencies stored in internal file
+ if (cmSystemTools::FileExists(internalDepFile)) {
+ internalDepFileTime.Load(internalDepFile);
+ forceReadDeps = false;
+
+ // read current dependencies
+ cmsys::ifstream fin(internalDepFile.c_str());
+ if (fin) {
+ std::string line;
+ std::string depender;
+ std::vector<std::string>* currentDependencies = nullptr;
+ while (std::getline(fin, line)) {
+ if (line.empty() || line.front() == '#') {
+ continue;
+ }
+ // Drop carriage return character at the end
+ if (line.back() == '\r') {
+ line.pop_back();
+ if (line.empty()) {
+ continue;
+ }
+ }
+ // Check if this a depender line
+ if (line.front() != ' ') {
+ depender = std::move(line);
+ currentDependencies = &dependencies[depender];
+ continue;
+ }
+ // This is a dependee line
+ if (currentDependencies != nullptr) {
+ currentDependencies->emplace_back(line.substr(1));
+ }
+ }
+ fin.close();
+ }
+ }
+
+ // Now, update dependencies map with all new compiler generated
+ // dependencies files
+ cmFileTime depFileTime;
+ for (auto dep = depFiles.begin(); dep != depFiles.end(); dep++) {
+ const auto& source = *dep++;
+ const auto& target = *dep++;
+ const auto& format = *dep++;
+ const auto& depFile = *dep;
+
+ if (!cmSystemTools::FileExists(depFile)) {
+ continue;
+ }
+
+ if (!forceReadDeps) {
+ depFileTime.Load(depFile);
+ }
+ if (forceReadDeps || depFileTime.Compare(internalDepFileTime) >= 0) {
+ status = false;
+ if (this->Verbose) {
+ cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile,
+ "\" is newer than depends file \"",
+ internalDepFile, "\".\n"));
+ }
+
+ std::vector<std::string> depends;
+ if (format == "custom"_s) {
+ auto deps = cmReadGccDepfile(
+ depFile.c_str(), this->LocalGenerator->GetCurrentBinaryDirectory());
+ if (!deps) {
+ continue;
+ }
+
+ for (auto& entry : *deps) {
+ depends = std::move(entry.paths);
+ if (isValidPath) {
+ cm::erase_if(depends, isValidPath);
+ }
+ // copy depends for each target, except first one, which can be
+ // moved
+ for (auto index = entry.rules.size() - 1; index > 0; --index) {
+ dependencies[entry.rules[index]] = depends;
+ }
+ dependencies[entry.rules.front()] = std::move(depends);
+ }
+ } else {
+ if (format == "msvc"_s) {
+ cmsys::ifstream fin(depFile.c_str());
+ if (!fin) {
+ continue;
+ }
+
+ std::string line;
+ if (!isValidPath) {
+ // insert source as first dependency
+ depends.push_back(source);
+ }
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ depends.emplace_back(std::move(line));
+ }
+ } else if (format == "gcc"_s) {
+ auto deps = cmReadGccDepfile(depFile.c_str());
+ if (!deps) {
+ continue;
+ }
+
+ // dependencies generated by the compiler contains only one target
+ depends = std::move(deps->front().paths);
+ if (depends.empty()) {
+ // unexpectedly empty, ignore it and continue
+ continue;
+ }
+
+ // depending of the effective format of the dependencies file
+ // generated by the compiler, the target can be wrongly identified
+ // as a dependency so remove it from the list
+ if (depends.front() == target) {
+ depends.erase(depends.begin());
+ }
+
+ // ensure source file is the first dependency
+ if (depends.front() != source) {
+ cm::erase(depends, source);
+ if (!isValidPath) {
+ depends.insert(depends.begin(), source);
+ }
+ } else if (isValidPath) {
+ // remove first dependency because it must not be filtered out
+ depends.erase(depends.begin());
+ }
+ } else {
+ // unknown format, ignore it
+ continue;
+ }
+
+ if (isValidPath) {
+ cm::erase_if(depends, isValidPath);
+ // insert source as first dependency
+ depends.insert(depends.begin(), source);
+ }
+
+ dependencies[target] = std::move(depends);
+ }
+ }
+ }
+
+ return status;
+}
+
+void cmDependsCompiler::WriteDependencies(
+ const cmDepends::DependencyMap& dependencies, std::ostream& makeDepends,
+ std::ostream& internalDepends)
+{
+ // dependencies file consumed by make tool
+ const auto& lineContinue = static_cast<cmGlobalUnixMakefileGenerator3*>(
+ this->LocalGenerator->GetGlobalGenerator())
+ ->LineContinueDirective;
+ 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));
+ 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));
+ });
+
+ bool first_dep = true;
+ if (supportLongLineDepend) {
+ makeDepends << target << ": ";
+ }
+ for (const auto& dep : deps) {
+ if (supportLongLineDepend) {
+ if (first_dep) {
+ first_dep = false;
+ makeDepends << dep;
+ } else {
+ makeDepends << ' ' << lineContinue << " " << dep;
+ }
+ } else {
+ makeDepends << target << ": " << dep << std::endl;
+ }
+
+ phonyTargets.emplace(dep.data(), dep.length());
+ }
+ makeDepends << std::endl << std::endl;
+ }
+
+ // add phony targets
+ for (const auto& target : phonyTargets) {
+ makeDepends << std::endl << target << ':' << std::endl;
+ }
+
+ // internal dependencies file
+ for (const auto& node : dependencies) {
+ internalDepends << node.first << std::endl;
+ for (const auto& dep : node.second) {
+ internalDepends << ' ' << dep << std::endl;
+ }
+ internalDepends << std::endl;
+ }
+}
+
+void cmDependsCompiler::ClearDependencies(
+ const std::vector<std::string>& depFiles)
+{
+ for (auto dep = depFiles.begin(); dep != depFiles.end(); dep++) {
+ dep += 3;
+ cmSystemTools::RemoveFile(*dep);
+ }
+}
diff --git a/Source/cmDependsCompiler.h b/Source/cmDependsCompiler.h
new file mode 100644
index 000000000..838156d8a
--- /dev/null
+++ b/Source/cmDependsCompiler.h
@@ -0,0 +1,60 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <functional>
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmDepends.h"
+
+class cmLocalUnixMakefileGenerator3;
+
+/** \class cmDepends
+ * \brief Dependencies files manager.
+ *
+ * This class is responsible for maintaining a compiler_depends.make file in
+ * the build tree corresponding to an object file.
+ */
+class cmDependsCompiler
+{
+public:
+ cmDependsCompiler() = default;
+ ~cmDependsCompiler() = default;
+
+ /** should this be verbose in its output */
+ void SetVerbose(bool verb) { this->Verbose = verb; }
+
+ /** Set the local generator for the directory in which we are
+ scanning dependencies. This is not a full local generator; it
+ has been setup to do relative path conversions for the current
+ directory. */
+ void SetLocalGenerator(cmLocalUnixMakefileGenerator3* lg)
+ {
+ this->LocalGenerator = lg;
+ }
+
+ /** Read dependencies for the target file. Return true if
+ dependencies didn't changed and false if not.
+ Up-to-date Dependencies will be stored in deps. */
+ bool CheckDependencies(
+ const std::string& internalDepFile,
+ const std::vector<std::string>& depFiles,
+ cmDepends::DependencyMap& dependencies,
+ const std::function<bool(const std::string&)>& isValidPath);
+
+ /** Write dependencies for the target file. */
+ void WriteDependencies(const cmDepends::DependencyMap& dependencies,
+ std::ostream& makeDepends,
+ std::ostream& internalDepends);
+
+ /** Clear dependencies for the target so they will be regenerated. */
+ void ClearDependencies(const std::vector<std::string>& depFiles);
+
+private:
+ bool Verbose = false;
+ cmLocalUnixMakefileGenerator3* LocalGenerator = nullptr;
+};
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index a239418fd..1a06f3170 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -12,6 +12,7 @@
#include "cmFortranParser.h" /* Interface to parser object. */
#include "cmGeneratedFileStream.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
@@ -320,14 +321,28 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj);
std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
internalDepends << obj_i << "\n " << src << '\n';
- for (std::string const& i : info.Includes) {
- makeDepends << obj_m << ": "
- << cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, i))
- << '\n';
- internalDepends << ' ' << i << '\n';
+ if (!info.Includes.empty()) {
+ const auto& lineContinue = static_cast<cmGlobalUnixMakefileGenerator3*>(
+ this->LocalGenerator->GetGlobalGenerator())
+ ->LineContinueDirective;
+ bool supportLongLineDepend = static_cast<cmGlobalUnixMakefileGenerator3*>(
+ this->LocalGenerator->GetGlobalGenerator())
+ ->SupportsLongLineDependencies();
+ if (supportLongLineDepend) {
+ makeDepends << obj_m << ':';
+ }
+ for (std::string const& i : info.Includes) {
+ std::string dependee = cmSystemTools::ConvertToOutputPath(
+ this->MaybeConvertToRelativePath(binDir, i));
+ if (supportLongLineDepend) {
+ makeDepends << ' ' << lineContinue << ' ' << dependee;
+ } else {
+ makeDepends << obj_m << ": " << dependee << '\n';
+ }
+ internalDepends << ' ' << i << '\n';
+ }
+ makeDepends << '\n';
}
- makeDepends << '\n';
// Write module requirements to the output stream.
for (std::string const& i : info.Requires) {
diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx
index fc1bbdd96..0c5d310e3 100644
--- a/Source/cmDependsJavaParserHelper.cxx
+++ b/Source/cmDependsJavaParserHelper.cxx
@@ -103,7 +103,7 @@ void cmDependsJavaParserHelper::SafePrintMissing(const char* str, int line,
std::cout << "- " << strlen(str) << std::endl;
}
}
-void cmDependsJavaParserHelper::Print(const char* place, const char* str)
+void cmDependsJavaParserHelper::Print(const char* place, const char* str) const
{
if (this->Verbose) {
std::cout << "[" << place << "=" << str << "]" << std::endl;
diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h
index 869b7d4e4..4057bb7e3 100644
--- a/Source/cmDependsJavaParserHelper.h
+++ b/Source/cmDependsJavaParserHelper.h
@@ -85,7 +85,7 @@ private:
void PrintClasses();
- void Print(const char* place, const char* str);
+ void Print(const char* place, const char* str) const;
void CombineUnions(char** out, const char* in1, char** in2, const char* sep);
void SafePrintMissing(const char* str, int line, int cnt);
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index 1bc453d37..3619aded5 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -194,7 +194,7 @@ void cmDocumentation::addCTestStandardDocSections()
{
// This is currently done for backward compatibility reason
// We may suppress some of these.
- addCMakeStandardDocSections();
+ this->addCMakeStandardDocSections();
}
void cmDocumentation::addCPackStandardDocSections()
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index a8d81f7c2..deffdb646 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -379,7 +379,7 @@ private:
// Fix the byte order of the header.
if (this->NeedSwap) {
- ByteSwap(x);
+ this->ByteSwap(x);
}
return true;
}
@@ -387,7 +387,7 @@ private:
{
if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
this->NeedSwap) {
- ByteSwap(x);
+ this->ByteSwap(x);
}
return !this->Stream->fail();
}
@@ -395,7 +395,7 @@ private:
{
if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
this->NeedSwap) {
- ByteSwap(x);
+ this->ByteSwap(x);
}
return !this->Stream->fail();
}
@@ -573,7 +573,7 @@ std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries(
dyn.d_un.d_val = static_cast<tagtype>(entry.second);
if (this->NeedSwap) {
- ByteSwap(dyn);
+ this->ByteSwap(dyn);
}
char* pdyn = reinterpret_cast<char*>(&dyn);
diff --git a/Source/cmELF.h b/Source/cmELF.h
index 99eb4f48b..c479e2b95 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -10,8 +10,8 @@
#include <utility>
#include <vector>
-#if !defined(CMAKE_USE_ELF_PARSER)
-# error "This file may be included only if CMAKE_USE_ELF_PARSER is enabled."
+#if !defined(CMake_USE_ELF_PARSER)
+# error "This file may be included only if CMake_USE_ELF_PARSER is enabled."
#endif
class cmELFInternal;
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 5a85b7de4..ffcc415a1 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -231,7 +231,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
}
if (echo_stdout || echo_stderr) {
std::string command;
- for (auto& cmd : arguments.Commands) {
+ for (const auto& cmd : arguments.Commands) {
command += "'";
command += cmJoin(cmd, "' '");
command += "'";
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index cbae4e59a..7015a0129 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -707,7 +707,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
break;
}
input.replace(pos, endPos - pos + 1, targetName);
- lastPos = endPos;
+ lastPos = pos + targetName.size();
}
pos = 0;
@@ -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.17 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.18 (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.17)\n";
+ << "cmake_policy(VERSION 2.6...3.18)\n";
/* clang-format on */
}
@@ -1214,7 +1214,7 @@ bool cmExportFileGenerator::PopulateExportProperties(
cmGeneratorTarget* gte, ImportPropertyMap& properties,
std::string& errorMessage)
{
- auto& targetProperties = gte->Target->GetProperties();
+ const auto& targetProperties = gte->Target->GetProperties();
if (cmProp exportProperties =
targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) {
for (auto& prop : cmExpandedList(*exportProperties)) {
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 0b9b183d5..3c69c5001 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -290,6 +290,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig(
cmSystemTools::Error(e.str());
return false;
}
+ exportFileStream.SetCopyIfDifferent(true);
std::ostream& os = exportFileStream;
// Start with the import file header.
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index 56dfc6c1d..cc8b8b7e8 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -42,20 +42,22 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
try {
int res = cmExpr_yyparse(yyscanner);
if (res != 0) {
- std::string e = cmStrCat("cannot parse the expression: \"", InputBuffer,
- "\": ", ErrorString, '.');
+ std::string e =
+ cmStrCat("cannot parse the expression: \"", this->InputBuffer,
+ "\": ", this->ErrorString, '.');
this->SetError(std::move(e));
}
} catch (std::runtime_error const& fail) {
- std::string e = cmStrCat("cannot evaluate the expression: \"", InputBuffer,
- "\": ", fail.what(), '.');
+ std::string e = cmStrCat("cannot evaluate the expression: \"",
+ this->InputBuffer, "\": ", fail.what(), '.');
this->SetError(std::move(e));
} catch (std::out_of_range const&) {
- std::string e = "cannot evaluate the expression: \"" + InputBuffer +
+ std::string e = "cannot evaluate the expression: \"" + this->InputBuffer +
"\": a numeric value is out of range.";
this->SetError(std::move(e));
} catch (...) {
- std::string e = "cannot parse the expression: \"" + InputBuffer + "\".";
+ std::string e =
+ "cannot parse the expression: \"" + this->InputBuffer + "\".";
this->SetError(std::move(e));
}
cmExpr_yylex_destroy(yyscanner);
@@ -63,7 +65,7 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
return 0;
}
- if (Verbose) {
+ if (this->Verbose) {
std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
<< std::endl;
}
diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h
index 54dd6a4d1..919e4926e 100644
--- a/Source/cmExprParserHelper.h
+++ b/Source/cmExprParserHelper.h
@@ -27,7 +27,7 @@ public:
void SetResult(KWIML_INT_int64_t value);
- KWIML_INT_int64_t GetResult() { return this->Result; }
+ KWIML_INT_int64_t GetResult() const { return this->Result; }
const char* GetError() { return this->ErrorString.c_str(); }
diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h
index 3ade67bea..311a2efe7 100644
--- a/Source/cmExternalMakefileProjectGenerator.h
+++ b/Source/cmExternalMakefileProjectGenerator.h
@@ -52,8 +52,8 @@ public:
//! Generate the project files, the Makefiles have already been generated
virtual void Generate() = 0;
- void SetName(const std::string& n) { Name = n; }
- std::string GetName() const { return Name; }
+ void SetName(const std::string& n) { this->Name = n; }
+ std::string GetName() const { return this->Name; }
virtual bool Open(const std::string& bindir, const std::string& projectName,
bool dryRun);
@@ -104,7 +104,7 @@ public:
CreateExternalMakefileProjectGenerator() const override
{
std::unique_ptr<cmExternalMakefileProjectGenerator> p(new T);
- p->SetName(GetName());
+ p->SetName(this->GetName());
return p;
}
};
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 87b8f9bd3..f21720174 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -112,10 +112,10 @@ void Tree::InsertPath(const std::vector<std::string>& split,
const std::string& fileName)
{
if (start == split.size()) {
- files.insert(fileName);
+ this->files.insert(fileName);
return;
}
- for (Tree& folder : folders) {
+ for (Tree& folder : this->folders) {
if (folder.path == split[start]) {
if (start + 1 < split.size()) {
folder.InsertPath(split, start + 1, fileName);
@@ -131,19 +131,19 @@ void Tree::InsertPath(const std::vector<std::string>& split,
newFolder.path = split[start];
if (start + 1 < split.size()) {
newFolder.InsertPath(split, start + 1, fileName);
- folders.push_back(newFolder);
+ this->folders.push_back(newFolder);
return;
}
// last part of split
newFolder.files.insert(fileName);
- folders.push_back(newFolder);
+ this->folders.push_back(newFolder);
}
void Tree::BuildVirtualFolder(cmXMLWriter& xml) const
{
xml.StartElement("Option");
std::string virtualFolders = "CMake Files\\;";
- for (Tree const& folder : folders) {
+ for (Tree const& folder : this->folders) {
folder.BuildVirtualFolderImpl(virtualFolders, "");
}
xml.Attribute("virtualFolders", virtualFolders);
@@ -153,15 +153,15 @@ void Tree::BuildVirtualFolder(cmXMLWriter& xml) const
void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
const std::string& prefix) const
{
- virtualFolders += "CMake Files\\" + prefix + path + "\\;";
- for (Tree const& folder : folders) {
- folder.BuildVirtualFolderImpl(virtualFolders, prefix + path + "\\");
+ virtualFolders += "CMake Files\\" + prefix + this->path + "\\;";
+ for (Tree const& folder : this->folders) {
+ folder.BuildVirtualFolderImpl(virtualFolders, prefix + this->path + "\\");
}
}
void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
{
- for (std::string const& f : files) {
+ for (std::string const& f : this->files) {
xml.StartElement("Unit");
xml.Attribute("filename", fsPath + f);
@@ -171,7 +171,7 @@ void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
xml.EndElement();
}
- for (Tree const& folder : folders) {
+ for (Tree const& folder : this->folders) {
folder.BuildUnitImpl(xml, "", fsPath);
}
}
@@ -180,20 +180,21 @@ void Tree::BuildUnitImpl(cmXMLWriter& xml,
const std::string& virtualFolderPath,
const std::string& fsPath) const
{
- for (std::string const& f : files) {
+ for (std::string const& f : this->files) {
xml.StartElement("Unit");
- xml.Attribute("filename", cmStrCat(fsPath, path, "/", f));
+ xml.Attribute("filename", cmStrCat(fsPath, this->path, "/", f));
xml.StartElement("Option");
- xml.Attribute("virtualFolder",
- cmStrCat("CMake Files\\", virtualFolderPath, path, "\\"));
+ xml.Attribute(
+ "virtualFolder",
+ cmStrCat("CMake Files\\", virtualFolderPath, this->path, "\\"));
xml.EndElement();
xml.EndElement();
}
- for (Tree const& folder : folders) {
- folder.BuildUnitImpl(xml, cmStrCat(virtualFolderPath, path, "\\"),
- cmStrCat(fsPath, path, "/"));
+ for (Tree const& folder : this->folders) {
+ folder.BuildUnitImpl(xml, cmStrCat(virtualFolderPath, this->path, "\\"),
+ cmStrCat(fsPath, this->path, "/"));
}
}
@@ -340,7 +341,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
all_files_map_t allFiles;
std::vector<std::string> cFiles;
- auto cm = this->GlobalGenerator->GetCMakeInstance();
+ auto* cm = this->GlobalGenerator->GetCMakeInstance();
for (cmLocalGenerator* lg : lgs) {
cmMakefile* makefile = lg->GetMakefile();
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 95cfb0a45..549b08b4e 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -64,7 +64,7 @@ void cmExtraCodeLiteGenerator::Generate()
for (auto const& it : projectMap) {
cmLocalGenerator* lg = it.second[0];
const cmMakefile* mf = lg->GetMakefile();
- this->ConfigName = GetConfigurationName(mf);
+ this->ConfigName = this->GetConfigurationName(mf);
if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
workspaceOutputDir = lg->GetCurrentBinaryDirectory();
@@ -89,9 +89,9 @@ void cmExtraCodeLiteGenerator::Generate()
std::vector<std::string> ProjectNames;
if (targetsAreProjects) {
- ProjectNames = CreateProjectsByTarget(&xml);
+ ProjectNames = this->CreateProjectsByTarget(&xml);
} else {
- ProjectNames = CreateProjectsByProjectMaps(&xml);
+ ProjectNames = this->CreateProjectsByProjectMaps(&xml);
}
xml.StartElement("BuildMatrix");
@@ -142,7 +142,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
xml->Attribute("Active", "No");
xml->EndElement();
- CreateNewProjectFile(lt.get(), filename);
+ this->CreateNewProjectFile(lt.get(), filename);
break;
default:
break;
@@ -268,7 +268,7 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
cmMakefile* makefile = lg->GetMakefile();
for (const auto& target : lg->GetGeneratorTargets()) {
projectType =
- CollectSourceFiles(makefile, target.get(), cFiles, otherFiles);
+ this->CollectSourceFiles(makefile, target.get(), cFiles, otherFiles);
}
}
@@ -276,8 +276,8 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
// their relative path)
std::string projectPath = cmSystemTools::GetFilenamePath(filename);
- CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
- projectType, "");
+ this->CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
+ projectType, "");
xml.EndElement(); // CodeLite_Project
}
@@ -402,7 +402,7 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
const std::string& projectType, const std::string& targetName)
{
cmXMLWriter& xml(*_xml);
- FindMatchingHeaderfiles(cFiles, otherFiles);
+ this->FindMatchingHeaderfiles(cFiles, otherFiles);
// Create 2 virtual folders: src and include
// and place all the implementation files into the src
// folder, the rest goes to the include folder
@@ -498,10 +498,10 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
xml.StartElement("CustomBuild");
xml.Attribute("Enabled", "yes");
- xml.Element("RebuildCommand", GetRebuildCommand(mf, targetName));
- xml.Element("CleanCommand", GetCleanCommand(mf, targetName));
- xml.Element("BuildCommand", GetBuildCommand(mf, targetName));
- xml.Element("SingleFileCommand", GetSingleFileBuildCommand(mf));
+ xml.Element("RebuildCommand", this->GetRebuildCommand(mf, targetName));
+ xml.Element("CleanCommand", this->GetCleanCommand(mf, targetName));
+ xml.Element("BuildCommand", this->GetBuildCommand(mf, targetName));
+ xml.Element("SingleFileCommand", this->GetSingleFileBuildCommand(mf));
xml.Element("PreprocessFileCommand");
xml.Element("WorkingDirectory", "$(WorkspacePath)");
xml.EndElement(); // CustomBuild
@@ -570,14 +570,14 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
std::map<std::string, cmSourceFile*> cFiles;
std::set<std::string> otherFiles;
- projectType = CollectSourceFiles(mf, gt, cFiles, otherFiles);
+ projectType = this->CollectSourceFiles(mf, gt, cFiles, otherFiles);
// Get the project path ( we need it later to convert files to
// their relative path)
std::string projectPath = cmSystemTools::GetFilenamePath(filename);
- CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
- projectType, targetName);
+ this->CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
+ projectType, targetName);
xml.EndElement(); // CodeLite_Project
}
@@ -648,7 +648,7 @@ std::string cmExtraCodeLiteGenerator::GetCleanCommand(
{
std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
std::ostringstream ss;
- std::string buildcommand = GetBuildCommand(mf, "");
+ std::string buildcommand = this->GetBuildCommand(mf, "");
if (!targetName.empty() && generator == "Ninja") {
ss << buildcommand << " -t clean " << targetName;
} else {
@@ -660,8 +660,8 @@ std::string cmExtraCodeLiteGenerator::GetCleanCommand(
std::string cmExtraCodeLiteGenerator::GetRebuildCommand(
const cmMakefile* mf, const std::string& targetName) const
{
- return GetCleanCommand(mf, targetName) + " && " +
- GetBuildCommand(mf, targetName);
+ return this->GetCleanCommand(mf, targetName) + " && " +
+ this->GetBuildCommand(mf, targetName);
}
std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand(
diff --git a/Source/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h
index 2478585b6..2bb1c0439 100644
--- a/Source/cmExtraCodeLiteGenerator.h
+++ b/Source/cmExtraCodeLiteGenerator.h
@@ -24,7 +24,6 @@ protected:
std::string WorkspacePath;
unsigned int CpuCount = 2;
-protected:
std::string GetCodeLiteCompilerName(const cmMakefile* mf) const;
std::string GetConfigurationName(const cmMakefile* mf) const;
std::string GetBuildCommand(const cmMakefile* mf,
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 7c3614435..a92f6e328 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -132,7 +132,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile(
// doesn't currently support these settings per build system, only project
// wide
MapSourceFileFlags sourceFileFlags;
- AppendAllTargets(lgs, mf, fout, sourceFileFlags);
+ this->AppendAllTargets(lgs, mf, fout, sourceFileFlags);
// End of build_systems
fout << "\n\t]";
@@ -349,6 +349,11 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
if (language.empty()) {
language = "C";
}
+
+ // Explicitly add the explicit language flag before any other flag
+ // so user flags can override it.
+ gtgt->AddExplicitLanguageFlags(flags, *source);
+
std::string const& config =
lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index d88617a01..77d57957c 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -10,6 +10,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
@@ -98,9 +99,11 @@ bool cmFLTKWrapUICommand(std::vector<std::string> const& args,
const char* no_comment = nullptr;
const char* no_working_dir = nullptr;
mf.AddCustomCommandToOutput(cxxres, depends, no_main_dependency,
- commandLines, no_comment, no_working_dir);
+ commandLines, no_comment, no_working_dir,
+ mf.GetPolicyStatus(cmPolicies::CMP0116));
mf.AddCustomCommandToOutput(hname, depends, no_main_dependency,
- commandLines, no_comment, no_working_dir);
+ commandLines, no_comment, no_working_dir,
+ mf.GetPolicyStatus(cmPolicies::CMP0116));
cmSourceFile* sf = mf.GetSource(cxxres);
sf->AddDepend(hname);
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index c2ab2f10b..d2a9becf4 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -18,6 +18,7 @@
#include "cmFileAPICMakeFiles.h"
#include "cmFileAPICache.h"
#include "cmFileAPICodemodel.h"
+#include "cmFileAPIToolchains.h"
#include "cmGlobalGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -262,6 +263,17 @@ bool cmFileAPI::ReadQuery(std::string const& query,
objects.push_back(o);
return true;
}
+ if (kindName == ObjectKindName(ObjectKind::Toolchains)) {
+ Object o;
+ o.Kind = ObjectKind::Toolchains;
+ if (verStr == "v1") {
+ o.Version = 1;
+ } else {
+ return false;
+ }
+ objects.push_back(o);
+ return true;
+ }
if (kindName == ObjectKindName(ObjectKind::InternalTest)) {
Object o;
o.Kind = ObjectKind::InternalTest;
@@ -402,6 +414,7 @@ const char* cmFileAPI::ObjectKindName(ObjectKind kind)
"codemodel", //
"cache", //
"cmakeFiles", //
+ "toolchains", //
"__test" //
};
return objectKindNames[size_t(kind)];
@@ -435,6 +448,9 @@ Json::Value cmFileAPI::BuildObject(Object const& object)
case ObjectKind::CMakeFiles:
value = this->BuildCMakeFiles(object);
break;
+ case ObjectKind::Toolchains:
+ value = this->BuildToolchains(object);
+ break;
case ObjectKind::InternalTest:
value = this->BuildInternalTest(object);
break;
@@ -491,6 +507,8 @@ cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
r.Kind = ObjectKind::Cache;
} else if (kindName == this->ObjectKindName(ObjectKind::CMakeFiles)) {
r.Kind = ObjectKind::CMakeFiles;
+ } else if (kindName == this->ObjectKindName(ObjectKind::Toolchains)) {
+ r.Kind = ObjectKind::Toolchains;
} else if (kindName == this->ObjectKindName(ObjectKind::InternalTest)) {
r.Kind = ObjectKind::InternalTest;
} else {
@@ -518,6 +536,9 @@ cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
case ObjectKind::CMakeFiles:
this->BuildClientRequestCMakeFiles(r, versions);
break;
+ case ObjectKind::Toolchains:
+ this->BuildClientRequestToolchains(r, versions);
+ break;
case ObjectKind::InternalTest:
this->BuildClientRequestInternalTest(r, versions);
break;
@@ -765,6 +786,40 @@ Json::Value cmFileAPI::BuildCMakeFiles(Object const& object)
return cmakeFiles;
}
+// The "toolchains" object kind.
+
+static unsigned int const ToolchainsV1Minor = 0;
+
+void cmFileAPI::BuildClientRequestToolchains(
+ ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+ // Select a known version from those requested.
+ for (RequestVersion const& v : versions) {
+ if ((v.Major == 1 && v.Minor <= ToolchainsV1Minor)) {
+ r.Version = v.Major;
+ break;
+ }
+ }
+ if (!r.Version) {
+ r.Error = NoSupportedVersion(versions);
+ }
+}
+
+Json::Value cmFileAPI::BuildToolchains(Object const& object)
+{
+ Json::Value toolchains = cmFileAPIToolchainsDump(*this, object.Version);
+ toolchains["kind"] = this->ObjectKindName(object.Kind);
+
+ Json::Value& version = toolchains["version"];
+ if (object.Version == 1) {
+ version = BuildVersion(1, ToolchainsV1Minor);
+ } else {
+ return toolchains; // should be unreachable
+ }
+
+ return toolchains;
+}
+
// The "__test" object kind is for internal testing of CMake.
static unsigned int const InternalTestV1Minor = 3;
@@ -828,5 +883,13 @@ Json::Value cmFileAPI::ReportCapabilities()
requests.append(std::move(request)); // NOLINT(*)
}
+ {
+ Json::Value request = Json::objectValue;
+ request["kind"] = ObjectKindName(ObjectKind::Toolchains);
+ Json::Value& versions = request["version"] = Json::arrayValue;
+ versions.append(BuildVersion(1, ToolchainsV1Minor));
+ requests.append(std::move(request)); // NOLINT(*)
+ }
+
return capabilities;
}
diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h
index 086a92a2b..22302b408 100644
--- a/Source/cmFileAPI.h
+++ b/Source/cmFileAPI.h
@@ -56,6 +56,7 @@ private:
CodeModel,
Cache,
CMakeFiles,
+ Toolchains,
InternalTest
};
@@ -200,6 +201,10 @@ private:
ClientRequest& r, std::vector<RequestVersion> const& versions);
Json::Value BuildCMakeFiles(Object const& object);
+ void BuildClientRequestToolchains(
+ ClientRequest& r, std::vector<RequestVersion> const& versions);
+ Json::Value BuildToolchains(Object const& object);
+
void BuildClientRequestInternalTest(
ClientRequest& r, std::vector<RequestVersion> const& versions);
Json::Value BuildInternalTest(Object const& object);
diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx
index 1e4f3b62b..e208ca8ba 100644
--- a/Source/cmFileAPICMakeFiles.cxx
+++ b/Source/cmFileAPICMakeFiles.cxx
@@ -41,7 +41,7 @@ CMakeFiles::CMakeFiles(cmFileAPI& fileAPI, unsigned long version)
, CMakeModules(cmSystemTools::GetCMakeRoot() + "/Modules")
, TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
, TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
- , OutOfSource(TopBuild != TopSource)
+ , OutOfSource(this->TopBuild != this->TopSource)
{
static_cast<void>(this->Version);
}
@@ -50,7 +50,7 @@ Json::Value CMakeFiles::Dump()
{
Json::Value cmakeFiles = Json::objectValue;
cmakeFiles["paths"] = this->DumpPaths();
- cmakeFiles["inputs"] = DumpInputs();
+ cmakeFiles["inputs"] = this->DumpInputs();
return cmakeFiles;
}
diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx
index 3ba943a45..ddae5273b 100644
--- a/Source/cmFileAPICache.cxx
+++ b/Source/cmFileAPICache.cxx
@@ -44,7 +44,7 @@ Cache::Cache(cmFileAPI& fileAPI, unsigned long version)
Json::Value Cache::Dump()
{
Json::Value cache = Json::objectValue;
- cache["entries"] = DumpEntries();
+ cache["entries"] = this->DumpEntries();
return cache;
}
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 4a53c8a8c..90611092b 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -145,7 +145,7 @@ class JBTIndex
{
public:
JBTIndex() = default;
- explicit operator bool() const { return Index != None; }
+ explicit operator bool() const { return this->Index != None; }
Json::ArrayIndex Index = None;
static Json::ArrayIndex const None = static_cast<Json::ArrayIndex>(-1);
};
@@ -1324,7 +1324,7 @@ Json::Value Target::DumpInstallDestinations()
{
Json::Value destinations = Json::arrayValue;
auto installGens = this->GT->Target->GetInstallGenerators();
- for (auto itGen : installGens) {
+ for (auto* itGen : installGens) {
destinations.append(this->DumpInstallDestination(itGen));
}
return destinations;
diff --git a/Source/cmFileAPIToolchains.cxx b/Source/cmFileAPIToolchains.cxx
new file mode 100644
index 000000000..722c1145e
--- /dev/null
+++ b/Source/cmFileAPIToolchains.cxx
@@ -0,0 +1,151 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileAPIToolchains.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm3p/json/value.h>
+
+#include "cmFileAPI.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmProperty.h"
+#include "cmState.h"
+#include "cmStringAlgorithms.h"
+#include "cmake.h"
+
+namespace {
+
+struct ToolchainVariable
+{
+ std::string ObjectKey;
+ std::string VariableSuffix;
+ bool IsList;
+};
+
+class Toolchains
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+
+ static const std::vector<ToolchainVariable> CompilerVariables;
+ static const std::vector<ToolchainVariable> CompilerImplicitVariables;
+ static const ToolchainVariable SourceFileExtensionsVariable;
+
+ Json::Value DumpToolchains();
+ Json::Value DumpToolchain(std::string const& lang);
+ Json::Value DumpToolchainVariables(
+ cmMakefile const* mf, std::string const& lang,
+ std::vector<ToolchainVariable> const& variables);
+ void DumpToolchainVariable(cmMakefile const* mf, Json::Value& object,
+ std::string const& lang,
+ ToolchainVariable const& variable);
+
+public:
+ Toolchains(cmFileAPI& fileAPI, unsigned long version);
+ Json::Value Dump();
+};
+
+const std::vector<ToolchainVariable> Toolchains::CompilerVariables{
+ { "path", "COMPILER", false },
+ { "id", "COMPILER_ID", false },
+ { "version", "COMPILER_VERSION", false },
+ { "target", "COMPILER_TARGET", false },
+};
+
+const std::vector<ToolchainVariable> Toolchains::CompilerImplicitVariables{
+ { "includeDirectories", "IMPLICIT_INCLUDE_DIRECTORIES", true },
+ { "linkDirectories", "IMPLICIT_LINK_DIRECTORIES", true },
+ { "linkFrameworkDirectories", "IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", true },
+ { "linkLibraries", "IMPLICIT_LINK_LIBRARIES", true },
+};
+
+const ToolchainVariable Toolchains::SourceFileExtensionsVariable{
+ "sourceFileExtensions", "SOURCE_FILE_EXTENSIONS", true
+};
+
+Toolchains::Toolchains(cmFileAPI& fileAPI, unsigned long version)
+ : FileAPI(fileAPI)
+ , Version(version)
+{
+ static_cast<void>(this->Version);
+}
+
+Json::Value Toolchains::Dump()
+{
+ Json::Value toolchains = Json::objectValue;
+ toolchains["toolchains"] = this->DumpToolchains();
+ return toolchains;
+}
+
+Json::Value Toolchains::DumpToolchains()
+{
+ Json::Value toolchains = Json::arrayValue;
+
+ for (std::string const& lang :
+ this->FileAPI.GetCMakeInstance()->GetState()->GetEnabledLanguages()) {
+ toolchains.append(this->DumpToolchain(lang));
+ }
+
+ return toolchains;
+}
+
+Json::Value Toolchains::DumpToolchain(std::string const& lang)
+{
+ const auto& mf =
+ this->FileAPI.GetCMakeInstance()->GetGlobalGenerator()->GetMakefiles()[0];
+ Json::Value toolchain = Json::objectValue;
+ toolchain["language"] = lang;
+ toolchain["compiler"] =
+ this->DumpToolchainVariables(mf.get(), lang, CompilerVariables);
+ toolchain["compiler"]["implicit"] =
+ this->DumpToolchainVariables(mf.get(), lang, CompilerImplicitVariables);
+ this->DumpToolchainVariable(mf.get(), toolchain, lang,
+ SourceFileExtensionsVariable);
+ return toolchain;
+}
+
+Json::Value Toolchains::DumpToolchainVariables(
+ cmMakefile const* mf, std::string const& lang,
+ std::vector<ToolchainVariable> const& variables)
+{
+ Json::Value object = Json::objectValue;
+ for (const auto& variable : variables) {
+ this->DumpToolchainVariable(mf, object, lang, variable);
+ }
+ return object;
+}
+
+void Toolchains::DumpToolchainVariable(cmMakefile const* mf,
+ Json::Value& object,
+ std::string const& lang,
+ ToolchainVariable const& variable)
+{
+ std::string const variableName =
+ cmStrCat("CMAKE_", lang, "_", variable.VariableSuffix);
+
+ if (variable.IsList) {
+ std::vector<std::string> values;
+ if (mf->GetDefExpandList(variableName, values)) {
+ Json::Value jsonArray = Json::arrayValue;
+ for (std::string const& value : values) {
+ jsonArray.append(value);
+ }
+ object[variable.ObjectKey] = jsonArray;
+ }
+ } else {
+ cmProp def = mf->GetDefinition(variableName);
+ if (def) {
+ object[variable.ObjectKey] = *def;
+ }
+ }
+}
+}
+
+Json::Value cmFileAPIToolchainsDump(cmFileAPI& fileAPI, unsigned long version)
+{
+ Toolchains toolchains(fileAPI, version);
+ return toolchains.Dump();
+}
diff --git a/Source/cmFileAPIToolchains.h b/Source/cmFileAPIToolchains.h
new file mode 100644
index 000000000..c1888075c
--- /dev/null
+++ b/Source/cmFileAPIToolchains.h
@@ -0,0 +1,12 @@
+/* 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 <cm3p/json/value.h>
+
+class cmFileAPI;
+
+extern Json::Value cmFileAPIToolchainsDump(cmFileAPI& fileAPI,
+ unsigned long version);
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 8a3aad2df..f674833ea 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -15,6 +15,7 @@
#include <vector>
#include <cm/memory>
+#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/string_view>
@@ -63,7 +64,7 @@
# include "cmFileLockResult.h"
#endif
-#if defined(CMAKE_USE_ELF_PARSER)
+#if defined(CMake_USE_ELF_PARSER)
# include "cmELF.h"
#endif
@@ -333,7 +334,7 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
arg_limit_count,
arg_length_minimum,
arg_length_maximum,
- arg__maximum,
+ arg_maximum,
arg_regex,
arg_encoding
};
@@ -557,8 +558,7 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
// back subsequent characters
if ((current_str.length() != num_utf8_bytes)) {
for (unsigned int j = 0; j < current_str.size() - 1; j++) {
- c = current_str[current_str.size() - 1 - j];
- fin.putback(static_cast<char>(c));
+ fin.putback(current_str[current_str.size() - 1 - j]);
}
current_str.clear();
}
@@ -1198,7 +1198,7 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
return false;
}
-#if defined(CMAKE_USE_ELF_PARSER)
+#if defined(CMake_USE_ELF_PARSER)
cmELF elf(fileNameArg.c_str());
if (!arguments.RPath.empty()) {
@@ -2290,6 +2290,7 @@ void AddEvaluationFile(const std::string& inputName,
const std::string& targetName,
const std::string& outputExpr,
const std::string& condition, bool inputIsContent,
+ const std::string& newLineCharacter, mode_t permissions,
cmExecutionStatus& status)
{
cmListFileBacktrace lfbt = status.GetMakefile().GetBacktrace();
@@ -2304,7 +2305,7 @@ void AddEvaluationFile(const std::string& inputName,
status.GetMakefile().AddEvaluationFile(
inputName, targetName, std::move(outputCge), std::move(conditionCge),
- inputIsContent);
+ newLineCharacter, permissions, inputIsContent);
}
bool HandleGenerateCommand(std::vector<std::string> const& args,
@@ -2314,49 +2315,171 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
status.SetError("Incorrect arguments to GENERATE subcommand.");
return false;
}
- if (args[1] != "OUTPUT") {
+
+ struct Arguments
+ {
+ std::string Output;
+ std::string Input;
+ std::string Content;
+ std::string Condition;
+ std::string Target;
+ std::string NewLineStyle;
+ bool NoSourcePermissions = false;
+ bool UseSourcePermissions = false;
+ std::vector<std::string> FilePermissions;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("OUTPUT"_s, &Arguments::Output)
+ .Bind("INPUT"_s, &Arguments::Input)
+ .Bind("CONTENT"_s, &Arguments::Content)
+ .Bind("CONDITION"_s, &Arguments::Condition)
+ .Bind("TARGET"_s, &Arguments::Target)
+ .Bind("NO_SOURCE_PERMISSIONS"_s, &Arguments::NoSourcePermissions)
+ .Bind("USE_SOURCE_PERMISSIONS"_s, &Arguments::UseSourcePermissions)
+ .Bind("FILE_PERMISSIONS"_s, &Arguments::FilePermissions)
+ .Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle);
+
+ std::vector<std::string> unparsedArguments;
+ std::vector<std::string> keywordsMissingValues;
+ std::vector<std::string> parsedKeywords;
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments,
+ &keywordsMissingValues, &parsedKeywords);
+
+ if (!keywordsMissingValues.empty()) {
+ status.SetError("Incorrect arguments to GENERATE subcommand.");
+ return false;
+ }
+
+ if (!unparsedArguments.empty()) {
+ status.SetError("Unknown argument to GENERATE subcommand.");
+ return false;
+ }
+
+ bool mandatoryOptionsSpecified = false;
+ if (parsedKeywords.size() > 1) {
+ const bool outputOprionSpecified = parsedKeywords[0] == "OUTPUT"_s;
+ const bool inputOrContentSpecified =
+ parsedKeywords[1] == "INPUT"_s || parsedKeywords[1] == "CONTENT"_s;
+ if (outputOprionSpecified && inputOrContentSpecified) {
+ mandatoryOptionsSpecified = true;
+ }
+ }
+ if (!mandatoryOptionsSpecified) {
status.SetError("Incorrect arguments to GENERATE subcommand.");
return false;
}
- std::string condition;
- std::string target;
+ const bool conditionOptionSpecified =
+ std::find(parsedKeywords.begin(), parsedKeywords.end(), "CONDITION"_s) !=
+ parsedKeywords.end();
+ if (conditionOptionSpecified && arguments.Condition.empty()) {
+ status.SetError("CONDITION of sub-command GENERATE must not be empty "
+ "if specified.");
+ return false;
+ }
- for (std::size_t i = 5; i < args.size();) {
- const std::string& arg = args[i++];
+ const bool targetOptionSpecified =
+ std::find(parsedKeywords.begin(), parsedKeywords.end(), "TARGET"_s) !=
+ parsedKeywords.end();
+ if (targetOptionSpecified && arguments.Target.empty()) {
+ status.SetError("TARGET of sub-command GENERATE must not be empty "
+ "if specified.");
+ return false;
+ }
+
+ const bool outputOptionSpecified =
+ std::find(parsedKeywords.begin(), parsedKeywords.end(), "OUTPUT"_s) !=
+ parsedKeywords.end();
+ if (outputOptionSpecified && parsedKeywords[0] != "OUTPUT"_s) {
+ status.SetError("Incorrect arguments to GENERATE subcommand.");
+ return false;
+ }
- if (args.size() - i == 0) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
+ const bool inputIsContent = parsedKeywords[1] != "INPUT"_s;
+ if (inputIsContent && parsedKeywords[1] != "CONTENT") {
+ status.SetError("Unknown argument to GENERATE subcommand.");
+ }
+
+ const bool newLineStyleSpecified =
+ std::find(parsedKeywords.begin(), parsedKeywords.end(),
+ "NEWLINE_STYLE"_s) != parsedKeywords.end();
+ cmNewLineStyle newLineStyle;
+ if (newLineStyleSpecified) {
+ std::string errorMessage;
+ if (!newLineStyle.ReadFromArguments(args, errorMessage)) {
+ status.SetError(cmStrCat("GENERATE ", errorMessage));
return false;
}
+ }
- const std::string& value = args[i++];
+ std::string input = arguments.Input;
+ if (inputIsContent) {
+ input = arguments.Content;
+ }
- if (value.empty()) {
- status.SetError(
- arg + " of sub-command GENERATE must not be empty if specified.");
+ if (arguments.NoSourcePermissions && arguments.UseSourcePermissions) {
+ status.SetError("given both NO_SOURCE_PERMISSIONS and "
+ "USE_SOURCE_PERMISSIONS. Only one option allowed.");
+ return false;
+ }
+
+ if (!arguments.FilePermissions.empty()) {
+ if (arguments.NoSourcePermissions) {
+ status.SetError("given both NO_SOURCE_PERMISSIONS and "
+ "FILE_PERMISSIONS. Only one option allowed.");
+ return false;
+ }
+ if (arguments.UseSourcePermissions) {
+ status.SetError("given both USE_SOURCE_PERMISSIONS and "
+ "FILE_PERMISSIONS. Only one option allowed.");
return false;
}
+ }
- if (arg == "CONDITION") {
- condition = value;
- } else if (arg == "TARGET") {
- target = value;
- } else {
- status.SetError("Unknown argument to GENERATE subcommand.");
+ if (arguments.UseSourcePermissions) {
+ if (inputIsContent) {
+ status.SetError("given USE_SOURCE_PERMISSIONS without a file INPUT.");
return false;
}
}
- std::string output = args[2];
- const bool inputIsContent = args[3] != "INPUT";
- if (inputIsContent && args[3] != "CONTENT") {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
- return false;
+ mode_t permisiions = 0;
+ if (arguments.NoSourcePermissions) {
+ permisiions |= cmFSPermissions::mode_owner_read;
+ permisiions |= cmFSPermissions::mode_owner_write;
+ permisiions |= cmFSPermissions::mode_group_read;
+ permisiions |= cmFSPermissions::mode_world_read;
}
- std::string input = args[4];
- AddEvaluationFile(input, target, output, condition, inputIsContent, status);
+ if (!arguments.FilePermissions.empty()) {
+ std::vector<std::string> invalidOptions;
+ for (auto const& e : arguments.FilePermissions) {
+ if (!cmFSPermissions::stringToModeT(e, permisiions)) {
+ invalidOptions.push_back(e);
+ }
+ }
+ if (!invalidOptions.empty()) {
+ std::ostringstream oss;
+ oss << "given invalid permission ";
+ for (auto i = 0u; i < invalidOptions.size(); i++) {
+ if (i == 0u) {
+ oss << "\"" << invalidOptions[i] << "\"";
+ } else {
+ oss << ",\"" << invalidOptions[i] << "\"";
+ }
+ }
+ oss << ".";
+ status.SetError(oss.str());
+ return false;
+ }
+ }
+
+ AddEvaluationFile(input, arguments.Target, arguments.Output,
+ arguments.Condition, inputIsContent,
+ newLineStyle.GetCharacters(), permisiions, status);
return true;
}
@@ -2902,17 +3025,60 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
bool HandleConfigureCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- if (args.size() < 5) {
- status.SetError("Incorrect arguments to CONFIGURE subcommand.");
+ struct Arguments
+ {
+ std::string Output;
+ std::string Content;
+ bool EscapeQuotes = false;
+ bool AtOnly = false;
+ std::string NewlineStyle;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("OUTPUT"_s, &Arguments::Output)
+ .Bind("CONTENT"_s, &Arguments::Content)
+ .Bind("ESCAPE_QUOTES"_s, &Arguments::EscapeQuotes)
+ .Bind("@ONLY"_s, &Arguments::AtOnly)
+ .Bind("NEWLINE_STYLE"_s, &Arguments::NewlineStyle);
+
+ std::vector<std::string> unrecognizedArguments;
+ std::vector<std::string> keywordsMissingArguments;
+ std::vector<std::string> parsedKeywords;
+ auto parsedArgs =
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
+ &keywordsMissingArguments, &parsedKeywords);
+
+ auto argIt = unrecognizedArguments.begin();
+ if (argIt != unrecognizedArguments.end()) {
+ status.SetError(
+ cmStrCat("CONFIGURE Unrecognized argument: \"", *argIt, "\""));
+ cmSystemTools::SetFatalErrorOccured();
return false;
}
- if (args[1] != "OUTPUT") {
- status.SetError("Incorrect arguments to CONFIGURE subcommand.");
- return false;
+
+ std::vector<std::string> mandatoryOptions{ "OUTPUT", "CONTENT" };
+ for (auto const& e : mandatoryOptions) {
+ const bool optionHasNoValue =
+ std::find(keywordsMissingArguments.begin(),
+ keywordsMissingArguments.end(),
+ e) != keywordsMissingArguments.end();
+ if (optionHasNoValue) {
+ status.SetError(cmStrCat("CONFIGURE ", e, " option needs a value."));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
}
- if (args[3] != "CONTENT") {
- status.SetError("Incorrect arguments to CONFIGURE subcommand.");
- return false;
+
+ for (auto const& e : mandatoryOptions) {
+ const bool optionGiven =
+ std::find(parsedKeywords.begin(), parsedKeywords.end(), e) !=
+ parsedKeywords.end();
+ if (!optionGiven) {
+ status.SetError(cmStrCat("CONFIGURE ", e, " option is mandatory."));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
}
std::string errorMessage;
@@ -2922,28 +3088,9 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
return false;
}
- bool escapeQuotes = false;
- bool atOnly = false;
- for (unsigned int i = 5; i < args.size(); ++i) {
- if (args[i] == "@ONLY") {
- atOnly = true;
- } else if (args[i] == "ESCAPE_QUOTES") {
- escapeQuotes = true;
- } else if (args[i] == "NEWLINE_STYLE" || args[i] == "LF" ||
- args[i] == "UNIX" || args[i] == "CRLF" || args[i] == "WIN32" ||
- args[i] == "DOS") {
- /* Options handled by NewLineStyle member above. */
- } else {
- status.SetError(
- cmStrCat("CONFIGURE Unrecognized argument \"", args[i], "\""));
- return false;
- }
- }
-
// Check for generator expressions
- const std::string input = args[4];
std::string outputFile = cmSystemTools::CollapseFullPath(
- args[2], status.GetMakefile().GetCurrentBinaryDirectory());
+ parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
std::string::size_type pos = outputFile.find_first_of("<>");
if (pos != std::string::npos) {
@@ -2974,11 +3121,11 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
cmSystemTools::MakeDirectory(path);
}
- std::string newLineCharacters;
+ std::string newLineCharacters = "\n";
bool open_with_binary_flag = false;
if (newLineStyle.IsValid()) {
- open_with_binary_flag = true;
newLineCharacters = newLineStyle.GetCharacters();
+ open_with_binary_flag = true;
}
cmGeneratedFileStream fout;
@@ -2992,13 +3139,18 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
fout.SetCopyIfDifferent(true);
// copy input to output and expand variables from input at the same time
- std::stringstream sin(input, std::ios::in);
+ std::stringstream sin(parsedArgs.Content, std::ios::in);
std::string inLine;
std::string outLine;
- while (cmSystemTools::GetLineFromStream(sin, inLine)) {
+ bool hasNewLine = false;
+ while (cmSystemTools::GetLineFromStream(sin, inLine, &hasNewLine)) {
outLine.clear();
- makeFile.ConfigureString(inLine, outLine, atOnly, escapeQuotes);
- fout << outLine << newLineCharacters;
+ makeFile.ConfigureString(inLine, outLine, parsedArgs.AtOnly,
+ parsedArgs.EscapeQuotes);
+ fout << outLine;
+ if (hasNewLine || newLineStyle.IsValid()) {
+ fout << newLineCharacters;
+ }
}
// close file before attempting to copy
diff --git a/Source/cmFileLock.cxx b/Source/cmFileLock.cxx
index 6010233ca..5d197d2fb 100644
--- a/Source/cmFileLock.cxx
+++ b/Source/cmFileLock.cxx
@@ -80,7 +80,9 @@ bool cmFileLock::IsLocked(const std::string& filename) const
}
#if defined(_WIN32)
+// NOLINTNEXTLINE(bugprone-suspicious-include)
# include "cmFileLockWin32.cxx"
#else
+// NOLINTNEXTLINE(bugprone-suspicious-include)
# include "cmFileLockUnix.cxx"
#endif
diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h
index 2b125afcc..94baea1fe 100644
--- a/Source/cmFileLock.h
+++ b/Source/cmFileLock.h
@@ -57,7 +57,7 @@ private:
BOOL LockFile(DWORD flags);
#else
int File = -1;
- int LockFile(int cmd, int type);
+ int LockFile(int cmd, int type) const;
#endif
std::string Filename;
diff --git a/Source/cmFileLockPool.cxx b/Source/cmFileLockPool.cxx
index e1f6e948a..99f6885e1 100644
--- a/Source/cmFileLockPool.cxx
+++ b/Source/cmFileLockPool.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileLockPool.h"
+#include <algorithm>
#include <cassert>
#include <utility>
@@ -145,10 +146,8 @@ cmFileLockResult cmFileLockPool::ScopePool::Release(
bool cmFileLockPool::ScopePool::IsAlreadyLocked(
const std::string& filename) const
{
- for (auto const& lock : this->Locks) {
- if (lock.IsLocked(filename)) {
- return true;
- }
- }
- return false;
+ return std::any_of(this->Locks.begin(), this->Locks.end(),
+ [&filename](cmFileLock const& lock) -> bool {
+ return lock.IsLocked(filename);
+ });
}
diff --git a/Source/cmFileLockUnix.cxx b/Source/cmFileLockUnix.cxx
index 1456ea8c1..613c6eeb5 100644
--- a/Source/cmFileLockUnix.cxx
+++ b/Source/cmFileLockUnix.cxx
@@ -64,7 +64,7 @@ cmFileLockResult cmFileLock::LockWithTimeout(unsigned long seconds)
}
}
-int cmFileLock::LockFile(int cmd, int type)
+int cmFileLock::LockFile(int cmd, int type) const
{
struct ::flock lock;
lock.l_start = 0;
diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx
deleted file mode 100644
index 8cfdb2ddd..000000000
--- a/Source/cmFileMonitor.cxx
+++ /dev/null
@@ -1,383 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmFileMonitor.h"
-
-#include <cassert>
-#include <cstddef>
-#include <unordered_map>
-#include <utility>
-
-#include <cm/memory>
-
-#include "cmsys/SystemTools.hxx"
-
-namespace {
-void on_directory_change(uv_fs_event_t* handle, const char* filename,
- int events, int status);
-void on_fs_close(uv_handle_t* handle);
-} // namespace
-
-class cmIBaseWatcher
-{
-public:
- virtual ~cmIBaseWatcher() = default;
-
- virtual void Trigger(const std::string& pathSegment, int events,
- int status) const = 0;
- virtual std::string Path() const = 0;
- virtual uv_loop_t* Loop() const = 0;
-
- virtual void StartWatching() = 0;
- virtual void StopWatching() = 0;
-
- virtual std::vector<std::string> WatchedFiles() const = 0;
- virtual std::vector<std::string> WatchedDirectories() const = 0;
-};
-
-class cmVirtualDirectoryWatcher : public cmIBaseWatcher
-{
-public:
- ~cmVirtualDirectoryWatcher() override = default;
-
- cmIBaseWatcher* Find(const std::string& ps)
- {
- const auto i = this->Children.find(ps);
- return (i == this->Children.end()) ? nullptr : i->second.get();
- }
-
- void Trigger(const std::string& pathSegment, int events,
- int status) const final
- {
- if (pathSegment.empty()) {
- for (auto const& child : this->Children) {
- child.second->Trigger(std::string(), events, status);
- }
- } else {
- const auto i = this->Children.find(pathSegment);
- if (i != this->Children.end()) {
- i->second->Trigger(std::string(), events, status);
- }
- }
- }
-
- void StartWatching() override
- {
- for (auto const& child : this->Children) {
- child.second->StartWatching();
- }
- }
-
- void StopWatching() override
- {
- for (auto const& child : this->Children) {
- child.second->StopWatching();
- }
- }
-
- std::vector<std::string> WatchedFiles() const final
- {
- std::vector<std::string> result;
- for (auto const& child : this->Children) {
- for (std::string const& f : child.second->WatchedFiles()) {
- result.push_back(f);
- }
- }
- return result;
- }
-
- std::vector<std::string> WatchedDirectories() const override
- {
- std::vector<std::string> result;
- for (auto const& child : this->Children) {
- for (std::string const& dir : child.second->WatchedDirectories()) {
- result.push_back(dir);
- }
- }
- return result;
- }
-
- void Reset() { this->Children.clear(); }
-
- void AddChildWatcher(const std::string& ps, cmIBaseWatcher* watcher)
- {
- assert(!ps.empty());
- assert(this->Children.find(ps) == this->Children.end());
- assert(watcher);
-
- this->Children.emplace(ps, std::unique_ptr<cmIBaseWatcher>(watcher));
- }
-
-private:
- std::unordered_map<std::string, std::unique_ptr<cmIBaseWatcher>>
- Children; // owned!
-};
-
-// Root of all the different (on windows!) root directories:
-class cmRootWatcher : public cmVirtualDirectoryWatcher
-{
-public:
- cmRootWatcher(uv_loop_t* loop)
- : mLoop(loop)
- {
- assert(loop);
- }
-
- std::string Path() const final
- {
- assert(false);
- return std::string();
- }
- uv_loop_t* Loop() const final { return this->mLoop; }
-
-private:
- uv_loop_t* const mLoop; // no ownership!
-};
-
-// Real directories:
-class cmRealDirectoryWatcher : public cmVirtualDirectoryWatcher
-{
-public:
- cmRealDirectoryWatcher(cmVirtualDirectoryWatcher* p, const std::string& ps)
- : Parent(p)
- , PathSegment(ps)
- {
- assert(p);
- assert(!ps.empty());
-
- p->AddChildWatcher(ps, this);
- }
-
- void StartWatching() final
- {
- if (!this->Handle) {
- this->Handle = new uv_fs_event_t;
-
- uv_fs_event_init(this->Loop(), this->Handle);
- this->Handle->data = this;
- uv_fs_event_start(this->Handle, &on_directory_change, Path().c_str(), 0);
- }
- cmVirtualDirectoryWatcher::StartWatching();
- }
-
- void StopWatching() final
- {
- if (this->Handle) {
- uv_fs_event_stop(this->Handle);
- if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(this->Handle))) {
- uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
- }
- this->Handle = nullptr;
- }
- cmVirtualDirectoryWatcher::StopWatching();
- }
-
- uv_loop_t* Loop() const final { return this->Parent->Loop(); }
-
- std::vector<std::string> WatchedDirectories() const override
- {
- std::vector<std::string> result = { Path() };
- for (std::string const& dir :
- cmVirtualDirectoryWatcher::WatchedDirectories()) {
- result.push_back(dir);
- }
- return result;
- }
-
-protected:
- cmVirtualDirectoryWatcher* const Parent;
- const std::string PathSegment;
-
-private:
- uv_fs_event_t* Handle = nullptr; // owner!
-};
-
-// Root directories:
-class cmRootDirectoryWatcher : public cmRealDirectoryWatcher
-{
-public:
- cmRootDirectoryWatcher(cmRootWatcher* p, const std::string& ps)
- : cmRealDirectoryWatcher(p, ps)
- {
- }
-
- std::string Path() const final { return this->PathSegment; }
-};
-
-// Normal directories below root:
-class cmDirectoryWatcher : public cmRealDirectoryWatcher
-{
-public:
- cmDirectoryWatcher(cmRealDirectoryWatcher* p, const std::string& ps)
- : cmRealDirectoryWatcher(p, ps)
- {
- }
-
- std::string Path() const final
- {
- return this->Parent->Path() + this->PathSegment + "/";
- }
-};
-
-class cmFileWatcher : public cmIBaseWatcher
-{
-public:
- cmFileWatcher(cmRealDirectoryWatcher* p, const std::string& ps,
- cmFileMonitor::Callback cb)
- : Parent(p)
- , PathSegment(ps)
- , CbList({ std::move(cb) })
- {
- assert(p);
- assert(!ps.empty());
- p->AddChildWatcher(ps, this);
- }
-
- void StartWatching() final {}
-
- void StopWatching() final {}
-
- void AppendCallback(cmFileMonitor::Callback const& cb)
- {
- this->CbList.push_back(cb);
- }
-
- std::string Path() const final
- {
- return this->Parent->Path() + this->PathSegment;
- }
-
- std::vector<std::string> WatchedDirectories() const final { return {}; }
-
- std::vector<std::string> WatchedFiles() const final
- {
- return { this->Path() };
- }
-
- void Trigger(const std::string& ps, int events, int status) const final
- {
- assert(ps.empty());
- assert(status == 0);
- static_cast<void>(ps);
-
- const std::string path = this->Path();
- for (cmFileMonitor::Callback const& cb : this->CbList) {
- cb(path, events, status);
- }
- }
-
- uv_loop_t* Loop() const final { return this->Parent->Loop(); }
-
-private:
- cmRealDirectoryWatcher* Parent;
- const std::string PathSegment;
- std::vector<cmFileMonitor::Callback> CbList;
-};
-
-namespace {
-
-void on_directory_change(uv_fs_event_t* handle, const char* filename,
- int events, int status)
-{
- const cmIBaseWatcher* const watcher =
- static_cast<const cmIBaseWatcher*>(handle->data);
- const std::string pathSegment(filename ? filename : "");
- watcher->Trigger(pathSegment, events, status);
-}
-
-void on_fs_close(uv_handle_t* handle)
-{
- delete reinterpret_cast<uv_fs_event_t*>(handle);
-}
-
-} // namespace
-
-cmFileMonitor::cmFileMonitor(uv_loop_t* l)
- : Root(cm::make_unique<cmRootWatcher>(l))
-{
-}
-
-cmFileMonitor::~cmFileMonitor() = default;
-
-void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths,
- Callback const& cb)
-{
- for (std::string const& p : paths) {
- std::vector<std::string> pathSegments;
- cmsys::SystemTools::SplitPath(p, pathSegments, true);
- const bool pathIsFile = !cmsys::SystemTools::FileIsDirectory(p);
-
- const size_t segmentCount = pathSegments.size();
- if (segmentCount < 2) { // Expect at least rootdir and filename
- continue;
- }
- cmVirtualDirectoryWatcher* currentWatcher = this->Root.get();
- for (size_t i = 0; i < segmentCount; ++i) {
- assert(currentWatcher);
-
- const bool fileSegment = (i == segmentCount - 1 && pathIsFile);
- const bool rootSegment = (i == 0);
- assert(
- !(fileSegment &&
- rootSegment)); // Can not be both filename and root part of the path!
-
- const std::string& currentSegment = pathSegments[i];
- if (currentSegment.empty()) {
- continue;
- }
-
- cmIBaseWatcher* nextWatcher = currentWatcher->Find(currentSegment);
- if (!nextWatcher) {
- if (rootSegment) { // Root part
- assert(currentWatcher == this->Root.get());
- nextWatcher =
- new cmRootDirectoryWatcher(this->Root.get(), currentSegment);
- assert(currentWatcher->Find(currentSegment) == nextWatcher);
- } else if (fileSegment) { // File part
- assert(currentWatcher != this->Root.get());
- nextWatcher = new cmFileWatcher(
- dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
- currentSegment, cb);
- assert(currentWatcher->Find(currentSegment) == nextWatcher);
- } else { // Any normal directory in between
- nextWatcher = new cmDirectoryWatcher(
- dynamic_cast<cmRealDirectoryWatcher*>(currentWatcher),
- currentSegment);
- assert(currentWatcher->Find(currentSegment) == nextWatcher);
- }
- } else {
- if (fileSegment) {
- auto filePtr = dynamic_cast<cmFileWatcher*>(nextWatcher);
- assert(filePtr);
- filePtr->AppendCallback(cb);
- continue;
- }
- }
- currentWatcher = dynamic_cast<cmVirtualDirectoryWatcher*>(nextWatcher);
- }
- }
- this->Root->StartWatching();
-}
-
-void cmFileMonitor::StopMonitoring()
-{
- this->Root->StopWatching();
- this->Root->Reset();
-}
-
-std::vector<std::string> cmFileMonitor::WatchedFiles() const
-{
- std::vector<std::string> result;
- if (this->Root) {
- result = this->Root->WatchedFiles();
- }
- return result;
-}
-
-std::vector<std::string> cmFileMonitor::WatchedDirectories() const
-{
- std::vector<std::string> result;
- if (this->Root) {
- result = this->Root->WatchedDirectories();
- }
- return result;
-}
diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h
deleted file mode 100644
index fc75b0cee..000000000
--- a/Source/cmFileMonitor.h
+++ /dev/null
@@ -1,35 +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 <functional>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <cm3p/uv.h>
-
-class cmRootWatcher;
-
-class cmFileMonitor
-{
-
-public:
- cmFileMonitor(uv_loop_t* l);
- ~cmFileMonitor();
-
- cmFileMonitor(cmFileMonitor const&) = delete;
- cmFileMonitor& operator=(cmFileMonitor const&) = delete;
-
- using Callback = std::function<void(const std::string&, int, int)>;
- void MonitorPaths(const std::vector<std::string>& paths, Callback const& cb);
- void StopMonitoring();
-
- std::vector<std::string> WatchedFiles() const;
- std::vector<std::string> WatchedDirectories() const;
-
-private:
- std::unique_ptr<cmRootWatcher> Root;
-};
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
index bb3f610d1..6b52230ed 100644
--- a/Source/cmFilePathChecksum.cxx
+++ b/Source/cmFilePathChecksum.cxx
@@ -16,15 +16,16 @@ cmFilePathChecksum::cmFilePathChecksum(std::string const& currentSrcDir,
std::string const& projectSrcDir,
std::string const& projectBinDir)
{
- setupParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
+ this->setupParentDirs(currentSrcDir, currentBinDir, projectSrcDir,
+ projectBinDir);
}
cmFilePathChecksum::cmFilePathChecksum(cmMakefile* makefile)
{
- setupParentDirs(makefile->GetCurrentSourceDirectory(),
- makefile->GetCurrentBinaryDirectory(),
- makefile->GetHomeDirectory(),
- makefile->GetHomeOutputDirectory());
+ this->setupParentDirs(makefile->GetCurrentSourceDirectory(),
+ makefile->GetCurrentBinaryDirectory(),
+ makefile->GetHomeDirectory(),
+ makefile->GetHomeOutputDirectory());
}
void cmFilePathChecksum::setupParentDirs(std::string const& currentSrcDir,
@@ -81,5 +82,5 @@ std::string cmFilePathChecksum::get(std::string const& filePath) const
std::string cmFilePathChecksum::getPart(std::string const& filePath,
size_t length) const
{
- return get(filePath).substr(0, length);
+ return this->get(filePath).substr(0, length);
}
diff --git a/Source/cmFileTimes.cxx b/Source/cmFileTimes.cxx
index d8fe24c5b..bd896f57a 100644
--- a/Source/cmFileTimes.cxx
+++ b/Source/cmFileTimes.cxx
@@ -62,14 +62,14 @@ public:
cmFileTimes::cmFileTimes() = default;
cmFileTimes::cmFileTimes(std::string const& fileName)
{
- Load(fileName);
+ this->Load(fileName);
}
cmFileTimes::~cmFileTimes() = default;
bool cmFileTimes::Load(std::string const& fileName)
{
std::unique_ptr<Times> ptr;
- if (IsValid()) {
+ if (this->IsValid()) {
// Invalidate this and re-use times
ptr.swap(this->times);
} else {
@@ -103,7 +103,7 @@ bool cmFileTimes::Load(std::string const& fileName)
bool cmFileTimes::Store(std::string const& fileName) const
{
- if (!IsValid()) {
+ if (!this->IsValid()) {
return false;
}
diff --git a/Source/cmFileTimes.h b/Source/cmFileTimes.h
index f1916f791..50d64fd97 100644
--- a/Source/cmFileTimes.h
+++ b/Source/cmFileTimes.h
@@ -19,7 +19,7 @@ public:
~cmFileTimes();
//! @return true, if file times were loaded successfully
- bool IsValid() const { return (times != nullptr); }
+ bool IsValid() const { return (this->times != nullptr); }
//! Try to load the file times from @a fileName and @return IsValid()
bool Load(std::string const& fileName);
//! Stores the file times at @a fileName (if IsValid())
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index dee91d75d..d2f96197b 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -182,7 +182,7 @@ void cmFindCommon::SelectDefaultSearchModes()
{ this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" } }
};
- for (auto& path : search_paths) {
+ for (auto const& path : search_paths) {
cmProp def = this->Makefile->GetDefinition(path.second);
if (def) {
path.first = !cmIsOn(*def);
@@ -289,7 +289,7 @@ void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
{
std::vector<std::string> ignoreVec;
- GetIgnoredPaths(ignoreVec);
+ this->GetIgnoredPaths(ignoreVec);
ignore.insert(ignoreVec.begin(), ignoreVec.end());
}
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index b87dfe396..49b1bd74b 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -31,7 +31,7 @@ cmFindLibraryCommand::cmFindLibraryCommand(cmExecutionStatus& status)
// cmFindLibraryCommand
bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
{
- this->DebugMode = ComputeIfDebugModeWanted();
+ this->DebugMode = this->ComputeIfDebugModeWanted();
this->VariableDocumentation = "Path to a library.";
this->CMakePathName = "LIBRARY";
if (!this->ParseArguments(argsIn)) {
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 92b1e80b8..3719fe194 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -144,7 +144,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]);
}
- this->DebugMode = ComputeIfDebugModeWanted();
+ this->DebugMode = this->ComputeIfDebugModeWanted();
this->DebugBuffer.clear();
// Lookup target architecture, if any.
@@ -534,7 +534,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
loadedPackage = true;
} else {
// The package was not loaded. Report errors.
- if (HandlePackageMode(HandlePackageModeType::Module)) {
+ if (this->HandlePackageMode(HandlePackageModeType::Module)) {
loadedPackage = true;
}
}
@@ -1145,34 +1145,27 @@ bool cmFindPackageCommand::FindConfig()
bool cmFindPackageCommand::FindPrefixedConfig()
{
std::vector<std::string> const& prefixes = this->SearchPaths;
- for (std::string const& p : prefixes) {
- if (this->SearchPrefix(p)) {
- return true;
- }
- }
- return false;
+ return std::any_of(
+ prefixes.begin(), prefixes.end(),
+ [this](std::string const& p) -> bool { return this->SearchPrefix(p); });
}
bool cmFindPackageCommand::FindFrameworkConfig()
{
std::vector<std::string> const& prefixes = this->SearchPaths;
- for (std::string const& p : prefixes) {
- if (this->SearchFrameworkPrefix(p)) {
- return true;
- }
- }
- return false;
+ return std::any_of(prefixes.begin(), prefixes.end(),
+ [this](std::string const& p) -> bool {
+ return this->SearchFrameworkPrefix(p);
+ });
}
bool cmFindPackageCommand::FindAppBundleConfig()
{
std::vector<std::string> const& prefixes = this->SearchPaths;
- for (std::string const& p : prefixes) {
- if (this->SearchAppBundlePrefix(p)) {
- return true;
- }
- }
- return false;
+ return std::any_of(prefixes.begin(), prefixes.end(),
+ [this](std::string const& p) -> bool {
+ return this->SearchAppBundlePrefix(p);
+ });
}
bool cmFindPackageCommand::ReadListFile(const std::string& f,
@@ -2070,8 +2063,8 @@ public:
void SetSort(cmFindPackageCommand::SortOrderType o,
cmFindPackageCommand::SortDirectionType d)
{
- SortOrder = o;
- SortDirection = d;
+ this->SortOrder = o;
+ this->SortDirection = d;
}
protected:
@@ -2102,8 +2095,8 @@ private:
// before testing the matches check if there is a specific sorting order to
// perform
if (this->SortOrder != cmFindPackageCommand::None) {
- cmFindPackageCommand::Sort(matches.begin(), matches.end(), SortOrder,
- SortDirection);
+ cmFindPackageCommand::Sort(matches.begin(), matches.end(),
+ this->SortOrder, this->SortDirection);
}
for (std::string const& i : matches) {
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 4bab46976..3fb082603 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -22,7 +22,7 @@ cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status)
// cmFindPathCommand
bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
{
- this->DebugMode = ComputeIfDebugModeWanted();
+ this->DebugMode = this->ComputeIfDebugModeWanted();
this->VariableDocumentation = "Path to a file.";
this->CMakePathName = "INCLUDE";
if (!this->ParseArguments(argsIn)) {
@@ -80,8 +80,8 @@ std::string cmFindPathCommand::FindHeader()
return header;
}
-std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
- std::string const& dir)
+std::string cmFindPathCommand::FindHeaderInFramework(
+ std::string const& file, std::string const& dir) const
{
std::string fileName = file;
std::string frameWorkName;
diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h
index b9fe67358..6101ea1c0 100644
--- a/Source/cmFindPathCommand.h
+++ b/Source/cmFindPathCommand.h
@@ -29,7 +29,7 @@ public:
private:
std::string FindHeaderInFramework(std::string const& file,
- std::string const& dir);
+ std::string const& dir) const;
std::string FindHeader();
std::string FindNormalHeader(cmFindBaseDebugState& debug);
std::string FindFrameworkHeader(cmFindBaseDebugState& debug);
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 77728ec8a..c22462e84 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -2,6 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindProgramCommand.h"
+#include <algorithm>
+#include <string>
+
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
@@ -60,44 +63,42 @@ struct cmFindProgramHelper
}
bool CheckCompoundNames()
{
- for (std::string const& n : this->Names) {
- // Only perform search relative to current directory if the file name
- // contains a directory separator.
- if (n.find('/') != std::string::npos) {
- if (this->CheckDirectoryForName("", n)) {
- return true;
- }
- }
- }
- return false;
+ return std::any_of(this->Names.begin(), this->Names.end(),
+ [this](std::string const& n) -> bool {
+ // Only perform search relative to current directory
+ // if the file name contains a directory separator.
+ return n.find('/') != std::string::npos &&
+ this->CheckDirectoryForName("", n);
+ });
}
bool CheckDirectory(std::string const& path)
{
- for (std::string const& n : this->Names) {
- if (this->CheckDirectoryForName(path, n)) {
- return true;
- }
- }
- return false;
+ return std::any_of(this->Names.begin(), this->Names.end(),
+ [this, &path](std::string const& n) -> bool {
+ // Only perform search relative to current directory
+ // if the file name contains a directory separator.
+ return this->CheckDirectoryForName(path, n);
+ });
}
bool CheckDirectoryForName(std::string const& path, std::string const& name)
{
- for (std::string const& ext : this->Extensions) {
- if (!ext.empty() && cmHasSuffix(name, ext)) {
- continue;
- }
- this->TestNameExt = cmStrCat(name, ext);
- this->TestPath =
- cmSystemTools::CollapseFullPath(this->TestNameExt, path);
- bool exists = this->FileIsExecutable(this->TestPath);
- exists ? this->DebugSearches.FoundAt(this->TestPath)
- : this->DebugSearches.FailedAt(this->TestPath);
- if (exists) {
- this->BestPath = this->TestPath;
- return true;
- }
- }
- return false;
+ return std::any_of(this->Extensions.begin(), this->Extensions.end(),
+ [this, &path, &name](std::string const& ext) -> bool {
+ if (!ext.empty() && cmHasSuffix(name, ext)) {
+ return false;
+ }
+ this->TestNameExt = cmStrCat(name, ext);
+ this->TestPath = cmSystemTools::CollapseFullPath(
+ this->TestNameExt, path);
+ bool exists = this->FileIsExecutable(this->TestPath);
+ exists ? this->DebugSearches.FoundAt(this->TestPath)
+ : this->DebugSearches.FailedAt(this->TestPath);
+ if (exists) {
+ this->BestPath = this->TestPath;
+ return true;
+ }
+ return false;
+ });
}
bool FileIsExecutable(std::string const& file) const
{
@@ -152,7 +153,7 @@ cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status)
// cmFindProgramCommand
bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
{
- this->DebugMode = ComputeIfDebugModeWanted();
+ this->DebugMode = this->ComputeIfDebugModeWanted();
this->VariableDocumentation = "Path to a program.";
this->CMakePathName = "PROGRAM";
// call cmFindBase::ParseArguments
@@ -171,7 +172,7 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
return true;
}
- std::string const result = FindProgram();
+ std::string const result = this->FindProgram();
if (!result.empty()) {
// Save the value in the cache
this->Makefile->AddCacheDefinition(this->VariableName, result,
@@ -198,7 +199,7 @@ std::string cmFindProgramCommand::FindProgram()
std::string program;
if (this->SearchAppBundleFirst || this->SearchAppBundleOnly) {
- program = FindAppBundle();
+ program = this->FindAppBundle();
}
if (program.empty() && !this->SearchAppBundleOnly) {
program = this->FindNormalProgram();
@@ -274,7 +275,7 @@ std::string cmFindProgramCommand::FindAppBundle()
cmSystemTools::FindDirectory(appName, this->SearchPaths, true);
if (!appPath.empty()) {
- std::string executable = GetBundleExecutable(appPath);
+ std::string executable = this->GetBundleExecutable(appPath);
if (!executable.empty()) {
return cmSystemTools::CollapseFullPath(executable);
}
diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h
index b4b493b7d..38abebabe 100644
--- a/Source/cmFunctionBlocker.h
+++ b/Source/cmFunctionBlocker.h
@@ -44,7 +44,6 @@ private:
virtual bool Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus& status) = 0;
-private:
cmListFileContext StartingContext;
std::vector<cmListFileFunction> Functions;
unsigned int ScopeDepth = 1;
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 71c82d608..1359009e6 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -163,8 +163,11 @@ bool cmFunctionFunctionBlocker::Replay(
f.FilePath = this->GetStartingContext().FilePath;
f.Line = this->GetStartingContext().Line;
mf.RecordPolicies(f.Policies);
- mf.GetState()->AddScriptedCommand(this->Args.front(), std::move(f));
- return true;
+ return mf.GetState()->AddScriptedCommand(
+ this->Args.front(),
+ BT<cmState::Command>(std::move(f),
+ mf.GetBacktrace().Push(this->GetStartingContext())),
+ mf);
}
} // anonymous namespace
diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx
index 957896f52..c782bcd0a 100644
--- a/Source/cmGccDepfileLexerHelper.cxx
+++ b/Source/cmGccDepfileLexerHelper.cxx
@@ -27,23 +27,30 @@ bool cmGccDepfileLexerHelper::readFile(const char* filePath)
if (!file) {
return false;
}
- newEntry();
+ this->newEntry();
yyscan_t scanner;
cmGccDepfile_yylex_init(&scanner);
cmGccDepfile_yyset_extra(this, scanner);
cmGccDepfile_yyrestart(file, scanner);
cmGccDepfile_yylex(scanner);
cmGccDepfile_yylex_destroy(scanner);
- sanitizeContent();
+ this->sanitizeContent();
fclose(file);
- return true;
+ return this->HelperState != State::Failed;
}
void cmGccDepfileLexerHelper::newEntry()
{
+ if (this->HelperState == State::Rule && !this->Content.empty()) {
+ if (!this->Content.back().rules.empty() &&
+ !this->Content.back().rules.back().empty()) {
+ this->HelperState = State::Failed;
+ }
+ return;
+ }
this->HelperState = State::Rule;
this->Content.emplace_back();
- newRule();
+ this->newRule();
}
void cmGccDepfileLexerHelper::newRule()
@@ -56,20 +63,22 @@ void cmGccDepfileLexerHelper::newRule()
void cmGccDepfileLexerHelper::newDependency()
{
- // printf("NEW DEP\n");
+ if (this->HelperState == State::Failed) {
+ return;
+ }
this->HelperState = State::Dependency;
- if (this->Content.back().paths.empty() ||
- !this->Content.back().paths.back().empty()) {
- this->Content.back().paths.emplace_back();
+ auto& entry = this->Content.back();
+ if (entry.paths.empty() || !entry.paths.back().empty()) {
+ entry.paths.emplace_back();
}
}
void cmGccDepfileLexerHelper::newRuleOrDependency()
{
if (this->HelperState == State::Rule) {
- newRule();
- } else {
- newDependency();
+ this->newRule();
+ } else if (this->HelperState == State::Dependency) {
+ this->newDependency();
}
}
@@ -93,6 +102,8 @@ void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
}
dst = &dep->paths.back();
} break;
+ case State::Failed:
+ return;
}
dst->append(s);
}
diff --git a/Source/cmGccDepfileLexerHelper.h b/Source/cmGccDepfileLexerHelper.h
index 07ca61d18..91132f5d0 100644
--- a/Source/cmGccDepfileLexerHelper.h
+++ b/Source/cmGccDepfileLexerHelper.h
@@ -29,7 +29,8 @@ private:
enum class State
{
Rule,
- Dependency
+ Dependency,
+ Failed,
};
State HelperState = State::Rule;
};
diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx
index 9d70edec5..6436baac8 100644
--- a/Source/cmGccDepfileReader.cxx
+++ b/Source/cmGccDepfileReader.cxx
@@ -4,15 +4,43 @@
#include <type_traits>
#include <utility>
+#include <vector>
+
+#include <cm/optional>
#include "cmGccDepfileLexerHelper.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
-cmGccDepfileContent cmReadGccDepfile(const char* filePath)
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath,
+ const std::string& prefix)
{
- cmGccDepfileContent result;
cmGccDepfileLexerHelper helper;
- if (helper.readFile(filePath)) {
- result = std::move(helper).extractContent();
+ if (!helper.readFile(filePath)) {
+ return cm::nullopt;
+ }
+ auto deps = cm::make_optional(std::move(helper).extractContent());
+
+ for (auto& dep : *deps) {
+ for (auto& rule : dep.rules) {
+ if (!prefix.empty() && !cmSystemTools::FileIsFullPath(rule)) {
+ rule = cmStrCat(prefix, '/', rule);
+ }
+ if (cmSystemTools::FileIsFullPath(rule)) {
+ rule = cmSystemTools::CollapseFullPath(rule);
+ }
+ cmSystemTools::ConvertToLongPath(rule);
+ }
+ for (auto& path : dep.paths) {
+ if (!prefix.empty() && !cmSystemTools::FileIsFullPath(path)) {
+ path = cmStrCat(prefix, '/', path);
+ }
+ if (cmSystemTools::FileIsFullPath(path)) {
+ path = cmSystemTools::CollapseFullPath(path);
+ }
+ cmSystemTools::ConvertToLongPath(path);
+ }
}
- return result;
+
+ return deps;
}
diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h
index 395dd779a..c8a37485c 100644
--- a/Source/cmGccDepfileReader.h
+++ b/Source/cmGccDepfileReader.h
@@ -2,6 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <string>
+
+#include <cm/optional>
+
#include "cmGccDepfileReaderTypes.h"
-cmGccDepfileContent cmReadGccDepfile(const char* filePath);
+/*
+ * Read dependencies file and append prefix to all relative paths
+ */
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(
+ const char* filePath, const std::string& prefix = {});
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 276854742..43f384ab0 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -14,11 +14,11 @@
#endif
cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
- : OriginalLocale(getloc())
+ : OriginalLocale(this->getloc())
{
#ifndef CMAKE_BOOTSTRAP
if (encoding != codecvt::None) {
- imbue(std::locale(OriginalLocale, new codecvt(encoding)));
+ this->imbue(std::locale(this->OriginalLocale, new codecvt(encoding)));
}
#else
static_cast<void>(encoding);
@@ -28,7 +28,7 @@ cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,
bool quiet, Encoding encoding)
: cmGeneratedFileStreamBase(name)
- , Stream(TempName.c_str())
+ , Stream(this->TempName.c_str())
{
// Check if the file opened.
if (!*this && !quiet) {
@@ -37,7 +37,7 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,
}
#ifndef CMAKE_BOOTSTRAP
if (encoding != codecvt::None) {
- imbue(std::locale(getloc(), new codecvt(encoding)));
+ this->imbue(std::locale(this->getloc(), new codecvt(encoding)));
}
#else
static_cast<void>(encoding);
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index e223f1545..a1fce552f 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -28,7 +28,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
, Backtrace(std::move(backtrace))
, TransitivePropertiesOnly(false)
{
- Initialize();
+ this->Initialize();
}
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
@@ -42,7 +42,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
, Backtrace()
, TransitivePropertiesOnly(false)
{
- Initialize();
+ this->Initialize();
}
void cmGeneratorExpressionDAGChecker::Initialize()
@@ -52,7 +52,7 @@ void cmGeneratorExpressionDAGChecker::Initialize()
#define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) top->METHOD() ||
- if (CheckResult == DAG &&
+ if (this->CheckResult == DAG &&
(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(*)
#undef TEST_TRANSITIVE_PROPERTY_METHOD
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 53225cd24..93b44db82 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -89,7 +89,6 @@ private:
Result CheckGraph() const;
void Initialize();
-private:
const cmGeneratorExpressionDAGChecker* const Parent;
cmGeneratorTarget const* Target;
const std::string Property;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 9e5023d39..9fae15ae8 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -15,20 +15,22 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSourceFile.h"
-#include "cmSourceFileLocationKind.h"
#include "cmSystemTools.h"
cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
std::string input, std::string target,
std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr,
std::unique_ptr<cmCompiledGeneratorExpression> condition,
- bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070)
+ bool inputIsContent, std::string newLineCharacter, mode_t permissions,
+ cmPolicies::PolicyStatus policyStatusCMP0070)
: Input(std::move(input))
, Target(std::move(target))
, OutputFileExpr(std::move(outputFileExpr))
, Condition(std::move(condition))
, InputIsContent(inputIsContent)
+ , NewLineCharacter(std::move(newLineCharacter))
, PolicyStatusCMP0070(policyStatusCMP0070)
+ , Permissions(permissions)
{
}
@@ -38,7 +40,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(
std::map<std::string, std::string>& outputFiles, mode_t perm)
{
std::string rawCondition = this->Condition->GetInput();
- cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(Target);
+ cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(this->Target);
if (!rawCondition.empty()) {
std::string condResult =
this->Condition->Evaluate(lg, config, target, nullptr, nullptr, lang);
@@ -81,9 +83,33 @@ void cmGeneratorExpressionEvaluationFile::Generate(
this->Files.push_back(outputFileName);
outputFiles[outputFileName] = outputContent;
- cmGeneratedFileStream fout(outputFileName);
+ bool openWithBinaryFlag = false;
+ if (!this->NewLineCharacter.empty()) {
+ openWithBinaryFlag = true;
+ }
+ cmGeneratedFileStream fout;
+ fout.Open(outputFileName, false, openWithBinaryFlag);
+ if (!fout) {
+ lg->IssueMessage(MessageType::FATAL_ERROR,
+ "Could not open file for write in copy operation " +
+ outputFileName);
+ return;
+ }
fout.SetCopyIfDifferent(true);
- fout << outputContent;
+ std::istringstream iss(outputContent);
+ std::string line;
+ bool hasNewLine = false;
+ while (cmSystemTools::GetLineFromStream(iss, line, &hasNewLine)) {
+ fout << line;
+ if (!this->NewLineCharacter.empty()) {
+ fout << this->NewLineCharacter;
+ } else if (hasNewLine) {
+ // if new line character is not specified, the file will be opened in
+ // text mode. So, "\n" will be translated to the correct newline
+ // ending based on the platform.
+ fout << "\n";
+ }
+ }
if (fout.Close() && perm) {
cmSystemTools::SetPermissions(outputFileName.c_str(), perm);
}
@@ -94,16 +120,12 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
{
std::vector<std::string> enabledLanguages;
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
- cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(Target);
+ cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(this->Target);
gg->GetEnabledLanguages(enabledLanguages);
for (std::string const& le : enabledLanguages) {
std::string const name = this->GetOutputFileName(lg, target, config, le);
- cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(
- name, false, cmSourceFileLocationKind::Known);
- // Tell TraceDependencies that the file is not expected to exist
- // on disk yet. We generate it after that runs.
- sf->SetProperty("GENERATED", "1");
+ cmSourceFile* sf = lg->GetMakefile()->GetOrCreateGeneratedSource(name);
// Tell the build system generators that there is no build rule
// to generate the file.
@@ -116,14 +138,15 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
{
- mode_t perm = 0;
std::string inputContent;
if (this->InputIsContent) {
inputContent = this->Input;
} else {
const std::string inputFileName = this->GetInputFileName(lg);
lg->GetMakefile()->AddCMakeDependFile(inputFileName);
- cmSystemTools::GetPermissions(inputFileName.c_str(), perm);
+ if (!this->Permissions) {
+ cmSystemTools::GetPermissions(inputFileName.c_str(), this->Permissions);
+ }
cmsys::ifstream fin(inputFileName.c_str());
if (!fin) {
std::ostringstream e;
@@ -157,7 +180,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
for (std::string const& le : enabledLanguages) {
for (std::string const& li : allConfigs) {
- this->Generate(lg, li, le, inputExpression.get(), outputFiles, perm);
+ this->Generate(lg, li, le, inputExpression.get(), outputFiles,
+ this->Permissions);
if (cmSystemTools::GetFatalErrorOccured()) {
return;
}
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 2cd35ae94..0eb78acdc 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -24,7 +24,8 @@ public:
std::string input, std::string target,
std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr,
std::unique_ptr<cmCompiledGeneratorExpression> condition,
- bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070);
+ bool inputIsContent, std::string newLineCharacter, mode_t permissions,
+ cmPolicies::PolicyStatus policyStatusCMP0070);
void Generate(cmLocalGenerator* lg);
@@ -51,12 +52,13 @@ private:
std::string FixRelativePath(std::string const& filePath, PathRole role,
cmLocalGenerator* lg);
-private:
const std::string Input;
const std::string Target;
const std::unique_ptr<cmCompiledGeneratorExpression> OutputFileExpr;
const std::unique_ptr<cmCompiledGeneratorExpression> Condition;
std::vector<std::string> Files;
const bool InputIsContent;
+ const std::string NewLineCharacter;
cmPolicies::PolicyStatus PolicyStatusCMP0070;
+ mode_t Permissions;
};
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 4129a0c4f..fec309cb9 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -31,7 +31,7 @@ std::string GeneratorExpressionContent::ProcessArbitraryContent(
const auto pend = this->ParamChildren.end();
for (; pit != pend; ++pit) {
- for (auto& pExprEval : *pit) {
+ for (const auto& pExprEval : *pit) {
if (node->RequiresLiteralInput()) {
if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) {
reportError(context, this->GetOriginalExpression(),
@@ -63,7 +63,7 @@ std::string GeneratorExpressionContent::Evaluate(
{
std::string identifier;
{
- for (auto& pExprEval : this->IdentifierChildren) {
+ for (const auto& pExprEval : this->IdentifierChildren) {
identifier += pExprEval->Evaluate(context, dagChecker);
if (context->HadError) {
return std::string();
@@ -124,7 +124,7 @@ std::string GeneratorExpressionContent::EvaluateParameters(
return std::string();
}
std::string parameter;
- for (auto& pExprEval : *pit) {
+ for (const auto& pExprEval : *pit) {
parameter += pExprEval->Evaluate(context, dagChecker);
if (context->HadError) {
return std::string();
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 3e7737e6a..8f47c0b37 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -60,7 +60,7 @@ struct TextContent : public cmGeneratorExpressionEvaluator
void Extend(size_t length) { this->Length += length; }
- size_t GetLength() { return this->Length; }
+ size_t GetLength() const { return this->Length; }
private:
const char* Content;
@@ -108,7 +108,6 @@ private:
std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit)
const;
-private:
cmGeneratorExpressionEvaluatorVector IdentifierChildren;
std::vector<cmGeneratorExpressionEvaluatorVector> ParamChildren;
const char* StartContent;
diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx
index a7f090ac7..b8c38c005 100644
--- a/Source/cmGeneratorExpressionLexer.cxx
+++ b/Source/cmGeneratorExpressionLexer.cxx
@@ -35,14 +35,14 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize(
2);
upto = c + 2;
++c;
- SawBeginExpression = true;
+ this->SawBeginExpression = true;
}
break;
case '>':
InsertText(upto, c, result);
result.emplace_back(cmGeneratorExpressionToken::EndExpression, c, 1);
upto = c + 1;
- SawGeneratorExpression = SawBeginExpression;
+ this->SawGeneratorExpression = this->SawBeginExpression;
break;
case ':':
InsertText(upto, c, result);
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 4ca7405b5..e40316e1a 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -677,7 +677,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
}
static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
- for (auto& param : parameters) {
+ for (auto const& param : parameters) {
if (!compilerIdValidator.find(param)) {
reportError(context, content->GetOriginalExpression(),
@@ -805,7 +805,7 @@ struct PlatformIdNode : public cmGeneratorExpressionNode
return parameters.front().empty() ? "1" : "0";
}
- for (auto& param : parameters) {
+ for (auto const& param : parameters) {
if (param == platformId) {
return "1";
}
@@ -901,7 +901,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
return std::string();
}
context->HadContextSensitiveCondition = true;
- for (auto& param : parameters) {
+ for (auto const& param : parameters) {
if (context->Config.empty()) {
if (param.empty()) {
return "1";
@@ -927,7 +927,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
if (cmProp mapValue = context->CurrentTarget->GetProperty(mapProp)) {
cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs);
- for (auto& param : parameters) {
+ for (auto const& param : parameters) {
if (cm::contains(mappedConfigs, cmSystemTools::UpperCase(param))) {
return "1";
}
@@ -995,7 +995,7 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
return context->Language;
}
- for (auto& param : parameters) {
+ for (auto const& param : parameters) {
if (context->Language == param) {
return "1";
}
@@ -1101,7 +1101,7 @@ static const struct LinkLanguageNode : public cmGeneratorExpressionNode
return context->Language;
}
- for (auto& param : parameters) {
+ for (auto const& param : parameters) {
if (context->Language == param) {
return "1";
}
@@ -1129,7 +1129,7 @@ struct LinkerId
}
static cmsys::RegularExpression linkerIdValidator("^[A-Za-z0-9_]*$");
- for (auto& param : parameters) {
+ for (auto const& param : parameters) {
if (!linkerIdValidator.find(param)) {
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index c2c9ef723..794c1a1fa 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -22,7 +22,7 @@ cmGeneratorExpressionParser::cmGeneratorExpressionParser(
void cmGeneratorExpressionParser::Parse(
cmGeneratorExpressionEvaluatorVector& result)
{
- it = this->Tokens.begin();
+ this->it = this->Tokens.begin();
while (this->it != this->Tokens.end()) {
this->ParseContent(result);
diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h
index d49bf3e22..efaef3e5e 100644
--- a/Source/cmGeneratorExpressionParser.h
+++ b/Source/cmGeneratorExpressionParser.h
@@ -24,7 +24,6 @@ private:
void ParseContent(cmGeneratorExpressionEvaluatorVector&);
void ParseGeneratorExpression(cmGeneratorExpressionEvaluatorVector&);
-private:
std::vector<cmGeneratorExpressionToken>::const_iterator it;
const std::vector<cmGeneratorExpressionToken> Tokens;
unsigned int NestingLevel;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index c299dadf0..d7e9952a2 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -24,9 +24,7 @@
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
-#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
-#include "cmCustomCommandLines.h"
#include "cmFileTimes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
@@ -254,7 +252,7 @@ EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
{
EvaluatedTargetPropertyEntries out;
out.Entries.reserve(in.size());
- for (auto& entry : in) {
+ for (auto const& entry : in) {
out.Entries.emplace_back(EvaluateTargetPropertyEntry(
thisTarget, config, lang, dagChecker, *entry));
}
@@ -332,7 +330,7 @@ cmGeneratorTarget::~cmGeneratorTarget() = default;
const std::string& cmGeneratorTarget::GetSourcesProperty() const
{
std::vector<std::string> values;
- for (auto& se : this->SourceEntries) {
+ for (auto const& se : this->SourceEntries) {
values.push_back(se->GetInput());
}
static std::string value;
@@ -559,7 +557,7 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
// Frameworks created by multi config generators can have a special
// framework postfix.
- frameworkPostfix = GetFrameworkMultiConfigPostfix(config);
+ frameworkPostfix = this->GetFrameworkMultiConfigPostfix(config);
if (!frameworkPostfix.empty()) {
postfix = &frameworkPostfix;
}
@@ -578,7 +576,7 @@ std::string cmGeneratorTarget::GetFrameworkMultiConfigPostfix(
if (!this->IsImported() && postfix &&
(this->IsFrameworkOnApple() &&
- !GetGlobalGenerator()->IsMultiConfig())) {
+ !this->GetGlobalGenerator()->IsMultiConfig())) {
postfix = nullptr;
}
}
@@ -992,9 +990,8 @@ cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const
bool cmGeneratorTarget::GetLanguageStandardRequired(
std::string const& lang) const
{
- cmProp p =
- this->GetPropertyWithPairedLanguageSupport(lang, "_STANDARD_REQUIRED");
- return cmIsOn(p);
+ return cmIsOn(
+ this->GetPropertyWithPairedLanguageSupport(lang, "_STANDARD_REQUIRED"));
}
void cmGeneratorTarget::GetModuleDefinitionSources(
@@ -1539,10 +1536,14 @@ bool processSources(cmGeneratorTarget const* tgt,
for (std::string& src : entry.Values) {
cmSourceFile* sf = mf->GetOrCreateSource(src);
std::string e;
- std::string fullPath = sf->ResolveFullPath(&e);
+ std::string w;
+ std::string fullPath = sf->ResolveFullPath(&e, &w);
+ cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
+ if (!w.empty()) {
+ cm->IssueMessage(MessageType::AUTHOR_WARNING, w, tgt->GetBacktrace());
+ }
if (fullPath.empty()) {
if (!e.empty()) {
- cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace());
}
return contextDependent;
@@ -2002,17 +2003,16 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
// this target must be relinked.
bool have_rpath =
this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config);
- bool is_ninja =
- this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja";
+ bool is_ninja = this->LocalGenerator->GetGlobalGenerator()->IsNinja();
if (have_rpath && is_ninja) {
std::ostringstream w;
/* clang-format off */
w <<
- "The install of the " << this->GetName() << " target requires "
- "changing an RPATH from the build tree, but this is not supported "
- "with the Ninja generator unless on an ELF-based platform. The "
- "CMAKE_BUILD_WITH_INSTALL_RPATH variable may be set to avoid this "
+ "The install of the " << this->GetName() << " target requires changing "
+ "an RPATH from the build tree, but this is not supported with the Ninja "
+ "generator unless on an ELF-based or XCOFF-based platform. "
+ "The CMAKE_BUILD_WITH_INSTALL_RPATH variable may be set to avoid this "
"relinking step."
;
/* clang-format on */
@@ -2058,20 +2058,29 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
return true;
}
-#if defined(CMAKE_USE_ELF_PARSER)
- // Enable if the rpath flag uses a separator and the target uses ELF
- // binaries.
+#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER)
+ // Enable if the rpath flag uses a separator and the target uses
+ // binaries we know how to edit.
std::string ll = this->GetLinkerLanguage(config);
if (!ll.empty()) {
std::string sepVar =
cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP");
cmProp sep = this->Makefile->GetDefinition(sepVar);
if (cmNonempty(sep)) {
- // TODO: Add ELF check to ABI detection and get rid of
+ // TODO: Add binary format check to ABI detection and get rid of
// CMAKE_EXECUTABLE_FORMAT.
if (cmProp fmt =
this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) {
- return (*fmt == "ELF");
+# if defined(CMake_USE_ELF_PARSER)
+ if (*fmt == "ELF") {
+ return true;
+ }
+# endif
+# if defined(CMake_USE_XCOFF_PARSER)
+ if (*fmt == "XCOFF") {
+ return true;
+ }
+# endif
}
}
}
@@ -2500,9 +2509,9 @@ public:
}
}
- bool GetHadLinkLanguageSensitiveCondition()
+ bool GetHadLinkLanguageSensitiveCondition() const
{
- return HadLinkLanguageSensitiveCondition;
+ return this->HadLinkLanguageSensitiveCondition;
}
private:
@@ -2639,8 +2648,12 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
LinkClosure linkClosure;
linkClosure.LinkerLanguage = this->LinkerLanguage;
+ bool hasHardCodedLinkerLanguage = this->Target->GetProperty("HAS_CXX") ||
+ !this->Target->GetSafeProperty("LINKER_LANGUAGE").empty();
+
// Get languages built in this target.
- secondPass = this->ComputeLinkClosure(config, linkClosure, false);
+ secondPass = this->ComputeLinkClosure(config, linkClosure, false) &&
+ !hasHardCodedLinkerLanguage;
this->LinkerLanguage = linkClosure.LinkerLanguage;
if (!secondPass) {
lc = std::move(linkClosure);
@@ -2888,9 +2901,6 @@ private:
bool IsUtility(std::string const& dep);
void CheckCustomCommand(cmCustomCommand const& cc);
void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
- void FollowCommandDepends(cmCustomCommand const& cc,
- const std::string& config,
- std::set<std::string>& emitted);
};
cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target)
@@ -2986,7 +2996,8 @@ void cmTargetTraceDependencies::FollowName(std::string const& name)
auto i = this->NameMap.lower_bound(name);
if (i == this->NameMap.end() || i->first != name) {
// Check if we know how to generate this file.
- cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name);
+ cmSourcesWithOutput sources =
+ this->LocalGenerator->GetSourcesWithOutput(name);
// If we failed to find a target or source and we have a relative path, it
// might be a valid source if made relative to the current binary
// directory.
@@ -2996,7 +3007,7 @@ void cmTargetTraceDependencies::FollowName(std::string const& name)
cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', name);
fullname = cmSystemTools::CollapseFullPath(
fullname, this->Makefile->GetHomeOutputDirectory());
- sources = this->Makefile->GetSourcesWithOutput(fullname);
+ sources = this->LocalGenerator->GetSourcesWithOutput(fullname);
}
i = this->NameMap.emplace_hint(i, name, sources);
}
@@ -3065,7 +3076,7 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
} else {
// The original name of the dependency was not a full path. It
// must name a target, so add the target-level dependency.
- this->GeneratorTarget->Target->AddUtility(util, false);
+ this->GeneratorTarget->Target->AddUtility(util, true);
return true;
}
}
@@ -3076,71 +3087,28 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
{
- // Transform command names that reference targets built in this
- // project to corresponding target-level dependencies.
- cmGeneratorExpression ge(cc.GetBacktrace());
-
- // Add target-level dependencies referenced by generator expressions.
- std::set<cmGeneratorTarget*> targets;
-
- for (cmCustomCommandLine const& cCmdLine : cc.GetCommandLines()) {
- std::string const& command = cCmdLine.front();
- // Check for a target with this name.
- if (cmGeneratorTarget* t =
- this->LocalGenerator->FindGeneratorTargetToUse(command)) {
- if (t->GetType() == cmStateEnums::EXECUTABLE) {
- // The command refers to an executable target built in
- // this project. Add the target-level dependency to make
- // sure the executable is up to date before this custom
- // command possibly runs.
- this->GeneratorTarget->Target->AddUtility(command, true);
+ // Collect dependencies referenced by all configurations.
+ std::set<std::string> depends;
+ for (std::string const& config :
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) {
+ for (cmCustomCommandGenerator const& ccg :
+ this->LocalGenerator->MakeCustomCommandGenerators(cc, config)) {
+ // Collect target-level dependencies referenced in command lines.
+ for (auto const& util : ccg.GetUtilities()) {
+ this->GeneratorTarget->Target->AddUtility(util);
}
- }
- // Check for target references in generator expressions.
- std::vector<std::string> const& configs =
- this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
- for (std::string const& c : configs) {
- for (std::string const& cl : cCmdLine) {
- const std::unique_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(cl);
- cge->SetQuiet(true);
- cge->Evaluate(this->GeneratorTarget->GetLocalGenerator(), c);
- std::set<cmGeneratorTarget*> geTargets = cge->GetTargets();
- targets.insert(geTargets.begin(), geTargets.end());
- }
+ // Collect file-level dependencies referenced in DEPENDS.
+ depends.insert(ccg.GetDepends().begin(), ccg.GetDepends().end());
}
}
- for (cmGeneratorTarget* target : targets) {
- this->GeneratorTarget->Target->AddUtility(target->GetName(), true);
- }
-
- // Queue the custom command dependencies.
- std::set<std::string> emitted;
- std::vector<std::string> const& configs =
- this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
- for (std::string const& conf : configs) {
- this->FollowCommandDepends(cc, conf, emitted);
- }
-}
-
-void cmTargetTraceDependencies::FollowCommandDepends(
- cmCustomCommand const& cc, const std::string& config,
- std::set<std::string>& emitted)
-{
- cmCustomCommandGenerator ccg(cc, config,
- this->GeneratorTarget->LocalGenerator);
-
- const std::vector<std::string>& depends = ccg.GetDepends();
-
+ // Queue file-level dependencies.
for (std::string const& dep : depends) {
- if (emitted.insert(dep).second) {
- if (!this->IsUtility(dep)) {
- // The dependency does not name a target and may be a file we
- // know how to generate. Queue it.
- this->FollowName(dep);
- }
+ if (!this->IsUtility(dep)) {
+ // The dependency does not name a target and may be a file we
+ // know how to generate. Queue it.
+ this->FollowName(dep);
}
}
}
@@ -3200,6 +3168,30 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
}
}
+void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags,
+ cmSourceFile const& sf) const
+{
+ cmProp lang = sf.GetProperty("LANGUAGE");
+ if (!lang) {
+ return;
+ }
+
+ switch (this->GetPolicyStatusCMP0119()) {
+ case cmPolicies::WARN:
+ case cmPolicies::OLD:
+ // The OLD behavior is to not add explicit language flags.
+ return;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ // The NEW behavior is to add explicit language flags.
+ break;
+ }
+
+ this->LocalGenerator->AppendFeatureOptions(flags, *lang,
+ "EXPLICIT_LANGUAGE");
+}
+
void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
{
const std::string& property = this->GetSafeProperty("CUDA_ARCHITECTURES");
@@ -3298,7 +3290,7 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
flags += " --cuda-gpu-arch=sm_" + architecture.name;
if (!architecture.real) {
- Makefile->IssueMessage(
+ this->Makefile->IssueMessage(
MessageType::WARNING,
"Clang doesn't support disabling CUDA real code generation.");
}
@@ -4071,7 +4063,7 @@ std::string cmGeneratorTarget::GetPchFileObject(const std::string& config,
}
std::string& filename = inserted.first->second;
- auto pchSf = this->Makefile->GetOrCreateSource(
+ auto* pchSf = this->Makefile->GetOrCreateSource(
pchSource, false, cmSourceFileLocationKind::Known);
filename = cmStrCat(this->ObjectDirectory, this->GetObjectName(pchSf));
@@ -4988,7 +4980,7 @@ void cmGeneratorTarget::GetFullNameInternal(
// the base, because the suffix ends up being used in Xcode's
// EXECUTABLE_SUFFIX attribute.
if (this->IsFrameworkOnApple() &&
- GetGlobalGenerator()->GetName() == "Xcode") {
+ this->GetGlobalGenerator()->GetName() == "Xcode") {
targetSuffix = &configPostfix;
} else {
outBase += configPostfix;
@@ -6511,15 +6503,14 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
if (cmProp config_outdir = this->GetProperty(configProp)) {
// Use the user-specified per-configuration output directory.
out = cmGeneratorExpression::Evaluate(*config_outdir, this->LocalGenerator,
- config);
+ config, this);
// Skip per-configuration subdirectory.
conf.clear();
} else if (cmProp outdir = this->GetProperty(propertyName)) {
// Use the user-specified output directory.
- out =
- cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator, config);
-
+ out = cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator,
+ config, this);
// Skip per-configuration subdirectory if the value contained a
// generator expression.
if (out != *outdir) {
@@ -7059,7 +7050,7 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
return &impl;
}
-bool cmGeneratorTarget::GetConfigCommonSourceFiles(
+bool cmGeneratorTarget::GetConfigCommonSourceFilesForXcode(
std::vector<cmSourceFile*>& files) const
{
std::vector<std::string> const& configs =
@@ -7380,7 +7371,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
std::string name = this->CheckCMP0004(lib);
if (this->GetPolicyStatusCMP0108() == cmPolicies::NEW) {
// resolve alias name
- auto target = this->Makefile->FindTargetToUse(name);
+ auto* target = this->Makefile->FindTargetToUse(name);
if (target) {
name = target->GetName();
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 2517b7205..8fe70abfc 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -430,8 +430,9 @@ public:
/** Get source files common to all configurations and diagnose cases
with per-config sources. Excludes sources added by a TARGET_OBJECTS
- generator expression. */
- bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
+ generator expression. Do not use outside the Xcode generator. */
+ bool GetConfigCommonSourceFilesForXcode(
+ std::vector<cmSourceFile*>& files) const;
bool HaveBuildTreeRPATH(const std::string& config) const;
@@ -447,6 +448,9 @@ public:
void GetAppleArchs(const std::string& config,
std::vector<std::string>& archVec) const;
+ void AddExplicitLanguageFlags(std::string& flags,
+ cmSourceFile const& sf) const;
+
void AddCUDAArchitectureFlags(std::string& flags) const;
void AddCUDAToolkitFlags(std::string& flags) const;
@@ -581,7 +585,8 @@ public:
std::string PdbDir;
bool empty() const
{
- return OutDir.empty() && ImpDir.empty() && PdbDir.empty();
+ return this->OutDir.empty() && this->ImpDir.empty() &&
+ this->PdbDir.empty();
}
};
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index c2098c0f2..7fbd479ac 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -50,6 +50,10 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
return false;
}
++i;
+ if (i == args.end()) {
+ status.SetError("called with incorrect number of arguments");
+ return false;
+ }
}
// OK, now we have the directory to process, we just get the requested
@@ -67,27 +71,30 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
return true;
}
+ if (i->empty()) {
+ status.SetError("given empty string for the property name to get");
+ return false;
+ }
+
const char* prop = nullptr;
- if (!i->empty()) {
- if (*i == "DEFINITIONS") {
- switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0059)) {
- case cmPolicies::WARN:
- status.GetMakefile().IssueMessage(
- MessageType::AUTHOR_WARNING,
- cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
- CM_FALLTHROUGH;
- case cmPolicies::OLD:
- StoreResult(status.GetMakefile(), variable,
- status.GetMakefile().GetDefineFlagsCMP0059());
- return true;
- case cmPolicies::NEW:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- break;
- }
+ if (*i == "DEFINITIONS") {
+ switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0059)) {
+ case cmPolicies::WARN:
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ StoreResult(status.GetMakefile(), variable,
+ status.GetMakefile().GetDefineFlagsCMP0059());
+ return true;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ break;
}
- prop = cmToCStr(dir->GetProperty(*i));
}
+ prop = cmToCStr(dir->GetProperty(*i));
StoreResult(status.GetMakefile(), variable, prop);
return true;
}
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 3a5b39da6..cb657f9ee 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -172,7 +172,7 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
std::vector<cmMakefile*> source_file_directory_makefiles;
bool file_scopes_handled =
- SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
status, source_file_directory_option_enabled,
source_file_target_option_enabled, source_file_directories,
source_file_target_directories, source_file_directory_makefiles);
@@ -280,8 +280,9 @@ bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
// Get the property.
cmake* cm = status.GetMakefile().GetCMakeInstance();
- cmProp p = cm->GetState()->GetGlobalProperty(propertyName);
- return StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(p));
+ return StoreResult(
+ infoType, status.GetMakefile(), variable,
+ cmToCStr(cm->GetState()->GetGlobalProperty(propertyName)));
}
bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
@@ -327,8 +328,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
}
// Get the property.
- cmProp p = mf->GetProperty(propertyName);
- return StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(p));
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ cmToCStr(mf->GetProperty(propertyName)));
}
bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
@@ -358,15 +359,14 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
}
return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
}
- cmProp prop_cstr = nullptr;
cmListFileBacktrace bt = status.GetMakefile().GetBacktrace();
cmMessenger* messenger = status.GetMakefile().GetMessenger();
- prop_cstr = target->GetComputedProperty(propertyName, messenger, bt);
- if (!prop_cstr) {
- prop_cstr = target->GetProperty(propertyName);
+ cmProp prop = target->GetComputedProperty(propertyName, messenger, bt);
+ if (!prop) {
+ prop = target->GetProperty(propertyName);
}
return StoreResult(infoType, status.GetMakefile(), variable,
- prop_cstr ? prop_cstr->c_str() : nullptr);
+ cmToCStr(prop));
}
status.SetError(cmStrCat("could not find TARGET ", name,
". Perhaps it has not yet been created."));
@@ -391,7 +391,7 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
if (cmSourceFile* sf =
directory_makefile.GetOrCreateSource(source_file_absolute_path)) {
return StoreResult(infoType, status.GetMakefile(), variable,
- sf->GetPropertyForUser(propertyName));
+ cmToCStr(sf->GetPropertyForUser(propertyName)));
}
status.SetError(
cmStrCat("given SOURCE name that could not be found or created: ",
diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx
index 5395bc8ef..5301b6618 100644
--- a/Source/cmGetSourceFilePropertyCommand.cxx
+++ b/Source/cmGetSourceFilePropertyCommand.cxx
@@ -4,6 +4,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
@@ -34,7 +35,7 @@ bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
std::vector<cmMakefile*> source_file_directory_makefiles;
bool file_scopes_handled =
- SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
status, source_file_directory_option_enabled,
source_file_target_option_enabled, source_file_directories,
source_file_target_directories, source_file_directory_makefiles);
@@ -57,14 +58,14 @@ bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
}
if (sf) {
- const char* prop = nullptr;
+ cmProp prop = nullptr;
if (!args[property_arg_index].empty()) {
prop = sf->GetPropertyForUser(args[property_arg_index]);
}
if (prop) {
// Set the value on the original Makefile scope, not the scope of the
// requested directory.
- status.GetMakefile().AddDefinition(var, prop);
+ status.GetMakefile().AddDefinition(var, *prop);
return true;
}
}
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index a8f8f573d..ed5bff5ff 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -62,7 +62,7 @@ void cmGhsMultiTargetGenerator::Generate()
// Get the name of the executable to generate.
this->TargetNameReal =
this->GeneratorTarget->GetExecutableNames(this->ConfigName).Real;
- if (cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) {
+ if (this->cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) {
this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION;
} else {
this->TagType = GhsMultiGpj::PROGRAM;
@@ -356,7 +356,7 @@ void cmGhsMultiTargetGenerator::WriteBuildEventsHelper(
} else {
fout << fname << "\n :outputName=\"" << fname << ".rule\"\n";
}
- for (auto& byp : ccg.GetByproducts()) {
+ for (const auto& byp : ccg.GetByproducts()) {
fout << " :extraOutputFile=\"" << byp << "\"\n";
}
}
@@ -528,7 +528,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
}
}
- for (auto& n : groupNames) {
+ for (const auto& n : groupNames) {
groupFilesList[i] = n;
i += 1;
}
@@ -631,7 +631,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
}
} else {
std::vector<cmSourceFile const*> customCommands;
- if (ComputeCustomCommandOrder(customCommands)) {
+ if (this->ComputeCustomCommandOrder(customCommands)) {
std::string message = "The custom commands for target [" +
this->GeneratorTarget->GetName() + "] had a cycle.\n";
cmSystemTools::Error(message);
@@ -691,14 +691,14 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandLine(
* the outputs is manually deleted.
*/
bool specifyExtra = true;
- for (auto& out : ccg.GetOutputs()) {
+ for (const auto& out : ccg.GetOutputs()) {
fout << fname << '\n';
fout << " :outputName=\"" << out << "\"\n";
if (specifyExtra) {
- for (auto& byp : ccg.GetByproducts()) {
+ for (const auto& byp : ccg.GetByproducts()) {
fout << " :extraOutputFile=\"" << byp << "\"\n";
}
- for (auto& dep : ccg.GetDepends()) {
+ for (const auto& dep : ccg.GetDepends()) {
fout << " :depends=\"" << dep << "\"\n";
}
specifyExtra = false;
@@ -721,18 +721,15 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()
{
- cmProp p = this->GeneratorTarget->GetProperty("ghs_integrity_app");
- if (p) {
+ if (cmProp p = this->GeneratorTarget->GetProperty("ghs_integrity_app")) {
return cmIsOn(*p);
}
std::vector<cmSourceFile*> sources;
this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName);
- for (const cmSourceFile* sf : sources) {
- if ("int" == sf->GetExtension()) {
- return true;
- }
- }
- return false;
+ return std::any_of(sources.begin(), sources.end(),
+ [](cmSourceFile const* sf) -> bool {
+ return "int" == sf->GetExtension();
+ });
}
bool cmGhsMultiTargetGenerator::ComputeCustomCommandOrder(
@@ -746,7 +743,7 @@ bool cmGhsMultiTargetGenerator::ComputeCustomCommandOrder(
this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
for (cmSourceFile const* si : customCommands) {
- bool r = VisitCustomCommand(temp, perm, order, si);
+ bool r = this->VisitCustomCommand(temp, perm, order, si);
if (r) {
return r;
}
@@ -762,10 +759,10 @@ bool cmGhsMultiTargetGenerator::VisitCustomCommand(
if (perm.find(si) == perm.end()) {
/* set temporary mark; check if revisit*/
if (temp.insert(si).second) {
- for (auto& di : si->GetCustomCommand()->GetDepends()) {
- cmSourceFile const* sf = this->GeneratorTarget->GetLocalGenerator()
- ->GetMakefile()
- ->GetSourceFileWithOutput(di);
+ for (const auto& di : si->GetCustomCommand()->GetDepends()) {
+ cmSourceFile const* sf =
+ this->GeneratorTarget->GetLocalGenerator()->GetSourceFileWithOutput(
+ di);
/* if sf exists then visit */
if (sf && this->VisitCustomCommand(temp, perm, order, sf)) {
return true;
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 06943e7ff..996fcff1d 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -26,6 +26,15 @@ cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator(cmake* cm)
this->DefineWindowsNULL = true;
this->PassMakeflags = true;
this->UnixCD = false;
+
+ /*
+ * 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:
+ * ** Fatal CMakeFiles\main.dir\depend.make 1224: Rule line too long **
+ * we disable long line dependencies rule generation for Borland make
+ */
+ this->ToolSupportsLongLineDependencies = false;
}
void cmGlobalBorlandMakefileGenerator::EnableLanguage(
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index fc40d63b3..ab76260f9 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1229,7 +1229,7 @@ void cmGlobalGenerator::Configure()
this->CMakeInstance->GetHomeOutputDirectory());
auto dirMfu = cm::make_unique<cmMakefile>(this, snapshot);
- auto dirMf = dirMfu.get();
+ auto* dirMf = dirMfu.get();
this->Makefiles.push_back(std::move(dirMfu));
dirMf->SetRecursionDepth(this->RecursionDepth);
this->IndexMakefile(dirMf);
@@ -1627,8 +1627,8 @@ void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
}
auto entry = insertion.first;
- auto& deps = this->GetTargetDirectDepends(gt);
- for (auto& d : deps) {
+ const auto& deps = this->GetTargetDirectDepends(gt);
+ for (const auto& d : deps) {
this->ComputeTargetOrder(d, index);
}
@@ -1811,6 +1811,7 @@ void cmGlobalGenerator::ClearGeneratorMembers()
this->AliasTargets.clear();
this->ExportSets.clear();
+ this->InstallComponents.clear();
this->TargetDependencies.clear();
this->TargetSearchIndex.clear();
this->GeneratorTargetSearchIndex.clear();
@@ -1821,6 +1822,7 @@ void cmGlobalGenerator::ClearGeneratorMembers()
this->RuleHashes.clear();
this->DirectoryContentMap.clear();
this->BinaryDirectories.clear();
+ this->GeneratedFiles.clear();
}
void cmGlobalGenerator::ComputeTargetObjectDirectory(
@@ -2146,6 +2148,16 @@ void cmGlobalGenerator::AddInstallComponent(const std::string& component)
}
}
+void cmGlobalGenerator::MarkAsGeneratedFile(const std::string& filepath)
+{
+ this->GeneratedFiles.insert(filepath);
+}
+
+bool cmGlobalGenerator::IsGeneratedFile(const std::string& filepath)
+{
+ return this->GeneratedFiles.find(filepath) != this->GeneratedFiles.end();
+}
+
void cmGlobalGenerator::EnableInstallTarget()
{
this->InstallTargetEnabled = true;
@@ -2608,7 +2620,7 @@ void cmGlobalGenerator::AddGlobalTarget_Test(
}
void cmGlobalGenerator::AddGlobalTarget_EditCache(
- std::vector<GlobalTargetInfo>& targets)
+ std::vector<GlobalTargetInfo>& targets) const
{
const char* editCacheTargetName = this->GetEditCacheTargetName();
if (!editCacheTargetName) {
@@ -2642,7 +2654,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache(
}
void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
- std::vector<GlobalTargetInfo>& targets)
+ std::vector<GlobalTargetInfo>& targets) const
{
const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
if (!rebuildCacheTargetName) {
@@ -2765,7 +2777,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
}
}
-std::string cmGlobalGenerator::GetPredefinedTargetsFolder()
+std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const
{
cmProp prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
"PREDEFINED_TARGETS_FOLDER");
@@ -2917,7 +2929,7 @@ void cmGlobalGenerator::GetTargetSets(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
// loop over all local generators
- for (auto generator : generators) {
+ for (auto* generator : generators) {
// check to make sure generator is not excluded
if (this->IsExcluded(root, generator)) {
continue;
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index c106258ad..590de268c 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -11,9 +11,11 @@
#include <set>
#include <string>
#include <unordered_map>
+#include <unordered_set>
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cmext/algorithm>
#include "cm_codecvt.hxx"
@@ -26,6 +28,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
+#include "cmTransformDepfile.h"
#if !defined(CMAKE_BOOTSTRAP)
# include <cm3p/json/value.h>
@@ -66,17 +69,17 @@ struct GeneratedMakeCommand
void Add(T&&... args)
{
// iterate the args and append each one
- AppendStrs(PrimaryCommand, std::forward<T>(args)...);
+ AppendStrs(this->PrimaryCommand, std::forward<T>(args)...);
}
// Add each value in the iterators as a separate element to the vector
void Add(std::vector<std::string>::const_iterator start,
std::vector<std::string>::const_iterator end)
{
- cm::append(PrimaryCommand, start, end);
+ cm::append(this->PrimaryCommand, start, end);
}
- std::string Printable() const { return cmJoin(PrimaryCommand, " "); }
+ std::string Printable() const { return cmJoin(this->PrimaryCommand, " "); }
std::vector<std::string> PrimaryCommand;
bool RequiresOutputForward = false;
@@ -288,6 +291,11 @@ public:
void AddInstallComponent(const std::string& component);
+ /** Mark the (absolute path to a) file as generated. */
+ void MarkAsGeneratedFile(const std::string& filepath);
+ /** Determine if the absolute filepath belongs to a generated file. */
+ bool IsGeneratedFile(const std::string& filepath);
+
const std::set<std::string>* GetInstallComponents() const
{
return &this->InstallComponents;
@@ -430,6 +438,8 @@ public:
virtual bool IsVisualStudio() const { return false; }
+ virtual bool IsNinja() const { return false; }
+
/** Return true if we know the exact location of object files.
If false, store the reason in the given string.
This is meaningful only after EnableLanguage has been called. */
@@ -452,6 +462,10 @@ public:
virtual bool ShouldStripResourcePath(cmMakefile*) const;
virtual bool SupportsCustomCommandDepfile() const { return false; }
+ virtual cm::optional<cmDepfileFormat> DepfileFormat() const
+ {
+ return cm::nullopt;
+ }
std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
@@ -489,7 +503,7 @@ public:
cmSourceFile* sf) const;
#if !defined(CMAKE_BOOTSTRAP)
- cmFileLockPool& GetFileLockPool() { return FileLockPool; }
+ cmFileLockPool& GetFileLockPool() { return this->FileLockPool; }
#endif
bool GetConfigureDoneCMP0026() const
@@ -568,8 +582,9 @@ protected:
void AddGlobalTarget_Package(std::vector<GlobalTargetInfo>& targets);
void AddGlobalTarget_PackageSource(std::vector<GlobalTargetInfo>& targets);
void AddGlobalTarget_Test(std::vector<GlobalTargetInfo>& targets);
- void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets);
- void AddGlobalTarget_RebuildCache(std::vector<GlobalTargetInfo>& targets);
+ void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets) const;
+ void AddGlobalTarget_RebuildCache(
+ std::vector<GlobalTargetInfo>& targets) const;
void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
cmTarget CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
@@ -595,7 +610,7 @@ protected:
cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;
- std::string GetPredefinedTargetsFolder();
+ std::string GetPredefinedTargetsFolder() const;
enum class FindMakeProgramStage
{
@@ -726,6 +741,8 @@ private:
std::map<std::string, std::string> RealPaths;
+ std::unordered_set<std::string> GeneratedFiles;
+
#if !defined(CMAKE_BOOTSTRAP)
// Pool of file locks
cmFileLockPool FileLockPool;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index c08c9cf5b..172cf3fc0 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -366,7 +366,7 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout,
target->GetType() == cmStateEnums::MODULE_LIBRARY ||
target->GetType() == cmStateEnums::SHARED_LIBRARY ||
(target->GetType() == cmStateEnums::GLOBAL_TARGET &&
- target->GetName() != GetInstallTargetName())) {
+ target->GetName() != this->GetInstallTargetName())) {
continue;
}
fout << "CMakeFiles/" << target->GetName() + ".tgt" + FILE_EXTENSION
@@ -415,7 +415,7 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
target->GetType() == cmStateEnums::MODULE_LIBRARY ||
target->GetType() == cmStateEnums::SHARED_LIBRARY ||
(target->GetType() == cmStateEnums::GLOBAL_TARGET &&
- target->GetName() != GetInstallTargetName())) {
+ target->GetName() != this->GetInstallTargetName())) {
continue;
}
@@ -427,13 +427,13 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
this->WriteFileHeader(fbld);
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld);
std::vector<cmGeneratorTarget const*> build;
- if (ComputeTargetBuildOrder(target, build)) {
+ if (this->ComputeTargetBuildOrder(target, build)) {
cmSystemTools::Error(
cmStrCat("The inter-target dependency graph for target [",
target->GetName(), "] had a cycle.\n"));
} else {
for (auto& tgt : build) {
- WriteProjectLine(fbld, tgt, root, rootBinaryDir);
+ this->WriteProjectLine(fbld, tgt, root, rootBinaryDir);
}
}
fbld.Close();
@@ -471,12 +471,12 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget(
if (!t->IsInBuildSystem()) {
continue;
}
- if (!IsExcluded(t->GetLocalGenerator(), t)) {
+ if (!this->IsExcluded(t->GetLocalGenerator(), t)) {
defaultTargets.push_back(t);
}
}
std::vector<cmGeneratorTarget const*> build;
- if (ComputeTargetBuildOrder(defaultTargets, build)) {
+ if (this->ComputeTargetBuildOrder(defaultTargets, build)) {
std::string message = "The inter-target dependency graph for project [" +
root->GetProjectName() + "] had a cycle.\n";
cmSystemTools::Error(message);
@@ -694,7 +694,7 @@ bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
cmGeneratorTarget const* tgt, std::vector<cmGeneratorTarget const*>& build)
{
std::vector<cmGeneratorTarget const*> t{ tgt };
- return ComputeTargetBuildOrder(t, build);
+ return this->ComputeTargetBuildOrder(t, build);
}
bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
@@ -704,8 +704,8 @@ bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
std::set<cmGeneratorTarget const*> temp;
std::set<cmGeneratorTarget const*> perm;
- for (auto ti : tgt) {
- bool r = VisitTarget(temp, perm, build, ti);
+ for (const auto* const ti : tgt) {
+ bool r = this->VisitTarget(temp, perm, build, ti);
if (r) {
return r;
}
@@ -726,7 +726,7 @@ bool cmGlobalGhsMultiGenerator::VisitTarget(
* in the same order */
OrderedTargetDependSet sortedTargets(this->GetTargetDirectDepends(ti),
"");
- for (auto& di : sortedTargets) {
+ for (auto const& di : sortedTargets) {
if (this->VisitTarget(temp, perm, order, di)) {
return true;
}
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index c4bec2387..36f583f01 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -21,6 +21,8 @@ cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
this->PassMakeflags = true;
this->UnixCD = false;
this->MakeSilentFlag = "/nologo";
+ // nmake breaks on '!' in long-line dependencies
+ this->ToolSupportsLongLineDependencies = false;
}
void cmGlobalNMakeMakefileGenerator::EnableLanguage(
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index e10c76e38..c502fb85a 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -34,6 +34,7 @@
#include "cmOutputConverter.h"
#include "cmProperty.h"
#include "cmRange.h"
+#include "cmScanDepFormat.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
@@ -55,6 +56,52 @@ std::string const cmGlobalNinjaGenerator::SHELL_NOOP = "cd .";
std::string const cmGlobalNinjaGenerator::SHELL_NOOP = ":";
#endif
+bool operator==(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return lhs.Target == rhs.Target && lhs.Config == rhs.Config &&
+ lhs.GenexOutput == rhs.GenexOutput;
+}
+
+bool operator!=(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return !(lhs == rhs);
+}
+
+bool operator<(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return lhs.Target < rhs.Target ||
+ (lhs.Target == rhs.Target &&
+ (lhs.Config < rhs.Config ||
+ (lhs.Config == rhs.Config && lhs.GenexOutput < rhs.GenexOutput)));
+}
+
+bool operator>(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return rhs < lhs;
+}
+
+bool operator<=(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return !(lhs > rhs);
+}
+
+bool operator>=(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return rhs <= lhs;
+}
+
void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count)
{
for (int i = 0; i < count; ++i) {
@@ -135,7 +182,7 @@ std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
else
std::replace(result.begin(), result.end(), '/', '\\');
#endif
- result = EncodeLiteral(result);
+ result = this->EncodeLiteral(result);
cmSystemTools::ReplaceString(result, " ", "$ ");
cmSystemTools::ReplaceString(result, ":", "$:");
return result;
@@ -167,7 +214,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
{
// Write explicit outputs
for (std::string const& output : build.Outputs) {
- buildStr += cmStrCat(' ', EncodePath(output));
+ buildStr += cmStrCat(' ', this->EncodePath(output));
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(output);
}
@@ -176,7 +223,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
if (!build.ImplicitOuts.empty()) {
buildStr += " |";
for (std::string const& implicitOut : build.ImplicitOuts) {
- buildStr += cmStrCat(' ', EncodePath(implicitOut));
+ buildStr += cmStrCat(' ', this->EncodePath(implicitOut));
}
}
buildStr += ':';
@@ -191,14 +238,14 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
// Write explicit dependencies.
for (std::string const& explicitDep : build.ExplicitDeps) {
- arguments += cmStrCat(' ', EncodePath(explicitDep));
+ arguments += cmStrCat(' ', this->EncodePath(explicitDep));
}
// Write implicit dependencies.
if (!build.ImplicitDeps.empty()) {
arguments += " |";
for (std::string const& implicitDep : build.ImplicitDeps) {
- arguments += cmStrCat(' ', EncodePath(implicitDep));
+ arguments += cmStrCat(' ', this->EncodePath(implicitDep));
}
}
@@ -206,7 +253,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
if (!build.OrderOnlyDeps.empty()) {
arguments += " ||";
for (std::string const& orderOnlyDep : build.OrderOnlyDeps) {
- arguments += cmStrCat(' ', EncodePath(orderOnlyDep));
+ arguments += cmStrCat(' ', this->EncodePath(orderOnlyDep));
}
}
@@ -284,11 +331,11 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
#endif
vars["COMMAND"] = std::move(cmd);
}
- vars["DESC"] = EncodeLiteral(description);
+ vars["DESC"] = this->EncodeLiteral(description);
if (restat) {
vars["restat"] = "1";
}
- if (uses_terminal && SupportsConsolePool()) {
+ if (uses_terminal && this->SupportsConsolePool()) {
vars["pool"] = "console";
} else if (!job_pool.empty()) {
vars["pool"] = job_pool;
@@ -315,7 +362,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
void cmGlobalNinjaGenerator::AddMacOSXContentRule()
{
cmNinjaRule rule("COPY_OSX_CONTENT");
- rule.Command = cmStrCat(CMakeCmd(), " -E copy $in $out");
+ rule.Command = cmStrCat(this->CMakeCmd(), " -E copy $in $out");
rule.Description = "Copying OS X Content $out";
rule.Comment = "Rule for copying OS X bundle content file.";
this->AddRule(rule);
@@ -508,6 +555,7 @@ void cmGlobalNinjaGenerator::Generate()
this->TargetAll = this->NinjaOutputPath("all");
this->CMakeCacheFile = this->NinjaOutputPath("CMakeCache.txt");
this->DisableCleandead = false;
+ this->DiagnosedCxxModuleSupport = false;
this->PolicyCMP0058 =
this->LocalGenerators[0]->GetMakefile()->GetPolicyStatus(
@@ -709,6 +757,37 @@ bool cmGlobalNinjaGenerator::CheckLanguages(
return true;
}
+bool cmGlobalNinjaGenerator::CheckCxxModuleSupport()
+{
+ bool const diagnose = !this->DiagnosedCxxModuleSupport &&
+ !this->CMakeInstance->GetIsInTryCompile();
+ if (diagnose) {
+ this->DiagnosedCxxModuleSupport = true;
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ "C++20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP "
+ "is experimental. It is meant only for compiler developers to try.");
+ }
+ if (this->NinjaSupportsDyndeps) {
+ return true;
+ }
+ if (diagnose) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "The Ninja generator does not support C++20 modules "
+ "using Ninja version \n"
+ " " << this->NinjaVersion << "\n"
+ "due to lack of required features. "
+ "Ninja " << RequiredNinjaVersionForDyndeps() << " or higher is required."
+ ;
+ /* clang-format on */
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ }
+ return false;
+}
+
bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
{
if (this->NinjaSupportsDyndeps) {
@@ -720,7 +799,8 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
e <<
"The Ninja generator does not support Fortran using Ninja version\n"
" " << this->NinjaVersion << "\n"
- "due to lack of required features. Ninja 1.10 or higher is required."
+ "due to lack of required features. "
+ "Ninja " << RequiredNinjaVersionForDyndeps() << " or higher is required."
;
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
@@ -739,7 +819,9 @@ bool cmGlobalNinjaGenerator::CheckISPC(cmMakefile* mf) const
e <<
"The Ninja generator does not support ISPC using Ninja version\n"
" " << this->NinjaVersion << "\n"
- "due to lack of required features. Ninja 1.10 or higher is required."
+ "due to lack of required features. "
+ "Ninja " << RequiredNinjaVersionForMultipleOutputs() <<
+ " or higher is required."
;
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
@@ -986,8 +1068,8 @@ static void EnsureTrailingSlash(std::string& path)
std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
const std::string& path) const
{
- auto const f = ConvertToNinjaPathCache.find(path);
- if (f != ConvertToNinjaPathCache.end()) {
+ auto const f = this->ConvertToNinjaPathCache.find(path);
+ if (f != this->ConvertToNinjaPathCache.end()) {
return f->second;
}
@@ -999,7 +1081,7 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
#ifdef _WIN32
std::replace(convPath.begin(), convPath.end(), '/', '\\');
#endif
- return ConvertToNinjaPathCache.emplace(path, std::move(convPath))
+ return this->ConvertToNinjaPathCache.emplace(path, std::move(convPath))
.first->second;
}
@@ -1057,7 +1139,7 @@ void cmGlobalNinjaGenerator::CloseCompileCommandsStream()
}
}
-void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
+void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os) const
{
os << "# CMAKE generated file: DO NOT EDIT!\n"
<< "# Generated by \"" << this->GetName() << "\""
@@ -1071,12 +1153,13 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
cmNinjaDeps orderOnlyDeps;
std::copy(asd.second.begin(), asd.second.end(),
std::back_inserter(orderOnlyDeps));
- WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
- "Assume dependencies for generated source file.",
- /*depfile*/ "", /*job_pool*/ "",
- /*uses_terminal*/ false,
- /*restat*/ true, cmNinjaDeps(1, asd.first), "",
- cmNinjaDeps(), orderOnlyDeps);
+ this->WriteCustomCommandBuild(
+ /*command=*/"", /*description=*/"",
+ "Assume dependencies for generated source file.",
+ /*depfile*/ "", /*job_pool*/ "",
+ /*uses_terminal*/ false,
+ /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(),
+ orderOnlyDeps);
}
}
@@ -1088,7 +1171,7 @@ std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget(
void cmGlobalNinjaGenerator::AppendTargetOutputs(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
- const std::string& config, cmNinjaTargetDepends depends)
+ const std::string& config, cmNinjaTargetDepends depends) const
{
// for frameworks, we want the real name, not smple name
// frameworks always appear versioned, and the build.ninja
@@ -1101,7 +1184,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::MODULE_LIBRARY: {
if (depends == DependOnTargetOrdering) {
- outputs.push_back(OrderDependsTargetForTarget(target, config));
+ outputs.push_back(this->OrderDependsTargetForTarget(target, config));
break;
}
}
@@ -1113,7 +1196,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
}
case cmStateEnums::OBJECT_LIBRARY: {
if (depends == DependOnTargetOrdering) {
- outputs.push_back(OrderDependsTargetForTarget(target, config));
+ outputs.push_back(this->OrderDependsTargetForTarget(target, config));
break;
}
}
@@ -1194,23 +1277,30 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
- const std::string& config)
+ const std::string& config, const std::string& fileConfig, bool genexOutput)
{
cmNinjaOuts outs;
- this->AppendTargetDependsClosure(target, outs, config, true);
+ this->AppendTargetDependsClosure(target, outs, config, fileConfig,
+ genexOutput, true);
cm::append(outputs, outs);
}
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmGeneratorTarget const* target, cmNinjaOuts& outputs,
- const std::string& config, bool omit_self)
+ const std::string& config, const std::string& fileConfig, bool genexOutput,
+ bool omit_self)
{
// try to locate the target in the cache
- auto find = this->Configs[config].TargetDependsClosures.lower_bound(target);
+ ByConfig::TargetDependsClosureKey key{
+ target,
+ config,
+ genexOutput,
+ };
+ auto find = this->Configs[fileConfig].TargetDependsClosures.lower_bound(key);
- if (find == this->Configs[config].TargetDependsClosures.end() ||
- find->first != target) {
+ if (find == this->Configs[fileConfig].TargetDependsClosures.end() ||
+ find->first != key) {
// We now calculate the closure outputs by inspecting the dependent
// targets recursively.
// For that we have to distinguish between a local result set that is only
@@ -1220,18 +1310,27 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmNinjaOuts this_outs; // this will be the new cache entry
for (auto const& dep_target : this->GetTargetDirectDepends(target)) {
- if (!dep_target->IsInBuildSystem() ||
- (target->GetType() != cmStateEnums::UTILITY &&
- dep_target->GetType() != cmStateEnums::UTILITY &&
- this->EnableCrossConfigBuild() && !dep_target.IsCross())) {
+ if (!dep_target->IsInBuildSystem()) {
+ continue;
+ }
+
+ if (!this->IsSingleConfigUtility(target) &&
+ !this->IsSingleConfigUtility(dep_target) &&
+ this->EnableCrossConfigBuild() && !dep_target.IsCross() &&
+ !genexOutput) {
continue;
}
- // Collect the dependent targets for _this_ target
- this->AppendTargetDependsClosure(dep_target, this_outs, config, false);
+ if (dep_target.IsCross()) {
+ this->AppendTargetDependsClosure(dep_target, this_outs, fileConfig,
+ fileConfig, genexOutput, false);
+ } else {
+ this->AppendTargetDependsClosure(dep_target, this_outs, config,
+ fileConfig, genexOutput, false);
+ }
}
- find = this->Configs[config].TargetDependsClosures.emplace_hint(
- find, target, std::move(this_outs));
+ find = this->Configs[fileConfig].TargetDependsClosures.emplace_hint(
+ find, key, std::move(this_outs));
}
// now fill the outputs of the final result from the newly generated cache
@@ -1414,7 +1513,7 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
build.Outputs.front() = this->BuildAlias(buildDirAllTarget, config);
configDeps.emplace_back(build.Outputs.front());
for (DirectoryTarget::Target const& t : dt.Targets) {
- if (!IsExcludedFromAllInConfig(t, config)) {
+ if (!this->IsExcludedFromAllInConfig(t, config)) {
this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config,
DependOnTargetArtifact);
}
@@ -1627,7 +1726,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
cmNinjaRule rule("RERUN_CMAKE");
rule.Command =
- cmStrCat(CMakeCmd(), " --regenerate-during-build -S",
+ cmStrCat(this->CMakeCmd(), " --regenerate-during-build -S",
lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
cmOutputConverter::SHELL),
" -B",
@@ -1652,7 +1751,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
// Use 'console' pool to get non buffered output of the CMake re-run call
// Available since Ninja 1.5
- if (SupportsConsolePool()) {
+ if (this->SupportsConsolePool()) {
reBuild.Variables["pool"] = "console";
}
@@ -1661,7 +1760,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
cmNinjaRule rule("VERIFY_GLOBS");
rule.Command =
- cmStrCat(CMakeCmd(), " -P ",
+ cmStrCat(this->CMakeCmd(), " -P ",
lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
cmOutputConverter::SHELL));
rule.Description = "Re-checking globbed directories...";
@@ -1722,8 +1821,8 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
build.Comment = "A missing CMake input file is not an error.";
std::set_difference(std::make_move_iterator(reBuild.ImplicitDeps.begin()),
std::make_move_iterator(reBuild.ImplicitDeps.end()),
- CustomCommandOutputs.begin(),
- CustomCommandOutputs.end(),
+ this->CustomCommandOutputs.begin(),
+ this->CustomCommandOutputs.end(),
std::back_inserter(build.Outputs));
this->WriteBuild(os, build);
}
@@ -1807,7 +1906,8 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
fout << " file(REMOVE_RECURSE\n";
for (std::string const& acf : it->second.AdditionalCleanFiles) {
fout << " "
- << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf))
+ << cmOutputConverter::EscapeForCMake(
+ this->ConvertToNinjaPath(acf))
<< '\n';
}
fout << " )\n";
@@ -1822,7 +1922,7 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
{
cmNinjaRule rule("CLEAN_ADDITIONAL");
rule.Command = cmStrCat(
- CMakeCmd(), " -DCONFIG=$CONFIG -P ",
+ this->CMakeCmd(), " -DCONFIG=$CONFIG -P ",
lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel),
cmOutputConverter::SHELL));
rule.Description = "Cleaning additional files...";
@@ -1839,13 +1939,13 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
build.Outputs.front() = this->BuildAlias(
this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), config);
build.Variables["CONFIG"] = config;
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
if (this->IsMultiConfig()) {
build.Outputs.front() =
this->NinjaOutputPath(this->GetAdditionalCleanTargetName());
build.Variables["CONFIG"] = "";
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
}
// Return success
@@ -1855,13 +1955,13 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
{
// -- Additional clean target
- bool additionalFiles = WriteTargetCleanAdditional(os);
+ bool additionalFiles = this->WriteTargetCleanAdditional(os);
// -- Default clean target
// Write rule
{
cmNinjaRule rule("CLEAN");
- rule.Command = cmStrCat(NinjaCmd(), " $FILE_ARG -t clean $TARGETS");
+ rule.Command = cmStrCat(this->NinjaCmd(), " $FILE_ARG -t clean $TARGETS");
rule.Description = "Cleaning all built files...";
rule.Comment = "Rule for cleaning all built files.";
WriteRule(*this->RulesFileStream, rule);
@@ -1962,13 +2062,13 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
build.Outputs.emplace_back(
this->ConvertToNinjaPath(GetByproductsForCleanTargetName()));
build.ExplicitDeps = this->ByproductsForCleanTarget;
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
for (auto const& config : configs) {
build.Outputs.front() = this->BuildAlias(
this->ConvertToNinjaPath(GetByproductsForCleanTargetName()), config);
build.ExplicitDeps = this->Configs[config].ByproductsForCleanTarget;
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
}
}
@@ -1977,7 +2077,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
{
{
cmNinjaRule rule("HELP");
- rule.Command = cmStrCat(NinjaCmd(), " -t targets");
+ rule.Command = cmStrCat(this->NinjaCmd(), " -t targets");
rule.Description = "All primary targets available:";
rule.Comment = "Rule for printing all primary targets available.";
WriteRule(*this->RulesFileStream, rule);
@@ -1986,7 +2086,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
cmNinjaBuild build("HELP");
build.Comment = "Print all primary targets available.";
build.Outputs.push_back(this->NinjaOutputPath("help"));
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
}
@@ -2017,6 +2117,8 @@ void cmGlobalNinjaGenerator::StripNinjaOutputPathPrefixAsSuffix(
cmStripSuffixIfExists(path, this->OutputPathPrefix);
}
+#if !defined(CMAKE_BOOTSTRAP)
+
/*
We use the following approach to support Fortran. Each target already
@@ -2096,16 +2198,6 @@ Compilation of source files within a target is split into the following steps:
(because the latter consumes the module).
*/
-struct cmSourceInfo
-{
- // Set of provided and required modules.
- std::set<std::string> Provides;
- std::set<std::string> Requires;
-
- // Set of files included in the translation unit.
- std::set<std::string> Includes;
-};
-
static std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
std::string const& arg_tdi, std::string const& arg_pp);
@@ -2113,6 +2205,7 @@ 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;
@@ -2121,6 +2214,8 @@ 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=")) {
@@ -2161,6 +2256,9 @@ 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;
if (arg_lang == "Fortran") {
@@ -2177,6 +2275,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
return 1;
}
+ info->PrimaryOutput = arg_obj;
+
{
cmGeneratedFileStream depfile(arg_dep);
depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":";
@@ -2186,24 +2286,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
depfile << "\n";
}
- Json::Value ddi(Json::objectValue);
- ddi["object"] = arg_obj;
-
- Json::Value& ddi_provides = ddi["provides"] = Json::arrayValue;
- for (std::string const& provide : info->Provides) {
- ddi_provides.append(provide);
- }
- Json::Value& ddi_requires = ddi["requires"] = Json::arrayValue;
- for (std::string const& r : info->Requires) {
- // Require modules not provided in the same source.
- if (!info->Provides.count(r)) {
- ddi_requires.append(r);
- }
- }
-
- cmGeneratedFileStream ddif(arg_ddi);
- ddif << ddi;
- if (!ddif) {
+ if (!cmScanDepFormat_P1689_Write(arg_ddi, arg_src, *info)) {
cmSystemTools::Error(
cmStrCat("-E cmake_ninja_depends failed to write ", arg_ddi));
return 1;
@@ -2261,26 +2344,35 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
}
auto info = cm::make_unique<cmSourceInfo>();
- info->Provides = finfo.Provides;
- info->Requires = finfo.Requires;
- info->Includes = finfo.Includes;
+ for (std::string const& provide : finfo.Provides) {
+ cmSourceReqInfo src_info;
+ src_info.LogicalName = provide;
+ src_info.CompiledModulePath = provide;
+ info->Provides.emplace_back(src_info);
+ }
+ for (std::string const& require : finfo.Requires) {
+ // Require modules not provided in the same source.
+ if (finfo.Provides.count(require)) {
+ continue;
+ }
+ cmSourceReqInfo src_info;
+ src_info.LogicalName = require;
+ src_info.CompiledModulePath = require;
+ info->Requires.emplace_back(src_info);
+ }
+ for (std::string const& include : finfo.Includes) {
+ info->Includes.push_back(include);
+ }
return info;
}
-struct cmDyndepObjectInfo
-{
- std::string Object;
- std::vector<std::string> Provides;
- std::vector<std::string> Requires;
-};
-
bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::string const& dir_top_src, std::string const& dir_top_bld,
std::string const& dir_cur_src, std::string const& dir_cur_bld,
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
- std::string const& arg_lang)
+ std::string const& arg_lang, std::string const& arg_modmapfmt)
{
// Setup path conversions.
{
@@ -2295,34 +2387,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
this->LocalGenerators.push_back(std::move(lgd));
}
- std::vector<cmDyndepObjectInfo> objects;
+ std::vector<cmSourceInfo> objects;
for (std::string const& arg_ddi : arg_ddis) {
- // Load the ddi file and compute the module file paths it provides.
- Json::Value ddio;
- Json::Value const& ddi = ddio;
- cmsys::ifstream ddif(arg_ddi.c_str(), std::ios::in | std::ios::binary);
- Json::Reader reader;
- if (!reader.parse(ddif, ddio, false)) {
- cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
- arg_ddi,
- reader.getFormattedErrorMessages()));
+ cmSourceInfo info;
+ if (!cmScanDepFormat_P1689_Parse(arg_ddi, &info)) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ddi file ", arg_ddi));
return false;
}
-
- cmDyndepObjectInfo info;
- info.Object = ddi["object"].asString();
- Json::Value const& ddi_provides = ddi["provides"];
- if (ddi_provides.isArray()) {
- for (auto const& ddi_provide : ddi_provides) {
- info.Provides.push_back(ddi_provide.asString());
- }
- }
- Json::Value const& ddi_requires = ddi["requires"];
- if (ddi_requires.isArray()) {
- for (auto const& ddi_require : ddi_requires) {
- info.Requires.push_back(ddi_require.asString());
- }
- }
objects.push_back(std::move(info));
}
@@ -2353,11 +2425,12 @@ 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 (cmDyndepObjectInfo const& object : objects) {
- for (std::string const& p : object.Provides) {
- std::string const mod = cmStrCat(module_dir, p);
- mod_files[p] = mod;
- tm[p] = mod;
+ for (cmSourceInfo const& object : objects) {
+ for (auto const& p : object.Provides) {
+ std::string const mod = cmStrCat(
+ module_dir, cmSystemTools::GetFilenameName(p.CompiledModulePath));
+ mod_files[p.LogicalName] = mod;
+ tm[p.LogicalName] = mod;
}
}
@@ -2367,15 +2440,16 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
{
cmNinjaBuild build("dyndep");
build.Outputs.emplace_back("");
- for (cmDyndepObjectInfo const& object : objects) {
- build.Outputs[0] = object.Object;
+ for (cmSourceInfo const& object : objects) {
+ build.Outputs[0] = this->ConvertToNinjaPath(object.PrimaryOutput);
build.ImplicitOuts.clear();
- for (std::string const& p : object.Provides) {
- build.ImplicitOuts.push_back(this->ConvertToNinjaPath(mod_files[p]));
+ for (auto const& p : object.Provides) {
+ build.ImplicitOuts.push_back(
+ this->ConvertToNinjaPath(mod_files[p.LogicalName]));
}
build.ImplicitDeps.clear();
- for (std::string const& r : object.Requires) {
- auto mit = mod_files.find(r);
+ for (auto const& r : object.Requires) {
+ auto mit = mod_files.find(r.LogicalName);
if (mit != mod_files.end()) {
build.ImplicitDeps.push_back(this->ConvertToNinjaPath(mit->second));
}
@@ -2385,6 +2459,48 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
build.Variables.emplace("restat", "1");
}
+ if (arg_modmapfmt.empty()) {
+ // nothing to do.
+ } else {
+ std::stringstream mm;
+ if (arg_modmapfmt == "gcc") {
+ // Documented in GCC's documentation. The format is a series of lines
+ // with a module name and the associated filename separated by
+ // spaces. The first line may use `$root` as the module name to
+ // specify a "repository root". That is used to anchor any relative
+ // paths present in the file (CMake should never generate any).
+
+ // Write the root directory to use for module paths.
+ mm << "$root .\n";
+
+ for (auto const& l : object.Provides) {
+ auto m = mod_files.find(l.LogicalName);
+ if (m != mod_files.end()) {
+ mm << l.LogicalName << " " << this->ConvertToNinjaPath(m->second)
+ << "\n";
+ }
+ }
+ for (auto const& r : object.Requires) {
+ auto m = mod_files.find(r.LogicalName);
+ if (m != mod_files.end()) {
+ mm << r.LogicalName << " " << this->ConvertToNinjaPath(m->second)
+ << "\n";
+ }
+ }
+ } else {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep does not understand the ",
+ arg_modmapfmt, " module map format"));
+ return false;
+ }
+
+ // XXX(modmap): If changing this path construction, change
+ // `cmNinjaTargetGenerator::WriteObjectBuildStatements` to generate the
+ // corresponding file path.
+ cmGeneratedFileStream mmf(cmStrCat(object.PrimaryOutput, ".modmap"));
+ mmf << mm.str();
+ }
+
this->WriteBuild(ddf, build);
}
}
@@ -2399,11 +2515,6 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
return true;
}
-bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const
-{
- return !this->CrossConfigs.empty();
-}
-
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd)
{
@@ -2413,6 +2524,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::string arg_dd;
std::string arg_lang;
std::string arg_tdi;
+ std::string arg_modmapfmt;
std::vector<std::string> arg_ddis;
for (std::string const& arg : arg_full) {
if (cmHasLiteralPrefix(arg, "--tdi=")) {
@@ -2421,6 +2533,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
arg_lang = arg.substr(7);
} else if (cmHasLiteralPrefix(arg, "--dd=")) {
arg_dd = arg.substr(5);
+ } else if (cmHasLiteralPrefix(arg, "--modmapfmt=")) {
+ arg_modmapfmt = arg.substr(12);
} else if (!cmHasLiteralPrefix(arg, "--") &&
cmHasLiteralSuffix(arg, ".ddi")) {
arg_ddis.push_back(arg);
@@ -2479,12 +2593,19 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
if (!ggd ||
!cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile(
dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis,
- module_dir, linked_target_dirs, arg_lang)) {
+ module_dir, linked_target_dirs, arg_lang, arg_modmapfmt)) {
return 1;
}
return 0;
}
+#endif
+
+bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const
+{
+ return !this->CrossConfigs.empty();
+}
+
void cmGlobalNinjaGenerator::AppendDirectoryForConfig(
const std::string& prefix, const std::string& config,
const std::string& suffix, std::string& dir)
@@ -2502,6 +2623,13 @@ std::set<std::string> cmGlobalNinjaGenerator::GetCrossConfigs(
return result;
}
+bool cmGlobalNinjaGenerator::IsSingleConfigUtility(
+ cmGeneratorTarget const* target) const
+{
+ return target->GetType() == cmStateEnums::UTILITY &&
+ !this->PerConfigUtilityTargets.count(target->GetName());
+}
+
const char* cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE =
"CMakeFiles/common.ninja";
const char* cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION = ".ninja";
@@ -2548,33 +2676,35 @@ bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams()
<< "# This file contains build statements common to all "
"configurations.\n\n";
- for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs(
- cmMakefile::IncludeEmptyConfig)) {
- // Open impl file.
- if (!this->OpenFileStream(this->ImplFileStreams[config],
- GetNinjaImplFilename(config))) {
- return false;
- }
+ auto const& configs =
+ this->Makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ return std::all_of(
+ configs.begin(), configs.end(), [this](std::string const& config) -> bool {
+ // Open impl file.
+ if (!this->OpenFileStream(this->ImplFileStreams[config],
+ GetNinjaImplFilename(config))) {
+ return false;
+ }
- // Write a comment about this file.
- *this->ImplFileStreams[config]
- << "# This file contains build statements specific to the \"" << config
- << "\"\n# configuration.\n\n";
+ // Write a comment about this file.
+ *this->ImplFileStreams[config]
+ << "# This file contains build statements specific to the \"" << config
+ << "\"\n# configuration.\n\n";
- // Open config file.
- if (!this->OpenFileStream(this->ConfigFileStreams[config],
- GetNinjaConfigFilename(config))) {
- return false;
- }
+ // Open config file.
+ if (!this->OpenFileStream(this->ConfigFileStreams[config],
+ GetNinjaConfigFilename(config))) {
+ return false;
+ }
- // Write a comment about this file.
- *this->ConfigFileStreams[config]
- << "# This file contains aliases specific to the \"" << config
- << "\"\n# configuration.\n\n"
- << "include " << GetNinjaImplFilename(config) << "\n\n";
- }
+ // Write a comment about this file.
+ *this->ConfigFileStreams[config]
+ << "# This file contains aliases specific to the \"" << config
+ << "\"\n# configuration.\n\n"
+ << "include " << GetNinjaImplFilename(config) << "\n\n";
- return true;
+ return true;
+ });
}
void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams()
@@ -2652,30 +2782,17 @@ void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs(
bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables()
{
- this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_DEFAULT_BUILD_TYPE");
- this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_CROSS_CONFIGS");
- this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_DEFAULT_CONFIGS");
- return this->ReadCacheEntriesForBuild(*this->Makefiles.front()->GetState());
-}
-
-std::string cmGlobalNinjaMultiGenerator::GetDefaultBuildConfig() const
-{
- return "";
-}
-
-bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
- const cmState& state)
-{
std::vector<std::string> configsVec;
- cmExpandList(state.GetSafeCacheEntryValue("CMAKE_CONFIGURATION_TYPES"),
- configsVec);
+ cmExpandList(
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_CONFIGURATION_TYPES"),
+ configsVec);
if (configsVec.empty()) {
configsVec.emplace_back();
}
std::set<std::string> configs(configsVec.cbegin(), configsVec.cend());
this->DefaultFileConfig =
- state.GetSafeCacheEntryValue("CMAKE_DEFAULT_BUILD_TYPE");
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_DEFAULT_BUILD_TYPE");
if (this->DefaultFileConfig.empty()) {
this->DefaultFileConfig = configsVec.front();
}
@@ -2690,8 +2807,9 @@ bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
}
std::vector<std::string> crossConfigsVec;
- cmExpandList(state.GetSafeCacheEntryValue("CMAKE_CROSS_CONFIGS"),
- crossConfigsVec);
+ cmExpandList(
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_CROSS_CONFIGS"),
+ crossConfigsVec);
auto crossConfigs = ListSubsetWithAll(configs, configs, crossConfigsVec);
if (!crossConfigs) {
std::ostringstream msg;
@@ -2704,7 +2822,7 @@ bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
this->CrossConfigs = *crossConfigs;
auto defaultConfigsString =
- state.GetSafeCacheEntryValue("CMAKE_DEFAULT_CONFIGS");
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_DEFAULT_CONFIGS");
if (defaultConfigsString.empty()) {
defaultConfigsString = this->DefaultFileConfig;
}
@@ -2738,6 +2856,11 @@ bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
return true;
}
+std::string cmGlobalNinjaMultiGenerator::GetDefaultBuildConfig() const
+{
+ return "";
+}
+
std::string cmGlobalNinjaMultiGenerator::OrderDependsTargetForTarget(
cmGeneratorTarget const* target, const std::string& config) const
{
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index b6687733e..0c919ef1d 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -24,6 +24,7 @@
#include "cmNinjaTypes.h"
#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
+#include "cmTransformDepfile.h"
class cmCustomCommand;
class cmGeneratorTarget;
@@ -31,7 +32,6 @@ class cmLinkLineComputer;
class cmLocalGenerator;
class cmMakefile;
class cmOutputConverter;
-class cmState;
class cmStateDirectory;
class cmake;
struct cmDocumentationEntry;
@@ -150,9 +150,8 @@ public:
static void WriteDefault(std::ostream& os, const cmNinjaDeps& targets,
const std::string& comment = "");
- bool IsGCCOnWindows() const { return UsingGCCOnWindows; }
+ bool IsGCCOnWindows() const { return this->UsingGCCOnWindows; }
-public:
cmGlobalNinjaGenerator(cmake* cm);
static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
@@ -171,6 +170,8 @@ public:
static std::string GetActualName() { return "Ninja"; }
+ bool IsNinja() const override { return true; }
+
/** Get encoding used by generator for ninja files */
codecvt::Encoding GetMakefileEncoding() const override;
@@ -211,6 +212,10 @@ public:
const char* GetCleanTargetName() const override { return "clean"; }
bool SupportsCustomCommandDepfile() const override { return true; }
+ cm::optional<cmDepfileFormat> DepfileFormat() const override
+ {
+ return cmDepfileFormat::GccDepfile;
+ }
virtual cmGeneratedFileStream* GetImplFileStream(
const std::string& /*config*/) const
@@ -248,7 +253,7 @@ public:
: GG(gg)
{
}
- std::string operator()(std::string const& path)
+ std::string operator()(std::string const& path) const
{
return this->GG->ConvertToNinjaPath(path);
}
@@ -319,17 +324,21 @@ public:
void AppendTargetOutputs(cmGeneratorTarget const* target,
cmNinjaDeps& outputs, const std::string& config,
- cmNinjaTargetDepends depends);
+ cmNinjaTargetDepends depends) const;
void AppendTargetDepends(cmGeneratorTarget const* target,
cmNinjaDeps& outputs, const std::string& config,
const std::string& fileConfig,
cmNinjaTargetDepends depends);
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaDeps& outputs,
- const std::string& config);
+ const std::string& config,
+ const std::string& fileConfig,
+ bool genexOutput);
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaOuts& outputs,
- const std::string& config, bool omit_self);
+ const std::string& config,
+ const std::string& fileConfig,
+ bool genexOutput, bool omit_self);
void AppendDirectoryForConfig(const std::string& prefix,
const std::string& config,
@@ -346,7 +355,10 @@ public:
outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
}
- int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }
+ int GetRuleCmdLength(const std::string& name)
+ {
+ return this->RuleCmdLength[name];
+ }
void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target,
const std::string& config);
@@ -385,15 +397,13 @@ public:
bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
- bool WriteDyndepFile(std::string const& dir_top_src,
- std::string const& dir_top_bld,
- std::string const& dir_cur_src,
- std::string const& dir_cur_bld,
- std::string const& arg_dd,
- std::vector<std::string> const& arg_ddis,
- std::string const& module_dir,
- std::vector<std::string> const& linked_target_dirs,
- std::string const& arg_lang);
+ bool WriteDyndepFile(
+ std::string const& dir_top_src, std::string const& dir_top_bld,
+ std::string const& dir_cur_src, std::string const& dir_cur_bld,
+ std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
+ std::string const& module_dir,
+ std::vector<std::string> const& linked_target_dirs,
+ std::string const& arg_lang, std::string const& arg_modmapfmt);
virtual std::string BuildAlias(const std::string& alias,
const std::string& /*config*/) const
@@ -425,6 +435,20 @@ public:
return this->DefaultConfigs;
}
+ const std::set<std::string>& GetPerConfigUtilityTargets() const
+ {
+ return this->PerConfigUtilityTargets;
+ }
+
+ void AddPerConfigUtilityTarget(const std::string& name)
+ {
+ this->PerConfigUtilityTargets.insert(name);
+ }
+
+ bool IsSingleConfigUtility(cmGeneratorTarget const* target) const;
+
+ bool CheckCxxModuleSupport();
+
protected:
void Generate() override;
@@ -462,7 +486,7 @@ private:
void CleanMetaData();
/// Write the common disclaimer text at the top of each build file.
- void WriteDisclaimer(std::ostream& os);
+ void WriteDisclaimer(std::ostream& os) const;
void WriteAssumedSourceDependencies();
@@ -518,6 +542,9 @@ private:
/// The mapping from source file to assumed dependencies.
std::map<std::string, std::set<std::string>> AssumedSourceDependencies;
+ /// Utility targets which have per-config outputs
+ std::set<std::string> PerConfigUtilityTargets;
+
struct TargetAlias
{
cmGeneratorTarget* GeneratorTarget;
@@ -542,7 +569,8 @@ private:
bool NinjaSupportsMultipleOutputs = false;
bool NinjaSupportsMetadataOnRegeneration = false;
-private:
+ bool DiagnosedCxxModuleSupport = false;
+
void InitOutputPathPrefix();
std::string OutputPathPrefix;
@@ -557,7 +585,14 @@ private:
/// The set of custom commands we have seen.
std::set<cmCustomCommand const*> CustomCommands;
- std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures;
+ struct TargetDependsClosureKey
+ {
+ cmGeneratorTarget const* Target;
+ std::string Config;
+ bool GenexOutput;
+ };
+
+ std::map<TargetDependsClosureKey, cmNinjaOuts> TargetDependsClosures;
TargetAliasMap TargetAliases;
@@ -566,6 +601,19 @@ private:
std::map<std::string, ByConfig> Configs;
cmNinjaDeps ByproductsForCleanTarget;
+
+ friend bool operator==(const ByConfig::TargetDependsClosureKey& lhs,
+ const ByConfig::TargetDependsClosureKey& rhs);
+ friend bool operator!=(const ByConfig::TargetDependsClosureKey& lhs,
+ const ByConfig::TargetDependsClosureKey& rhs);
+ friend bool operator<(const ByConfig::TargetDependsClosureKey& lhs,
+ const ByConfig::TargetDependsClosureKey& rhs);
+ friend bool operator>(const ByConfig::TargetDependsClosureKey& lhs,
+ const ByConfig::TargetDependsClosureKey& rhs);
+ friend bool operator<=(const ByConfig::TargetDependsClosureKey& lhs,
+ const ByConfig::TargetDependsClosureKey& rhs);
+ friend bool operator>=(const ByConfig::TargetDependsClosureKey& lhs,
+ const ByConfig::TargetDependsClosureKey& rhs);
};
class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator
@@ -651,8 +699,6 @@ public:
std::string GetDefaultBuildConfig() const override;
- bool ReadCacheEntriesForBuild(const cmState& state) override;
-
bool SupportsDefaultBuildType() const override { return true; }
bool SupportsCrossConfigs() const override { return true; }
bool SupportsDefaultConfigs() const override { return true; }
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 2c934e1d3..97384cd5a 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -44,6 +44,7 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm)
#endif
this->IncludeDirective = "include";
+ this->LineContinueDirective = "\\\n";
this->DefineWindowsNULL = false;
this->PassMakeflags = false;
this->UnixCD = true;
@@ -589,10 +590,16 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
}
makeCommand.Add(this->SelectMakeProgram(makeProgram));
+ // Explicitly tell the make tool to use the Makefile written by
+ // cmLocalUnixMakefileGenerator3::WriteLocalMakefile
+ makeCommand.Add("-f");
+ makeCommand.Add("Makefile");
+
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
- makeCommand.Add("-j");
- if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
- makeCommand.Add(std::to_string(jobs));
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add("-j");
+ } else {
+ makeCommand.Add("-j" + std::to_string(jobs));
}
}
@@ -831,7 +838,7 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks()
for (const auto& gt : lg->GetGeneratorTargets()) {
cmLocalGenerator* tlg = gt->GetLocalGenerator();
- if (!gt->IsInBuildSystem() || IsExcluded(lg.get(), gt.get())) {
+ if (!gt->IsInBuildSystem() || this->IsExcluded(lg.get(), gt.get())) {
continue;
}
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 77d0827b5..7c950cca1 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -93,6 +93,12 @@ public:
*/
static bool SupportsPlatform() { return false; }
+ /**
+ * Utilized to determine if this generator
+ * supports DEPFILE option.
+ */
+ bool SupportsCustomCommandDepfile() const override { return true; }
+
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
@@ -127,6 +133,18 @@ public:
void WriteConvenienceRules(std::ostream& ruleFileStream,
std::set<std::string>& emitted);
+ // Make tool supports dependency files generated by compiler
+ bool SupportsCompilerDependencies() const
+ {
+ return this->ToolSupportsCompilerDependencies;
+ }
+
+ // Make tool supports long line dependencies
+ bool SupportsLongLineDependencies() const
+ {
+ return this->ToolSupportsLongLineDependencies;
+ }
+
/** Get the command to use for a target that has no rule. This is
used for multiple output dependencies and for cmake_force. */
std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; }
@@ -170,6 +188,7 @@ public:
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
std::string IncludeDirective;
+ std::string LineContinueDirective;
bool DefineWindowsNULL;
bool PassMakeflags;
bool UnixCD;
@@ -218,6 +237,14 @@ protected:
bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
+ // Specify if the make tool is able to consume dependency files
+ // generated by the compiler
+ bool ToolSupportsCompilerDependencies = true;
+
+ // some Make generator, such as Borland not support long line dependencies,
+ // we add SupportsLongLineDependencies to predicate.
+ bool ToolSupportsLongLineDependencies = true;
+
// Some make programs (Borland) do not keep a rule if there are no
// dependencies or commands. This is a problem for creating rules
// that might not do anything but might have other dependencies
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 6267205ab..75cd71443 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -380,9 +380,10 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
std::string project = target->GetName();
std::string location = *expath;
- cmProp p = target->GetProperty("VS_PROJECT_TYPE");
- this->WriteExternalProject(fout, project, location, cmToCStr(p),
- target->GetUtilities());
+ this->WriteExternalProject(
+ fout, project, location,
+ cmToCStr(target->GetProperty("VS_PROJECT_TYPE")),
+ target->GetUtilities());
written = true;
} else {
cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index fcdfc5064..b19212e47 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -108,9 +108,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
cmCustomCommandLines no_commands;
- cmTarget* tgt = lg.AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
- no_working_directory, no_byproducts,
- no_depends, no_commands);
+ cmTarget* tgt = lg.AddUtilityCommand(
+ CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, no_working_directory,
+ no_byproducts, no_depends, no_commands, cmPolicies::NEW);
auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg);
auto gt = ptr.get();
@@ -160,10 +160,11 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
std::vector<std::string> byproducts;
byproducts.push_back(cm->GetGlobVerifyStamp());
- lg.AddCustomCommandToTarget(
- CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, no_depends,
- verifyCommandLines, cmCustomCommandType::PRE_BUILD,
- "Checking File Globs", no_working_directory, stdPipesUTF8);
+ lg.AddCustomCommandToTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts,
+ no_depends, verifyCommandLines,
+ cmCustomCommandType::PRE_BUILD,
+ "Checking File Globs", no_working_directory,
+ cmPolicies::NEW, stdPipesUTF8);
// Ensure ZERO_CHECK always runs in Visual Studio using MSBuild,
// otherwise the prebuild command will not be run.
@@ -195,8 +196,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
if (cmSourceFile* file = lg.AddCustomCommandToOutput(
stamps, no_byproducts, listFiles, no_main_dependency,
no_implicit_depends, commandLines, "Checking Build System",
- no_working_directory, true, false, false, false, "", "",
- stdPipesUTF8)) {
+ no_working_directory, cmPolicies::NEW, true, false, false, false, "",
+ "", stdPipesUTF8)) {
gt->AddSource(file->ResolveFullPath());
} else {
cmSystemTools::Error("Error adding rule for " + stamps[0]);
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 001d87665..c23ee9451 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -200,7 +200,7 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
// considered always out of date.
cmTarget* allBuild = gen[0]->AddUtilityCommand(
"ALL_BUILD", true, no_working_dir, no_byproducts, no_depends,
- no_commands, false, "Build all projects");
+ no_commands, cmPolicies::NEW, false, "Build all projects");
gen[0]->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(allBuild, gen[0]));
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index fb518a233..9a9a4658f 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -205,6 +205,7 @@ public:
platforms.emplace_back("Win32");
platforms.emplace_back("ARM");
platforms.emplace_back("ARM64");
+ platforms.emplace_back("ARM64EC");
return platforms;
}
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index d6a7afa7a..3e2d92df7 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -25,6 +25,7 @@ cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator(cmake* cm)
#endif
cm->GetState()->SetWatcomWMake(true);
this->IncludeDirective = "!include";
+ this->LineContinueDirective = "&\n";
this->DefineWindowsNULL = true;
this->UnixCD = false;
this->MakeSilentFlag = "-h";
@@ -37,7 +38,6 @@ void cmGlobalWatcomWMakeGenerator::EnableLanguage(
mf->AddDefinition("WATCOM", "1");
mf->AddDefinition("CMAKE_QUOTE_INCLUDE_PATHS", "1");
mf->AddDefinition("CMAKE_MANGLE_OBJECT_FILE_NAMES", "1");
- mf->AddDefinition("CMAKE_MAKE_LINE_CONTINUE", "&");
mf->AddDefinition("CMAKE_MAKE_SYMBOLIC_RULE", ".SYMBOLIC");
mf->AddDefinition("CMAKE_GENERATOR_CC", "wcl386");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "wcl386");
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 5b4485193..d6cc423bf 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -47,8 +47,11 @@
struct cmLinkImplementation;
#if !defined(CMAKE_BOOTSTRAP) && defined(__APPLE__)
-# define HAVE_APPLICATION_SERVICES
-# include <ApplicationServices/ApplicationServices.h>
+# include <CoreFoundation/CoreFoundation.h>
+# if !TARGET_OS_IPHONE
+# define HAVE_APPLICATION_SERVICES
+# include <ApplicationServices/ApplicationServices.h>
+# endif
#endif
#if !defined(CMAKE_BOOTSTRAP)
@@ -504,16 +507,15 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
}
}
- if (this->XcodeBuildSystem >= BuildSystem::Twelve) {
+ if ((this->XcodeBuildSystem >= BuildSystem::Twelve) ||
+ (jobs != cmake::NO_BUILD_PARALLEL_LEVEL)) {
makeCommand.Add("-parallelizeTargets");
}
makeCommand.Add("-configuration", (config.empty() ? "Debug" : config));
- if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
- makeCommand.Add("-jobs");
- if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
- makeCommand.Add(std::to_string(jobs));
- }
+ if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) &&
+ (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) {
+ makeCommand.Add("-jobs", std::to_string(jobs));
}
if (this->XcodeVersion >= 70) {
@@ -618,7 +620,8 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// Add ALL_BUILD
cmTarget* allbuild = root->AddUtilityCommand(
"ALL_BUILD", true, no_working_directory, no_byproducts, no_depends,
- cmMakeSingleCommandLine({ "echo", "Build all projects" }));
+ cmMakeSingleCommandLine({ "echo", "Build all projects" }),
+ cmPolicies::NEW);
root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(allbuild, root));
@@ -644,10 +647,10 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
std::string file =
this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
cmSystemTools::ReplaceString(file, "\\ ", " ");
- cmTarget* check =
- root->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true,
- no_working_directory, no_byproducts, no_depends,
- cmMakeSingleCommandLine({ "make", "-f", file }));
+ cmTarget* check = root->AddUtilityCommand(
+ CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_working_directory,
+ no_byproducts, no_depends,
+ cmMakeSingleCommandLine({ "make", "-f", file }), cmPolicies::NEW);
root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(check, root));
}
@@ -676,8 +679,9 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
gen->AddCustomCommandToTarget(
target->GetName(), no_byproducts, no_depends,
legacyDependHelperCommandLines, cmCustomCommandType::POST_BUILD,
- "Depend check for xcode", legacyDependHelperDir.c_str(), true, false,
- "", "", false, cmObjectLibraryCommands::Accept);
+ "Depend check for xcode", legacyDependHelperDir.c_str(),
+ cmPolicies::NEW, true, false, "", "", false,
+ cmObjectLibraryCommands::Accept);
}
if (!this->IsExcluded(gens[0], target.get())) {
@@ -775,7 +779,9 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects()
this->TargetGroup.clear();
this->FileRefs.clear();
this->ExternalLibRefs.clear();
+ this->EmbeddedLibRefs.clear();
this->FileRefToBuildFileMap.clear();
+ this->FileRefToEmbedBuildFileMap.clear();
this->CommandsVisited.clear();
}
@@ -941,6 +947,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
default:
break;
}
+
+ // Explicitly add the explicit language flag before any other flag
+ // so user flags can override it.
+ gtgt->AddExplicitLanguageFlags(flags, *sf);
+
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (cmProp cflags = sf->GetProperty(COMPILE_FLAGS)) {
lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
@@ -1202,7 +1213,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
}
}
// Make a copy so that we can override it later
- std::string path = fullpath;
+ std::string path = cmSystemTools::CollapseFullPath(fullpath);
// Compute the extension without leading '.'.
std::string ext = cmSystemTools::GetFilenameLastExtension(path);
if (!ext.empty()) {
@@ -1382,7 +1393,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
// organize the sources
std::vector<cmSourceFile*> commonSourceFiles;
- if (!gtgt->GetConfigCommonSourceFiles(commonSourceFiles)) {
+ if (!gtgt->GetConfigCommonSourceFilesForXcode(commonSourceFiles)) {
return false;
}
@@ -1647,6 +1658,14 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
}
}
+ // Allow empty source file list for iOS Sticker packs
+ if (const char* productType = GetTargetProductType(gtgt)) {
+ if (strcmp(productType,
+ "com.apple.product-type.app-extension.messages-sticker-pack") ==
+ 0)
+ return;
+ }
+
// Add an empty source file to the target that compiles with the
// linker language. This should convince Xcode to choose the proper
// language.
@@ -1738,7 +1757,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
gtgt, postbuild);
} else {
std::vector<cmSourceFile*> classes;
- if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ if (!gtgt->GetConfigCommonSourceFilesForXcode(classes)) {
return;
}
// add all the sources
@@ -1798,6 +1817,10 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
if (frameworkBuildPhase) {
buildPhases->AddObject(frameworkBuildPhase);
}
+
+ // When this build phase is present, it must be last. More build phases may
+ // be added later for embedding things and they will insert themselves just
+ // before this last build phase.
if (postBuildPhase) {
buildPhases->AddObject(postBuildPhase);
}
@@ -1807,7 +1830,7 @@ void cmGlobalXCodeGenerator::CreateRunScriptBuildPhases(
cmXCodeObject* buildPhases, cmGeneratorTarget const* gt)
{
std::vector<cmSourceFile*> sources;
- if (!gt->GetConfigCommonSourceFiles(sources)) {
+ if (!gt->GetConfigCommonSourceFilesForXcode(sources)) {
return;
}
auto& visited = this->CommandsVisited[gt];
@@ -2953,7 +2976,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
if (gtgt->GetType() != cmStateEnums::GLOBAL_TARGET &&
gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
std::vector<cmSourceFile*> sources;
- if (!gtgt->GetConfigCommonSourceFiles(sources)) {
+ if (!gtgt->GetConfigCommonSourceFilesForXcode(sources)) {
return nullptr;
}
@@ -3228,36 +3251,43 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
if (!attr) {
settings->AddAttribute(attribute, value);
} else {
- if (value->GetType() != cmXCodeObject::OBJECT_LIST &&
- value->GetType() != cmXCodeObject::STRING) {
- cmSystemTools::Error("Unsupported value type for appending: " +
- std::string(attribute));
- return;
- }
- if (attr->GetType() == cmXCodeObject::OBJECT_LIST) {
- if (value->GetType() == cmXCodeObject::OBJECT_LIST) {
- for (auto* obj : value->GetObjectList()) {
- attr->AddObject(obj);
- }
- } else {
- attr->AddObject(value);
- }
- } else if (attr->GetType() == cmXCodeObject::STRING) {
- if (value->GetType() == cmXCodeObject::OBJECT_LIST) {
- // Add old value as a list item to new object list
- // and replace the attribute with the new list
- value->PrependObject(attr);
- settings->AddAttribute(attribute, value);
- } else {
- std::string newValue =
- cmStrCat(attr->GetString(), ' ', value->GetString());
- attr->SetString(newValue);
- }
- } else {
- cmSystemTools::Error("Unsupported attribute type for appending: " +
- std::string(attribute));
+ this->AppendBuildSettingAttribute(settings, attribute, attr, value);
+ }
+ }
+}
+
+void cmGlobalXCodeGenerator::AppendBuildSettingAttribute(
+ cmXCodeObject* settings, const char* attribute, cmXCodeObject* attr,
+ cmXCodeObject* value)
+{
+ if (value->GetType() != cmXCodeObject::OBJECT_LIST &&
+ value->GetType() != cmXCodeObject::STRING) {
+ cmSystemTools::Error("Unsupported value type for appending: " +
+ std::string(attribute));
+ return;
+ }
+ if (attr->GetType() == cmXCodeObject::OBJECT_LIST) {
+ if (value->GetType() == cmXCodeObject::OBJECT_LIST) {
+ for (auto* obj : value->GetObjectList()) {
+ attr->AddObject(obj);
}
+ } else {
+ attr->AddObject(value);
+ }
+ } else if (attr->GetType() == cmXCodeObject::STRING) {
+ if (value->GetType() == cmXCodeObject::OBJECT_LIST) {
+ // Add old value as a list item to new object list
+ // and replace the attribute with the new list
+ value->PrependObject(attr);
+ settings->AddAttribute(attribute, value);
+ } else {
+ std::string newValue =
+ cmStrCat(attr->GetString(), ' ', value->GetString());
+ attr->SetString(newValue);
}
+ } else {
+ cmSystemTools::Error("Unsupported attribute type for appending: " +
+ std::string(attribute));
}
}
@@ -3280,6 +3310,24 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute(
}
}
+void cmGlobalXCodeGenerator::InheritBuildSettingAttribute(
+ cmXCodeObject* target, const char* attribute)
+{
+ cmXCodeObject* configurationList =
+ target->GetAttribute("buildConfigurationList")->GetObject();
+ cmXCodeObject* buildConfigs =
+ configurationList->GetAttribute("buildConfigurations");
+ for (auto obj : buildConfigs->GetObjectList()) {
+ cmXCodeObject* settings = obj->GetAttribute("buildSettings");
+ if (cmXCodeObject* attr = settings->GetAttribute(attribute)) {
+ BuildObjectListOrString inherited(this, true);
+ inherited.Add("$(inherited)");
+ this->AppendBuildSettingAttribute(settings, attribute, attr,
+ inherited.CreateList());
+ }
+ }
+}
+
void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
{
cmGeneratorTarget* gt = target->GetTarget();
@@ -3596,11 +3644,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
for (auto& libDir : linkSearchPaths) {
libSearchPaths.Add(this->XCodeEscapePath(libDir));
}
- // Add paths defined in project-wide build settings
- libSearchPaths.Add("$(inherited)");
- this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
- libSearchPaths.CreateList(),
- configName);
+ if (!libSearchPaths.IsEmpty()) {
+ this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
+ libSearchPaths.CreateList(),
+ configName);
+ }
}
// add framework search paths
@@ -3611,11 +3659,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
for (auto& fwDir : frameworkSearchPaths) {
fwSearchPaths.Add(this->XCodeEscapePath(fwDir));
}
- // Add paths defined in project-wide build settings
- fwSearchPaths.Add("$(inherited)");
- this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
- fwSearchPaths.CreateList(),
- configName);
+ if (!fwSearchPaths.IsEmpty()) {
+ this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
+ fwSearchPaths.CreateList(),
+ configName);
+ }
}
// now add the left-over link libraries
@@ -3679,6 +3727,130 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
}
+void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
+{
+ cmGeneratorTarget* gt = target->GetTarget();
+ if (!gt) {
+ cmSystemTools::Error("Error no target on xobject\n");
+ return;
+ }
+ if (!gt->IsInBuildSystem()) {
+ return;
+ }
+ bool isFrameworkTarget = gt->IsFrameworkOnApple();
+ bool isBundleTarget = gt->GetPropertyAsBool("MACOSX_BUNDLE");
+ bool isCFBundleTarget = gt->IsCFBundleOnApple();
+ if (!(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
+ return;
+ }
+ cmProp files = gt->GetProperty("XCODE_EMBED_FRAMEWORKS");
+ if (!files) {
+ return;
+ }
+
+ // 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));
+ copyFilesBuildPhase->AddAttribute(
+ "name", this->CreateString(copyFilesBuildPhaseName));
+ if (cmProp fwEmbedPath = gt->GetProperty("XCODE_EMBED_FRAMEWORKS_PATH")) {
+ copyFilesBuildPhase->AddAttribute("dstPath",
+ this->CreateString(*fwEmbedPath));
+ } else {
+ copyFilesBuildPhase->AddAttribute("dstPath", this->CreateString(""));
+ }
+ copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ // Collect all embedded frameworks and add them to build phase
+ std::vector<std::string> relFiles = cmExpandedList(*files);
+ for (std::string const& relFile : relFiles) {
+ cmXCodeObject* buildFile{ nullptr };
+ std::string filePath = relFile;
+ auto* genTarget = FindGeneratorTarget(relFile);
+ if (genTarget) {
+ // This is a target - get it's product path reference
+ auto* xcTarget = FindXCodeTarget(genTarget);
+ if (!xcTarget) {
+ cmSystemTools::Error("Can not find a target for " +
+ genTarget->GetName());
+ continue;
+ }
+ // Add the target output file as a build reference for other targets
+ // to link against
+ auto* fileRefObject = xcTarget->GetAttribute("productReference");
+ if (!fileRefObject) {
+ cmSystemTools::Error("Target " + genTarget->GetName() +
+ " is missing product reference");
+ continue;
+ }
+ auto it = FileRefToEmbedBuildFileMap.find(fileRefObject);
+ if (it == FileRefToEmbedBuildFileMap.end()) {
+ buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildFile->AddAttribute("fileRef", fileRefObject);
+ 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()) {
+ cmXCodeObject* fileRef =
+ this->CreateXCodeFileReferenceFromPath(relFile, gt, "", nullptr);
+ if (fileRef) {
+ buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildFile->SetComment(fileRef->GetComment());
+ buildFile->AddAttribute("fileRef",
+ this->CreateObjectReference(fileRef));
+ }
+ if (!buildFile) {
+ cmSystemTools::Error("Can't create build file for " + relFile);
+ continue;
+ }
+ this->EmbeddedLibRefs.emplace(filePath, buildFile);
+ } else {
+ buildFile = it->second;
+ }
+ }
+ if (!buildFile) {
+ cmSystemTools::Error("Can't find a build file for " + relFile);
+ continue;
+ }
+ // Set build file configuration
+ 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)) {
+ attrs->AddObject(this->CreateString("RemoveHeadersOnCopy"));
+ }
+ const auto& codeSignProp =
+ gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY");
+ if (cmIsOn(codeSignProp)) {
+ attrs->AddObject(this->CreateString("CodeSignOnCopy"));
+ }
+ settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs);
+ buildFile->AddAttributeIfNotEmpty("settings", settings);
+ if (!buildFiles->HasObject(buildFile)) {
+ buildFiles->AddObject(buildFile);
+ }
+ }
+ copyFilesBuildPhase->AddAttribute("files", buildFiles);
+ auto* buildPhases = target->GetAttribute("buildPhases");
+ // Insert embed build phase right before the post-build command
+ buildPhases->InsertObject(buildPhases->GetObjectCount() - 1,
+ copyFilesBuildPhase);
+}
+
bool cmGlobalXCodeGenerator::CreateGroups(
std::vector<cmLocalGenerator*>& generators)
{
@@ -4057,7 +4229,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
// loop over all targets and add link and depend info
for (auto t : targets) {
this->AddDependAndLinkInformation(t);
+ this->AddEmbeddedFrameworks(t);
+ // Inherit project-wide values for any target-specific search paths.
+ this->InheritBuildSettingAttribute(t, "HEADER_SEARCH_PATHS");
+ this->InheritBuildSettingAttribute(t, "SYSTEM_HEADER_SEARCH_PATHS");
+ this->InheritBuildSettingAttribute(t, "FRAMEWORK_SEARCH_PATHS");
+ this->InheritBuildSettingAttribute(t, "SYSTEM_FRAMEWORK_SEARCH_PATHS");
+ this->InheritBuildSettingAttribute(t, "LIBRARY_SEARCH_PATHS");
+ this->InheritBuildSettingAttribute(t, "LD_RUNPATH_SEARCH_PATHS");
}
+
if (this->XcodeBuildSystem == BuildSystem::One) {
this->CreateXCodeDependHackMakefile(targets);
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 8ff6846e9..1ab56e20e 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -186,11 +186,17 @@ private:
cmGeneratorTarget* gtgt);
void AppendOrAddBuildSetting(cmXCodeObject* settings, const char* attr,
cmXCodeObject* value);
+ void AppendBuildSettingAttribute(cmXCodeObject* settings,
+ const char* attribute, cmXCodeObject* attr,
+ cmXCodeObject* value);
void AppendBuildSettingAttribute(cmXCodeObject* target, const char* attr,
cmXCodeObject* value,
const std::string& configName);
+ void InheritBuildSettingAttribute(cmXCodeObject* target,
+ const char* attribute);
cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
void AddDependAndLinkInformation(cmXCodeObject* target);
+ void AddEmbeddedFrameworks(cmXCodeObject* target);
void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
cmXCodeObject* buildSettings,
const std::string& configName);
@@ -329,8 +335,10 @@ private:
std::map<std::string, cmXCodeObject*> TargetGroup;
std::map<std::string, cmXCodeObject*> FileRefs;
std::map<std::string, cmXCodeObject*> ExternalLibRefs;
+ std::map<std::string, cmXCodeObject*> EmbeddedLibRefs;
std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap;
+ std::map<cmXCodeObject*, cmXCodeObject*> FileRefToEmbedBuildFileMap;
std::vector<std::string> Architectures;
std::string ObjectDirArchDefault;
std::string ObjectDirArch;
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index cf4ba93c5..122bda52d 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -131,8 +131,8 @@ cmGraphVizWriter::~cmGraphVizWriter()
void cmGraphVizWriter::VisitGraph(std::string const&)
{
- this->WriteHeader(GlobalFileStream, this->GraphName);
- this->WriteLegend(GlobalFileStream);
+ this->WriteHeader(this->GlobalFileStream, this->GraphName);
+ this->WriteLegend(this->GlobalFileStream);
}
void cmGraphVizWriter::OnItem(cmLinkItem const& item)
@@ -141,8 +141,9 @@ void cmGraphVizWriter::OnItem(cmLinkItem const& item)
return;
}
- NodeNames[item.AsStr()] = cmStrCat(GraphNodePrefix, NextNodeId);
- ++NextNodeId;
+ this->NodeNames[item.AsStr()] =
+ cmStrCat(this->GraphNodePrefix, this->NextNodeId);
+ ++this->NextNodeId;
this->WriteNode(this->GlobalFileStream, item);
}
@@ -191,12 +192,13 @@ void cmGraphVizWriter::VisitLink(cmLinkItem const& depender,
this->WriteConnection(this->GlobalFileStream, depender, dependee, scopeType);
if (this->GeneratePerTarget) {
- PerTargetConnections[depender].emplace_back(depender, dependee, scopeType);
+ this->PerTargetConnections[depender].emplace_back(depender, dependee,
+ scopeType);
}
if (this->GenerateDependers) {
- TargetDependersConnections[dependee].emplace_back(dependee, depender,
- scopeType);
+ this->TargetDependersConnections[dependee].emplace_back(dependee, depender,
+ scopeType);
}
}
@@ -228,7 +230,7 @@ void cmGraphVizWriter::ReadSettings(
std::cout << "Reading GraphViz options file: " << inFileName << std::endl;
-#define __set_if_set(var, cmakeDefinition) \
+#define set_if_set(var, cmakeDefinition) \
do { \
cmProp value = mf.GetDefinition(cmakeDefinition); \
if (value) { \
@@ -236,11 +238,11 @@ void cmGraphVizWriter::ReadSettings(
} \
} while (false)
- __set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME");
- __set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER");
- __set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX");
+ set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME");
+ set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER");
+ set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX");
-#define __set_bool_if_set(var, cmakeDefinition) \
+#define set_bool_if_set(var, cmakeDefinition) \
do { \
cmProp value = mf.GetDefinition(cmakeDefinition); \
if (value) { \
@@ -248,20 +250,20 @@ void cmGraphVizWriter::ReadSettings(
} \
} while (false)
- __set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES");
- __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS");
- __set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS");
- __set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS");
- __set_bool_if_set(this->GenerateForInterfaceLibs, "GRAPHVIZ_INTERFACE_LIBS");
- __set_bool_if_set(this->GenerateForObjectLibs, "GRAPHVIZ_OBJECT_LIBS");
- __set_bool_if_set(this->GenerateForUnknownLibs, "GRAPHVIZ_UNKNOWN_LIBS");
- __set_bool_if_set(this->GenerateForCustomTargets, "GRAPHVIZ_CUSTOM_TARGETS");
- __set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS");
- __set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET");
- __set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS");
+ set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES");
+ set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS");
+ set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS");
+ set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS");
+ set_bool_if_set(this->GenerateForInterfaceLibs, "GRAPHVIZ_INTERFACE_LIBS");
+ set_bool_if_set(this->GenerateForObjectLibs, "GRAPHVIZ_OBJECT_LIBS");
+ set_bool_if_set(this->GenerateForUnknownLibs, "GRAPHVIZ_UNKNOWN_LIBS");
+ set_bool_if_set(this->GenerateForCustomTargets, "GRAPHVIZ_CUSTOM_TARGETS");
+ set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS");
+ set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET");
+ set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS");
std::string ignoreTargetsRegexes;
- __set_if_set(ignoreTargetsRegexes, "GRAPHVIZ_IGNORE_TARGETS");
+ set_if_set(ignoreTargetsRegexes, "GRAPHVIZ_IGNORE_TARGETS");
this->TargetsToIgnoreRegex.clear();
if (!ignoreTargetsRegexes.empty()) {
@@ -280,7 +282,7 @@ void cmGraphVizWriter::ReadSettings(
void cmGraphVizWriter::Write()
{
- auto gg = this->GlobalGenerator;
+ const auto* gg = this->GlobalGenerator;
this->VisitGraph(gg->GetName());
@@ -301,18 +303,18 @@ void cmGraphVizWriter::Write()
}
// write global data and collect all connection data for per target graphs
- for (auto const gt : sortedGeneratorTargets) {
+ for (const auto* const gt : sortedGeneratorTargets) {
auto item = cmLinkItem(gt, false, gt->GetBacktrace());
this->VisitItem(item);
}
if (this->GeneratePerTarget) {
- WritePerTargetConnections<DependeesDir>(PerTargetConnections);
+ this->WritePerTargetConnections<DependeesDir>(this->PerTargetConnections);
}
if (this->GenerateDependers) {
- WritePerTargetConnections<DependersDir>(TargetDependersConnections,
- ".dependers");
+ this->WritePerTargetConnections<DependersDir>(
+ this->TargetDependersConnections, ".dependers");
}
}
@@ -336,7 +338,8 @@ void cmGraphVizWriter::FindAllConnections(const ConnectionsMap& connectionMap,
bool const visited = visitedItems.find(dstItem) != visitedItems.cend();
if (!visited) {
visitedItems.insert(dstItem);
- FindAllConnections(connectionMap, dstItem, extendedCons, visitedItems);
+ this->FindAllConnections(connectionMap, dstItem, extendedCons,
+ visitedItems);
}
}
}
@@ -346,7 +349,8 @@ void cmGraphVizWriter::FindAllConnections(const ConnectionsMap& connectionMap,
Connections& extendedCons)
{
std::set<cmLinkItem> visitedItems = { rootItem };
- FindAllConnections(connectionMap, rootItem, extendedCons, visitedItems);
+ this->FindAllConnections(connectionMap, rootItem, extendedCons,
+ visitedItems);
}
template <typename DirFunc>
@@ -358,7 +362,7 @@ void cmGraphVizWriter::WritePerTargetConnections(
for (auto const& conPerTarget : connections) {
const cmLinkItem& rootItem = conPerTarget.first;
Connections& extendedCons = extendedConnections[conPerTarget.first];
- FindAllConnections(connections, rootItem, extendedCons);
+ this->FindAllConnections(connections, rootItem, extendedCons);
}
for (auto const& conPerTarget : extendedConnections) {
@@ -451,7 +455,7 @@ void cmGraphVizWriter::WriteNode(cmGeneratedFileStream& fs,
auto const& itemName = item.AsStr();
auto const& nodeName = this->NodeNames[itemName];
- auto const itemNameWithAliases = ItemNameWithAliases(itemName);
+ auto const itemNameWithAliases = this->ItemNameWithAliases(itemName);
auto const escapedLabel = EscapeForDotFile(itemNameWithAliases);
fs << " \"" << nodeName << "\" [ label = \"" << escapedLabel
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index ae801bb98..ce1f030be 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -21,6 +21,7 @@ bool cmIncludeCommand(std::vector<std::string> const& args,
static std::map<std::string, cmPolicies::PolicyID> DeprecatedModules;
if (DeprecatedModules.empty()) {
DeprecatedModules["Documentation"] = cmPolicies::CMP0106;
+ DeprecatedModules["WriteCompilerDetectionHeader"] = cmPolicies::CMP0120;
}
if (args.empty() || args.size() > 4) {
@@ -146,11 +147,24 @@ bool cmIncludeCommand(std::vector<std::string> const& args,
std::string listFile = cmSystemTools::CollapseFullPath(
fname, status.GetMakefile().GetCurrentSourceDirectory());
- if (optional && !cmSystemTools::FileExists(listFile)) {
+
+ const bool fileDoesnotExist = !cmSystemTools::FileExists(listFile);
+ const bool fileIsDirectory = cmSystemTools::FileIsDirectory(listFile);
+ if (fileDoesnotExist || fileIsDirectory) {
if (!resultVarName.empty()) {
status.GetMakefile().AddDefinition(resultVarName, "NOTFOUND");
}
- return true;
+ if (optional) {
+ return true;
+ }
+ if (fileDoesnotExist) {
+ status.SetError(cmStrCat("could not find requested file:\n ", fname));
+ return false;
+ }
+ if (fileIsDirectory) {
+ status.SetError(cmStrCat("requested file is a directory:\n ", fname));
+ return false;
+ }
}
bool readit =
@@ -163,9 +177,7 @@ bool cmIncludeCommand(std::vector<std::string> const& args,
}
if (!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) {
- std::string m = cmStrCat("could not find load file:\n"
- " ",
- fname);
+ std::string m = cmStrCat("could not load requested file:\n ", fname);
status.SetError(m);
return false;
}
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index ff08ee41e..7788db3bb 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -57,28 +57,38 @@ public:
bool MakeFilesFullPath(const char* modeName,
const std::vector<std::string>& relFiles,
std::vector<std::string>& absFiles);
- bool CheckCMP0006(bool& failure);
+ bool CheckCMP0006(bool& failure) const;
std::string GetDestination(const cmInstallCommandArguments* args,
const std::string& varName,
- const std::string& guess);
- std::string GetRuntimeDestination(const cmInstallCommandArguments* args);
- std::string GetSbinDestination(const cmInstallCommandArguments* args);
- std::string GetArchiveDestination(const cmInstallCommandArguments* args);
- std::string GetLibraryDestination(const cmInstallCommandArguments* args);
- std::string GetIncludeDestination(const cmInstallCommandArguments* args);
- std::string GetSysconfDestination(const cmInstallCommandArguments* args);
- std::string GetSharedStateDestination(const cmInstallCommandArguments* args);
- std::string GetLocalStateDestination(const cmInstallCommandArguments* args);
- std::string GetRunStateDestination(const cmInstallCommandArguments* args);
- std::string GetDataRootDestination(const cmInstallCommandArguments* args);
- std::string GetDataDestination(const cmInstallCommandArguments* args);
- std::string GetInfoDestination(const cmInstallCommandArguments* args);
- std::string GetLocaleDestination(const cmInstallCommandArguments* args);
- std::string GetManDestination(const cmInstallCommandArguments* args);
- std::string GetDocDestination(const cmInstallCommandArguments* args);
+ const std::string& guess) const;
+ std::string GetRuntimeDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetSbinDestination(const cmInstallCommandArguments* args) const;
+ std::string GetArchiveDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetLibraryDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetIncludeDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetSysconfDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetSharedStateDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetLocalStateDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetRunStateDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetDataRootDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetDataDestination(const cmInstallCommandArguments* args) const;
+ std::string GetInfoDestination(const cmInstallCommandArguments* args) const;
+ std::string GetLocaleDestination(
+ const cmInstallCommandArguments* args) const;
+ std::string GetManDestination(const cmInstallCommandArguments* args) const;
+ std::string GetDocDestination(const cmInstallCommandArguments* args) const;
std::string GetDestinationForType(const cmInstallCommandArguments* args,
- const std::string& type);
+ const std::string& type) const;
cmExecutionStatus& Status;
cmMakefile* Makefile;
@@ -123,7 +133,8 @@ std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
return cm::make_unique<cmInstallFilesGenerator>(
absFiles, destination, programs, args.GetPermissions(),
args.GetConfigurations(), args.GetComponent(), message,
- args.GetExcludeFromAll(), args.GetRename(), args.GetOptional());
+ args.GetExcludeFromAll(), args.GetRename(), args.GetOptional(),
+ mf->GetBacktrace());
}
std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
@@ -196,14 +207,16 @@ bool HandleScriptMode(std::vector<std::string> const& args,
return false;
}
helper.Makefile->AddInstallGenerator(
- cm::make_unique<cmInstallScriptGenerator>(script, false, component,
- exclude_from_all));
+ cm::make_unique<cmInstallScriptGenerator>(
+ script, false, component, exclude_from_all,
+ 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));
+ cm::make_unique<cmInstallScriptGenerator>(
+ code, true, component, exclude_from_all,
+ helper.Makefile->GetBacktrace()));
}
}
@@ -1243,7 +1256,8 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallDirectoryGenerator>(
dirs, *destination, permissions_file, permissions_dir, configurations,
- component, message, exclude_from_all, literal_args, optional));
+ component, message, exclude_from_all, literal_args, optional,
+ helper.Makefile->GetBacktrace()));
// Tell the global generator about any installation component names
// specified.
@@ -1335,7 +1349,8 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
cm::make_unique<cmInstallExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
- ica.GetExcludeFromAll(), fname, name_space, exportOld, true));
+ ica.GetExcludeFromAll(), fname, name_space, exportOld, true,
+ helper.Makefile->GetBacktrace()));
return true;
#else
@@ -1448,7 +1463,8 @@ bool HandleExportMode(std::vector<std::string> const& args,
cm::make_unique<cmInstallExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
- ica.GetExcludeFromAll(), fname, name_space, exportOld, false));
+ ica.GetExcludeFromAll(), fname, name_space, exportOld, false,
+ helper.Makefile->GetBacktrace()));
return true;
}
@@ -1477,7 +1493,7 @@ bool Helper::MakeFilesFullPath(const char* modeName,
return true;
}
-bool Helper::CheckCMP0006(bool& failure)
+bool Helper::CheckCMP0006(bool& failure) const
{
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) {
case cmPolicies::WARN:
@@ -1504,7 +1520,7 @@ bool Helper::CheckCMP0006(bool& failure)
std::string Helper::GetDestination(const cmInstallCommandArguments* args,
const std::string& varName,
- const std::string& guess)
+ const std::string& guess) const
{
if (args && !args->GetDestination().empty()) {
return args->GetDestination();
@@ -1517,54 +1533,55 @@ std::string Helper::GetDestination(const cmInstallCommandArguments* args,
}
std::string Helper::GetRuntimeDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin");
}
-std::string Helper::GetSbinDestination(const cmInstallCommandArguments* args)
+std::string Helper::GetSbinDestination(
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin");
}
std::string Helper::GetArchiveDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
}
std::string Helper::GetLibraryDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
}
std::string Helper::GetIncludeDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include");
}
std::string Helper::GetSysconfDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc");
}
std::string Helper::GetSharedStateDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
}
std::string Helper::GetLocalStateDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
}
std::string Helper::GetRunStateDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR",
this->GetLocalStateDestination(nullptr) +
@@ -1572,44 +1589,49 @@ std::string Helper::GetRunStateDestination(
}
std::string Helper::GetDataRootDestination(
- const cmInstallCommandArguments* args)
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share");
}
-std::string Helper::GetDataDestination(const cmInstallCommandArguments* args)
+std::string Helper::GetDataDestination(
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_DATADIR",
this->GetDataRootDestination(nullptr));
}
-std::string Helper::GetInfoDestination(const cmInstallCommandArguments* args)
+std::string Helper::GetInfoDestination(
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_INFODIR",
this->GetDataRootDestination(nullptr) + "/info");
}
-std::string Helper::GetLocaleDestination(const cmInstallCommandArguments* args)
+std::string Helper::GetLocaleDestination(
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR",
this->GetDataRootDestination(nullptr) +
"/locale");
}
-std::string Helper::GetManDestination(const cmInstallCommandArguments* args)
+std::string Helper::GetManDestination(
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_MANDIR",
this->GetDataRootDestination(nullptr) + "/man");
}
-std::string Helper::GetDocDestination(const cmInstallCommandArguments* args)
+std::string Helper::GetDocDestination(
+ const cmInstallCommandArguments* args) const
{
return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR",
this->GetDataRootDestination(nullptr) + "/doc");
}
std::string Helper::GetDestinationForType(
- const cmInstallCommandArguments* args, const std::string& type)
+ const cmInstallCommandArguments* args, const std::string& type) const
{
if (args && !args->GetDestination().empty()) {
return args->GetDestination();
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index a034689c0..cc3df2abb 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommandArguments.h"
+#include <algorithm>
#include <utility>
#include <cmext/string_view>
@@ -176,13 +177,11 @@ bool cmInstallCommandArguments::Finalize()
bool cmInstallCommandArguments::CheckPermissions()
{
this->PermissionsString.clear();
- for (std::string const& perm : this->Permissions) {
- if (!cmInstallCommandArguments::CheckPermissions(
- perm, this->PermissionsString)) {
- return false;
- }
- }
- return true;
+ return std::all_of(this->Permissions.begin(), this->Permissions.end(),
+ [this](std::string const& perm) -> bool {
+ return cmInstallCommandArguments::CheckPermissions(
+ perm, this->PermissionsString);
+ });
}
bool cmInstallCommandArguments::CheckPermissions(
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index 175e7cf0b..4eb5f69e4 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -16,9 +16,9 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
std::string file_permissions, std::string dir_permissions,
std::vector<std::string> const& configurations, std::string const& component,
MessageLevel message, bool exclude_from_all, std::string literal_args,
- bool optional)
+ bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all)
+ exclude_from_all, std::move(backtrace))
, LocalGenerator(nullptr)
, Directories(dirs)
, FilePermissions(std::move(file_permissions))
@@ -27,7 +27,7 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
, Optional(optional)
{
// We need per-config actions if destination have generator expressions.
- if (cmGeneratorExpression::Find(Destination) != std::string::npos) {
+ if (cmGeneratorExpression::Find(this->Destination) != std::string::npos) {
this->ActionsPerConfig = true;
}
@@ -50,6 +50,22 @@ bool cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg)
return true;
}
+std::vector<std::string> cmInstallDirectoryGenerator::GetDirectories(
+ std::string const& config) const
+{
+ std::vector<std::string> directories;
+ if (this->ActionsPerConfig) {
+ for (std::string const& f : this->Directories) {
+ cmExpandList(
+ cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config),
+ directories);
+ }
+ } else {
+ directories = this->Directories;
+ }
+ return directories;
+}
+
void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
Indent indent)
{
@@ -63,11 +79,7 @@ void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
void cmInstallDirectoryGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent indent)
{
- std::vector<std::string> dirs;
- for (std::string const& d : this->Directories) {
- cmExpandList(
- cmGeneratorExpression::Evaluate(d, this->LocalGenerator, config), dirs);
- }
+ std::vector<std::string> dirs = this->GetDirectories(config);
// Make sure all dirs have absolute paths.
cmMakefile const& mf = *this->LocalGenerator->GetMakefile();
diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h
index af310f399..0f91a5996 100644
--- a/Source/cmInstallDirectoryGenerator.h
+++ b/Source/cmInstallDirectoryGenerator.h
@@ -9,6 +9,7 @@
#include <vector>
#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
#include "cmScriptGenerator.h"
class cmLocalGenerator;
@@ -19,19 +20,20 @@ class cmLocalGenerator;
class cmInstallDirectoryGenerator : public cmInstallGenerator
{
public:
- cmInstallDirectoryGenerator(std::vector<std::string> const& dirs,
- std::string const& dest,
- std::string file_permissions,
- std::string dir_permissions,
- std::vector<std::string> const& configurations,
- std::string const& component,
- MessageLevel message, bool exclude_from_all,
- std::string literal_args, bool optional = false);
+ cmInstallDirectoryGenerator(
+ std::vector<std::string> const& dirs, std::string const& dest,
+ std::string file_permissions, std::string dir_permissions,
+ std::vector<std::string> const& configurations,
+ std::string const& component, MessageLevel message, bool exclude_from_all,
+ std::string literal_args, bool optional, cmListFileBacktrace backtrace);
~cmInstallDirectoryGenerator() override;
bool Compute(cmLocalGenerator* lg) override;
std::string GetDestination(std::string const& config) const;
+ std::vector<std::string> GetDirectories(std::string const& config) const;
+
+ bool GetOptional() const { return this->Optional; }
protected:
void GenerateScriptActions(std::ostream& os, Indent indent) override;
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 6e3508c2d..fdc3f8c1a 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -23,9 +23,10 @@ cmInstallExportGenerator::cmInstallExportGenerator(
cmExportSet* exportSet, std::string const& destination,
std::string file_permissions, std::vector<std::string> const& configurations,
std::string const& component, MessageLevel message, bool exclude_from_all,
- std::string filename, std::string name_space, bool exportOld, bool android)
+ std::string filename, std::string name_space, bool exportOld, bool android,
+ cmListFileBacktrace backtrace)
: cmInstallGenerator(destination, configurations, component, message,
- exclude_from_all)
+ exclude_from_all, std::move(backtrace))
, ExportSet(exportSet)
, FilePermissions(std::move(file_permissions))
, FileName(std::move(filename))
@@ -122,10 +123,10 @@ size_t cmInstallExportGenerator::GetMaxConfigLength() const
void cmInstallExportGenerator::GenerateScript(std::ostream& os)
{
// Skip empty sets.
- if (ExportSet->GetTargetExports().empty()) {
+ if (this->ExportSet->GetTargetExports().empty()) {
std::ostringstream e;
- e << "INSTALL(EXPORT) given unknown export \"" << ExportSet->GetName()
- << "\"";
+ e << "INSTALL(EXPORT) given unknown export \""
+ << this->ExportSet->GetName() << "\"";
cmSystemTools::Error(e.str());
return;
}
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index dd8624bbd..efeae86ee 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -11,6 +11,7 @@
#include <vector>
#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
#include "cmScriptGenerator.h"
class cmExportInstallFileGenerator;
@@ -29,7 +30,7 @@ public:
std::string const& component, MessageLevel message,
bool exclude_from_all, std::string filename,
std::string name_space, bool exportOld,
- bool android);
+ bool android, cmListFileBacktrace backtrace);
cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
~cmInstallExportGenerator() override;
@@ -44,8 +45,11 @@ public:
const std::string& GetNamespace() const { return this->Namespace; }
+ std::string const& GetMainImportFile() const { return this->MainImportFile; }
+
std::string const& GetDestination() const { return this->Destination; }
std::string GetDestinationFile() const;
+ std::string GetFileName() const { return this->FileName; }
protected:
void GenerateScript(std::ostream& os) override;
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 3c59f0180..e65cb24a8 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -125,7 +125,7 @@ static void CreateInstallGenerator(cmMakefile& makefile,
cmInstallGenerator::SelectMessageLevel(&makefile);
makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>(
files, destination, false, no_permissions, no_configurations, no_component,
- message, no_exclude_from_all, no_rename));
+ message, no_exclude_from_all, no_rename, false, makefile.GetBacktrace()));
}
/**
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index ad2f84e02..556c93827 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -15,9 +15,9 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
bool programs, std::string file_permissions,
std::vector<std::string> const& configurations, std::string const& component,
MessageLevel message, bool exclude_from_all, std::string rename,
- bool optional)
+ bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
- exclude_from_all)
+ exclude_from_all, std::move(backtrace))
, LocalGenerator(nullptr)
, Files(files)
, FilePermissions(std::move(file_permissions))
@@ -25,8 +25,12 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
, Programs(programs)
, Optional(optional)
{
- // We need per-config actions if the destination has generator expressions.
- if (cmGeneratorExpression::Find(Destination) != std::string::npos) {
+ // We need per-config actions if the destination and rename have generator
+ // expressions.
+ if (cmGeneratorExpression::Find(this->Destination) != std::string::npos) {
+ this->ActionsPerConfig = true;
+ }
+ if (cmGeneratorExpression::Find(this->Rename) != std::string::npos) {
this->ActionsPerConfig = true;
}
@@ -56,6 +60,28 @@ std::string cmInstallFilesGenerator::GetDestination(
this->LocalGenerator, config);
}
+std::string cmInstallFilesGenerator::GetRename(std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(this->Rename, this->LocalGenerator,
+ config);
+}
+
+std::vector<std::string> cmInstallFilesGenerator::GetFiles(
+ std::string const& config) const
+{
+ std::vector<std::string> files;
+ if (this->ActionsPerConfig) {
+ for (std::string const& f : this->Files) {
+ cmExpandList(
+ cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config),
+ files);
+ }
+ } else {
+ files = this->Files;
+ }
+ return files;
+}
+
void cmInstallFilesGenerator::AddFilesInstallRule(
std::ostream& os, std::string const& config, Indent indent,
std::vector<std::string> const& files)
@@ -66,7 +92,7 @@ void cmInstallFilesGenerator::AddFilesInstallRule(
os, this->GetDestination(config),
(this->Programs ? cmInstallType_PROGRAMS : cmInstallType_FILES), files,
this->Optional, this->FilePermissions.c_str(), no_dir_permissions,
- this->Rename.c_str(), nullptr, indent);
+ this->GetRename(config).c_str(), nullptr, indent);
}
void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
@@ -82,10 +108,6 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
void cmInstallFilesGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent indent)
{
- std::vector<std::string> files;
- for (std::string const& f : this->Files) {
- cmExpandList(
- cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config), files);
- }
+ std::vector<std::string> files = this->GetFiles(config);
this->AddFilesInstallRule(os, config, indent, files);
}
diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h
index b5a1ef42a..af7f11356 100644
--- a/Source/cmInstallFilesGenerator.h
+++ b/Source/cmInstallFilesGenerator.h
@@ -9,6 +9,7 @@
#include <vector>
#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
#include "cmScriptGenerator.h"
class cmLocalGenerator;
@@ -25,12 +26,15 @@ public:
std::vector<std::string> const& configurations,
std::string const& component, MessageLevel message,
bool exclude_from_all, std::string rename,
- bool optional = false);
+ bool optional, cmListFileBacktrace backtrace);
~cmInstallFilesGenerator() override;
bool Compute(cmLocalGenerator* lg) override;
std::string GetDestination(std::string const& config) const;
+ std::string GetRename(std::string const& config) const;
+ std::vector<std::string> GetFiles(std::string const& config) const;
+ bool GetOptional() const { return this->Optional; }
protected:
void GenerateScriptActions(std::ostream& os, Indent indent) override;
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 0665895b7..98e37666d 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -10,12 +10,14 @@
cmInstallGenerator::cmInstallGenerator(
std::string destination, std::vector<std::string> const& configurations,
- std::string component, MessageLevel message, bool exclude_from_all)
+ std::string component, MessageLevel message, bool exclude_from_all,
+ cmListFileBacktrace backtrace)
: cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
, Destination(std::move(destination))
, Component(std::move(component))
, Message(message)
, ExcludeFromAll(exclude_from_all)
+ , Backtrace(std::move(backtrace))
{
}
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index ee55ee935..6cd9ff9bb 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -9,6 +9,7 @@
#include <vector>
#include "cmInstallType.h"
+#include "cmListFileCache.h"
#include "cmScriptGenerator.h"
class cmLocalGenerator;
@@ -32,7 +33,7 @@ public:
cmInstallGenerator(std::string destination,
std::vector<std::string> const& configurations,
std::string component, MessageLevel message,
- bool exclude_from_all);
+ bool exclude_from_all, cmListFileBacktrace backtrace);
~cmInstallGenerator() override;
cmInstallGenerator(cmInstallGenerator const&) = delete;
@@ -61,6 +62,12 @@ public:
virtual bool Compute(cmLocalGenerator*) { return true; }
+ std::string const& GetComponent() const { return this->Component; }
+
+ bool GetExcludeFromAll() const { return this->ExcludeFromAll; }
+
+ cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+
protected:
void GenerateScript(std::ostream& os) override;
@@ -72,4 +79,5 @@ protected:
std::string const Component;
MessageLevel const Message;
bool const ExcludeFromAll;
+ cmListFileBacktrace const Backtrace;
};
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index be07fd4d4..65b8d8994 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -99,7 +99,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& dest,
cmInstallGenerator::SelectMessageLevel(&makefile);
makefile.AddInstallGenerator(cm::make_unique<cmInstallFilesGenerator>(
files, destination, true, no_permissions, no_configurations, no_component,
- message, no_exclude_from_all, no_rename));
+ message, no_exclude_from_all, no_rename, false, makefile.GetBacktrace()));
}
/**
diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx
index 7cdf3b45b..bb389906a 100644
--- a/Source/cmInstallScriptGenerator.cxx
+++ b/Source/cmInstallScriptGenerator.cxx
@@ -14,15 +14,15 @@
cmInstallScriptGenerator::cmInstallScriptGenerator(
std::string script, bool code, std::string const& component,
- bool exclude_from_all)
+ bool exclude_from_all, cmListFileBacktrace backtrace)
: cmInstallGenerator("", std::vector<std::string>(), component,
- MessageDefault, exclude_from_all)
+ MessageDefault, exclude_from_all, std::move(backtrace))
, Script(std::move(script))
, Code(code)
, AllowGenex(false)
{
// We need per-config actions if the script has generator expressions.
- if (cmGeneratorExpression::Find(Script) != std::string::npos) {
+ if (cmGeneratorExpression::Find(this->Script) != std::string::npos) {
this->ActionsPerConfig = true;
}
}
@@ -53,9 +53,21 @@ bool cmInstallScriptGenerator::Compute(cmLocalGenerator* lg)
return true;
}
-void cmInstallScriptGenerator::AddScriptInstallRule(std::ostream& os,
- Indent indent,
- std::string const& script)
+std::string cmInstallScriptGenerator::GetScript(
+ std::string const& config) const
+{
+ std::string script;
+ if (this->AllowGenex && this->ActionsPerConfig) {
+ script = cmGeneratorExpression::Evaluate(this->Script,
+ this->LocalGenerator, config);
+ } else {
+ script = this->Script;
+ }
+ return script;
+}
+
+void cmInstallScriptGenerator::AddScriptInstallRule(
+ std::ostream& os, Indent indent, std::string const& script) const
{
if (this->Code) {
os << indent << script << "\n";
@@ -77,11 +89,5 @@ void cmInstallScriptGenerator::GenerateScriptActions(std::ostream& os,
void cmInstallScriptGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent indent)
{
- if (this->AllowGenex) {
- this->AddScriptInstallRule(os, indent,
- cmGeneratorExpression::Evaluate(
- this->Script, this->LocalGenerator, config));
- } else {
- this->AddScriptInstallRule(os, indent, this->Script);
- }
+ this->AddScriptInstallRule(os, indent, this->GetScript(config));
}
diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h
index 338d866ef..6274f1cd2 100644
--- a/Source/cmInstallScriptGenerator.h
+++ b/Source/cmInstallScriptGenerator.h
@@ -8,6 +8,7 @@
#include <string>
#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
#include "cmScriptGenerator.h"
class cmLocalGenerator;
@@ -18,19 +19,24 @@ class cmLocalGenerator;
class cmInstallScriptGenerator : public cmInstallGenerator
{
public:
- cmInstallScriptGenerator(std::string script, bool code,
- std::string const& component,
- bool exclude_from_all);
+ cmInstallScriptGenerator(
+ std::string script, bool code, std::string const& component,
+ bool exclude_from_all,
+ cmListFileBacktrace backtrace = cmListFileBacktrace());
~cmInstallScriptGenerator() override;
bool Compute(cmLocalGenerator* lg) override;
+ bool IsCode() const { return this->Code; }
+
+ std::string GetScript(std::string const& config) const;
+
protected:
void GenerateScriptActions(std::ostream& os, Indent indent) override;
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
Indent indent) override;
void AddScriptInstallRule(std::ostream& os, Indent indent,
- std::string const& script);
+ std::string const& script) const;
std::string const Script;
bool const Code;
diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx
index 12bc92bbf..76806e535 100644
--- a/Source/cmInstallSubdirectoryGenerator.cxx
+++ b/Source/cmInstallSubdirectoryGenerator.cxx
@@ -14,9 +14,10 @@
#include "cmSystemTools.h"
cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
- cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll)
+ cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll,
+ cmListFileBacktrace backtrace)
: cmInstallGenerator("", std::vector<std::string>(), "", MessageDefault,
- excludeFromAll)
+ excludeFromAll, std::move(backtrace))
, Makefile(makefile)
, BinaryDirectory(std::move(binaryDirectory))
{
diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h
index 3e46d6bbb..614cef921 100644
--- a/Source/cmInstallSubdirectoryGenerator.h
+++ b/Source/cmInstallSubdirectoryGenerator.h
@@ -8,6 +8,7 @@
#include <string>
#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
class cmLocalGenerator;
class cmMakefile;
@@ -20,7 +21,8 @@ class cmInstallSubdirectoryGenerator : public cmInstallGenerator
public:
cmInstallSubdirectoryGenerator(cmMakefile* makefile,
std::string binaryDirectory,
- bool excludeFromAll);
+ bool excludeFromAll,
+ cmListFileBacktrace backtrace);
~cmInstallSubdirectoryGenerator() override;
bool HaveInstall() override;
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index b3da202c1..bef785d0b 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -25,19 +25,33 @@
#include "cmTarget.h"
#include "cmake.h"
+namespace {
+std::string computeInstallObjectDir(cmGeneratorTarget* gt,
+ std::string const& config)
+{
+ std::string objectDir = "objects";
+ if (!config.empty()) {
+ objectDir += "-";
+ objectDir += config;
+ }
+ objectDir += "/";
+ objectDir += gt->GetName();
+ return objectDir;
+}
+}
+
cmInstallTargetGenerator::cmInstallTargetGenerator(
std::string targetName, std::string const& dest, bool implib,
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)
+ exclude_from_all, std::move(backtrace))
, TargetName(std::move(targetName))
, Target(nullptr)
, FilePermissions(std::move(file_permissions))
, ImportLibrary(implib)
, Optional(optional)
- , Backtrace(std::move(backtrace))
{
this->ActionsPerConfig = true;
this->NamelinkMode = NamelinkModeNone;
@@ -48,20 +62,69 @@ cmInstallTargetGenerator::~cmInstallTargetGenerator() = default;
void cmInstallTargetGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent indent)
{
+ // Compute the list of files to install for this target.
+ Files files = this->GetFiles(config);
+
+ // Skip this rule if no files are to be installed for the target.
+ if (files.From.empty()) {
+ return;
+ }
+
+ // Compute the effective install destination.
+ std::string dest = this->GetDestination(config);
+ if (!files.ToDir.empty()) {
+ dest = cmStrCat(dest, '/', files.ToDir);
+ }
+
+ // Tweak files located in the destination directory.
+ std::string toDir = cmStrCat(this->ConvertToAbsoluteDestination(dest), '/');
+
+ // Add pre-installation tweaks.
+ if (!files.NoTweak) {
+ this->AddTweak(os, indent, config, toDir, files.To,
+ &cmInstallTargetGenerator::PreReplacementTweaks);
+ }
+
+ // Write code to install the target file.
+ const char* no_dir_permissions = nullptr;
+ const char* no_rename = nullptr;
+ bool optional = this->Optional || this->ImportLibrary;
+ std::string literal_args;
+ if (!files.FromDir.empty()) {
+ literal_args += " FILES_FROM_DIR \"" + files.FromDir + "\"";
+ }
+ if (files.UseSourcePermissions) {
+ literal_args += " USE_SOURCE_PERMISSIONS";
+ }
+ this->AddInstallRule(os, dest, files.Type, files.From, optional,
+ this->FilePermissions.c_str(), no_dir_permissions,
+ no_rename, literal_args.c_str(), indent);
+
+ // Add post-installation tweaks.
+ if (!files.NoTweak) {
+ this->AddTweak(os, indent, config, toDir, files.To,
+ &cmInstallTargetGenerator::PostReplacementTweaks);
+ }
+}
+
+cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
+ std::string const& config) const
+{
+ Files files;
+
cmStateEnums::TargetType targetType = this->Target->GetType();
- cmInstallType type = cmInstallType();
switch (targetType) {
case cmStateEnums::EXECUTABLE:
- type = cmInstallType_EXECUTABLE;
+ files.Type = cmInstallType_EXECUTABLE;
break;
case cmStateEnums::STATIC_LIBRARY:
- type = cmInstallType_STATIC_LIBRARY;
+ files.Type = cmInstallType_STATIC_LIBRARY;
break;
case cmStateEnums::SHARED_LIBRARY:
- type = cmInstallType_SHARED_LIBRARY;
+ files.Type = cmInstallType_SHARED_LIBRARY;
break;
case cmStateEnums::MODULE_LIBRARY:
- type = cmInstallType_MODULE_LIBRARY;
+ files.Type = cmInstallType_MODULE_LIBRARY;
break;
case cmStateEnums::INTERFACE_LIBRARY:
// Not reachable. We never create a cmInstallTargetGenerator for
@@ -70,9 +133,21 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
"INTERFACE_LIBRARY targets have no installable outputs.");
break;
- case cmStateEnums::OBJECT_LIBRARY:
- this->GenerateScriptForConfigObjectLibrary(os, config, indent);
- return;
+ case cmStateEnums::OBJECT_LIBRARY: {
+ // Compute all the object files inside this target
+ std::vector<std::string> objects;
+ this->Target->GetTargetObjectNames(config, objects);
+
+ files.Type = cmInstallType_FILES;
+ files.NoTweak = true;
+ files.FromDir = this->Target->GetObjectDirectory(config);
+ files.ToDir = computeInstallObjectDir(this->Target, config);
+ for (std::string& obj : objects) {
+ files.From.emplace_back(obj);
+ files.To.emplace_back(std::move(obj));
+ }
+ return files;
+ }
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
@@ -80,7 +155,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
this->Target->GetLocalGenerator()->IssueMessage(
MessageType::INTERNAL_ERROR,
"cmInstallTargetGenerator created with non-installable target.");
- return;
+ return files;
}
// Compute the build tree directory from which to copy the target.
@@ -97,14 +172,6 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
cmStrCat(this->Target->GetDirectory(config, artifact), '/');
}
- std::string toDir = cmStrCat(
- this->ConvertToAbsoluteDestination(this->GetDestination(config)), '/');
-
- // Compute the list of files to install for this target.
- std::vector<std::string> filesFrom;
- std::vector<std::string> filesTo;
- std::string literal_args;
-
if (targetType == cmStateEnums::EXECUTABLE) {
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
@@ -113,21 +180,21 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
this->Target->GetExecutableNames(config);
if (this->ImportLibrary) {
std::string from1 = fromDirConfig + targetNames.ImportLibrary;
- std::string to1 = toDir + targetNames.ImportLibrary;
- filesFrom.push_back(std::move(from1));
- filesTo.push_back(std::move(to1));
+ std::string to1 = targetNames.ImportLibrary;
+ files.From.emplace_back(std::move(from1));
+ files.To.emplace_back(std::move(to1));
std::string targetNameImportLib;
if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
targetNameImportLib)) {
- filesFrom.push_back(fromDirConfig + targetNameImportLib);
- filesTo.push_back(toDir + targetNameImportLib);
+ files.From.emplace_back(fromDirConfig + targetNameImportLib);
+ files.To.emplace_back(targetNameImportLib);
}
// An import library looks like a static library.
- type = cmInstallType_STATIC_LIBRARY;
+ files.Type = cmInstallType_STATIC_LIBRARY;
} else {
std::string from1 = fromDirConfig + targetNames.Output;
- std::string to1 = toDir + targetNames.Output;
+ std::string to1 = targetNames.Output;
// Handle OSX Bundles.
if (this->Target->IsAppBundleOnApple()) {
@@ -142,8 +209,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
}
// Install the whole app bundle directory.
- type = cmInstallType_DIRECTORY;
- literal_args += " USE_SOURCE_PERMISSIONS";
+ files.Type = cmInstallType_DIRECTORY;
+ files.UseSourcePermissions = true;
from1 += ".";
from1 += ext;
@@ -159,14 +226,14 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// Tweaks apply to the real file, so list it first.
if (targetNames.Real != targetNames.Output) {
std::string from2 = fromDirConfig + targetNames.Real;
- std::string to2 = toDir += targetNames.Real;
- filesFrom.push_back(std::move(from2));
- filesTo.push_back(std::move(to2));
+ std::string to2 = targetNames.Real;
+ files.From.emplace_back(std::move(from2));
+ files.To.emplace_back(std::move(to2));
}
}
- filesFrom.push_back(std::move(from1));
- filesTo.push_back(std::move(to1));
+ files.From.emplace_back(std::move(from1));
+ files.To.emplace_back(std::move(to1));
}
} else {
cmGeneratorTarget::Names targetNames =
@@ -176,18 +243,18 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
assert(this->NamelinkMode == NamelinkModeNone);
std::string from1 = fromDirConfig + targetNames.ImportLibrary;
- std::string to1 = toDir + targetNames.ImportLibrary;
- filesFrom.push_back(std::move(from1));
- filesTo.push_back(std::move(to1));
+ std::string to1 = targetNames.ImportLibrary;
+ files.From.emplace_back(std::move(from1));
+ files.To.emplace_back(std::move(to1));
std::string targetNameImportLib;
if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
targetNameImportLib)) {
- filesFrom.push_back(fromDirConfig + targetNameImportLib);
- filesTo.push_back(toDir + targetNameImportLib);
+ files.From.emplace_back(fromDirConfig + targetNameImportLib);
+ files.To.emplace_back(targetNameImportLib);
}
// An import library looks like a static library.
- type = cmInstallType_STATIC_LIBRARY;
+ files.Type = cmInstallType_STATIC_LIBRARY;
} else if (this->Target->IsFrameworkOnApple()) {
// FIXME: In principle we should be able to
// assert(this->NamelinkMode == NamelinkModeNone);
@@ -207,7 +274,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
break;
case NamelinkModeOnly:
// Assume the NamelinkModeSkip instance will warn and install.
- return;
+ return files;
case NamelinkModeSkip: {
std::string e = "Target '" + this->Target->GetName() +
"' was changed to a FRAMEWORK sometime after install(). "
@@ -219,36 +286,36 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
}
// Install the whole framework directory.
- type = cmInstallType_DIRECTORY;
- literal_args += " USE_SOURCE_PERMISSIONS";
+ files.Type = cmInstallType_DIRECTORY;
+ files.UseSourcePermissions = true;
std::string from1 = fromDirConfig + targetNames.Output;
from1 = cmSystemTools::GetFilenamePath(from1);
// Tweaks apply to the binary inside the bundle.
- std::string to1 = toDir + targetNames.Real;
+ std::string to1 = targetNames.Real;
- filesFrom.push_back(std::move(from1));
- filesTo.push_back(std::move(to1));
+ files.From.emplace_back(std::move(from1));
+ files.To.emplace_back(std::move(to1));
} else if (this->Target->IsCFBundleOnApple()) {
// Install the whole app bundle directory.
- type = cmInstallType_DIRECTORY;
- literal_args += " USE_SOURCE_PERMISSIONS";
+ files.Type = cmInstallType_DIRECTORY;
+ files.UseSourcePermissions = true;
std::string targetNameBase =
targetNames.Output.substr(0, targetNames.Output.find('/'));
std::string from1 = fromDirConfig + targetNameBase;
- std::string to1 = toDir + targetNames.Output;
+ std::string to1 = targetNames.Output;
- filesFrom.push_back(std::move(from1));
- filesTo.push_back(std::move(to1));
+ files.From.emplace_back(std::move(from1));
+ files.To.emplace_back(std::move(to1));
} else {
bool haveNamelink = false;
// Library link name.
std::string fromName = fromDirConfig + targetNames.Output;
- std::string toName = toDir + targetNames.Output;
+ std::string toName = targetNames.Output;
// Library interface name.
std::string fromSOName;
@@ -256,7 +323,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
if (targetNames.SharedObject != targetNames.Output) {
haveNamelink = true;
fromSOName = fromDirConfig + targetNames.SharedObject;
- toSOName = toDir + targetNames.SharedObject;
+ toSOName = targetNames.SharedObject;
}
// Library implementation name.
@@ -266,7 +333,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
targetNames.Real != targetNames.SharedObject) {
haveNamelink = true;
fromRealName = fromDirConfig + targetNames.Real;
- toRealName = toDir + targetNames.Real;
+ toRealName = targetNames.Real;
}
// Add the names based on the current namelink mode.
@@ -274,95 +341,42 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// With a namelink we need to check the mode.
if (this->NamelinkMode == NamelinkModeOnly) {
// Install the namelink only.
- filesFrom.push_back(fromName);
- filesTo.push_back(toName);
+ files.From.emplace_back(fromName);
+ files.To.emplace_back(toName);
} else {
// Install the real file if it has its own name.
if (!fromRealName.empty()) {
- filesFrom.push_back(fromRealName);
- filesTo.push_back(toRealName);
+ files.From.emplace_back(fromRealName);
+ files.To.emplace_back(toRealName);
}
// Install the soname link if it has its own name.
if (!fromSOName.empty()) {
- filesFrom.push_back(fromSOName);
- filesTo.push_back(toSOName);
+ files.From.emplace_back(fromSOName);
+ files.To.emplace_back(toSOName);
}
// Install the namelink if it is not to be skipped.
if (this->NamelinkMode != NamelinkModeSkip) {
- filesFrom.push_back(fromName);
- filesTo.push_back(toName);
+ files.From.emplace_back(fromName);
+ files.To.emplace_back(toName);
}
}
} else {
// Without a namelink there will be only one file. Install it
// if this is not a namelink-only rule.
if (this->NamelinkMode != NamelinkModeOnly) {
- filesFrom.push_back(fromName);
- filesTo.push_back(toName);
+ files.From.emplace_back(fromName);
+ files.To.emplace_back(toName);
}
}
}
}
// If this fails the above code is buggy.
- assert(filesFrom.size() == filesTo.size());
-
- // Skip this rule if no files are to be installed for the target.
- if (filesFrom.empty()) {
- return;
- }
-
- // Add pre-installation tweaks.
- this->AddTweak(os, indent, config, filesTo,
- &cmInstallTargetGenerator::PreReplacementTweaks);
-
- // Write code to install the target file.
- const char* no_dir_permissions = nullptr;
- const char* no_rename = nullptr;
- bool optional = this->Optional || this->ImportLibrary;
- this->AddInstallRule(os, this->GetDestination(config), type, filesFrom,
- optional, this->FilePermissions.c_str(),
- no_dir_permissions, no_rename, literal_args.c_str(),
- indent);
-
- // Add post-installation tweaks.
- this->AddTweak(os, indent, config, filesTo,
- &cmInstallTargetGenerator::PostReplacementTweaks);
-}
+ assert(files.From.size() == files.To.size());
-static std::string computeInstallObjectDir(cmGeneratorTarget* gt,
- std::string const& config)
-{
- std::string objectDir = "objects";
- if (!config.empty()) {
- objectDir += "-";
- objectDir += config;
- }
- objectDir += "/";
- objectDir += gt->GetName();
- return objectDir;
-}
-
-void cmInstallTargetGenerator::GenerateScriptForConfigObjectLibrary(
- std::ostream& os, const std::string& config, Indent indent)
-{
- // Compute all the object files inside this target
- std::vector<std::string> objects;
- this->Target->GetTargetObjectNames(config, objects);
-
- std::string const dest = this->GetDestination(config) + "/" +
- computeInstallObjectDir(this->Target, config);
-
- std::string const obj_dir = this->Target->GetObjectDirectory(config);
- std::string const literal_args = " FILES_FROM_DIR \"" + obj_dir + "\"";
-
- const char* no_dir_permissions = nullptr;
- const char* no_rename = nullptr;
- this->AddInstallRule(os, dest, cmInstallType_FILES, objects, this->Optional,
- this->FilePermissions.c_str(), no_dir_permissions,
- no_rename, literal_args.c_str(), indent);
+ return files;
}
void cmInstallTargetGenerator::GetInstallObjectNames(
@@ -464,12 +478,14 @@ void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
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(files[0]), tweak);
+ this->AddTweak(os, indent, config,
+ this->GetDestDirPath(cmStrCat(dir, files[0])), tweak);
} else {
// Generate a foreach loop to tweak multiple files.
std::ostringstream tw;
@@ -479,7 +495,8 @@ void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
Indent indent2 = indent.Next().Next();
os << indent << "foreach(file\n";
for (std::string const& f : files) {
- os << indent2 << "\"" << this->GetDestDirPath(f) << "\"\n";
+ os << indent2 << "\"" << this->GetDestDirPath(cmStrCat(dir, f))
+ << "\"\n";
}
os << indent2 << ")\n";
os << tws;
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index a53a75a28..8c5d44410 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -9,6 +9,7 @@
#include <vector>
#include "cmInstallGenerator.h"
+#include "cmInstallType.h"
#include "cmListFileCache.h"
#include "cmScriptGenerator.h"
@@ -65,21 +66,41 @@ public:
std::string GetDestination(std::string const& config) const;
- cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+ struct Files
+ {
+ // Names or paths of files to be read from the source or build tree.
+ // The paths may be computed as [FromDir/] + From[i].
+ std::vector<std::string> From;
+
+ // Corresponding names of files to be written in the install directory.
+ // The paths may be computed as Destination/ + [ToDir/] + To[i].
+ std::vector<std::string> To;
+
+ // Prefix for all files in From.
+ std::string FromDir;
+
+ // Prefix for all files in To.
+ std::string ToDir;
+
+ bool NoTweak = false;
+ bool UseSourcePermissions = false;
+ cmInstallType Type = cmInstallType();
+ };
+ Files GetFiles(std::string const& config) const;
+
+ bool GetOptional() const { return this->Optional; }
protected:
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
Indent indent) override;
- void GenerateScriptForConfigObjectLibrary(std::ostream& os,
- const std::string& config,
- Indent indent);
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::vector<std::string> const& files, TweakMethod tweak);
+ 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,
@@ -111,5 +132,4 @@ protected:
NamelinkModeType NamelinkMode;
bool const ImportLibrary;
bool const Optional;
- cmListFileBacktrace const Backtrace;
};
diff --git a/Source/cmJsonObjectDictionary.h b/Source/cmJsonObjectDictionary.h
deleted file mode 100644
index 8a2b52995..000000000
--- a/Source/cmJsonObjectDictionary.h
+++ /dev/null
@@ -1,45 +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 <string>
-
-// Vocabulary:
-
-static const std::string kARTIFACTS_KEY = "artifacts";
-static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
-static const std::string kCOMPILE_FLAGS_KEY = "compileFlags";
-static const std::string kCONFIGURATIONS_KEY = "configurations";
-static const std::string kDEFINES_KEY = "defines";
-static const std::string kFILE_GROUPS_KEY = "fileGroups";
-static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath";
-static const std::string kFULL_NAME_KEY = "fullName";
-static const std::string kINCLUDE_PATH_KEY = "includePath";
-static const std::string kIS_CMAKE_KEY = "isCMake";
-static const std::string kIS_GENERATED_KEY = "isGenerated";
-static const std::string kIS_SYSTEM_KEY = "isSystem";
-static const std::string kIS_TEMPORARY_KEY = "isTemporary";
-static const std::string kKEY_KEY = "key";
-static const std::string kLANGUAGE_KEY = "language";
-static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage";
-static const std::string kLINK_FLAGS_KEY = "linkFlags";
-static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags";
-static const std::string kLINK_LIBRARIES_KEY = "linkLibraries";
-static const std::string kLINK_PATH_KEY = "linkPath";
-static const std::string kNAME_KEY = "name";
-static const std::string kPATH_KEY = "path";
-static const std::string kPROJECTS_KEY = "projects";
-static const std::string kPROPERTIES_KEY = "properties";
-static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
-static const std::string kSOURCES_KEY = "sources";
-static const std::string kSYSROOT_KEY = "sysroot";
-static const std::string kTARGETS_KEY = "targets";
-static const std::string kTYPE_KEY = "type";
-static const std::string kVALUE_KEY = "value";
-static const std::string kHAS_INSTALL_RULE = "hasInstallRule";
-static const std::string kINSTALL_PATHS = "installPaths";
-static const std::string kCTEST_NAME = "ctestName";
-static const std::string kCTEST_COMMAND = "ctestCommand";
-static const std::string kCTEST_INFO = "ctestInfo";
-static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion";
-static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided";
diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx
deleted file mode 100644
index 3a7ae0cd3..000000000
--- a/Source/cmJsonObjects.cxx
+++ /dev/null
@@ -1,692 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmJsonObjects.h" // IWYU pragma: keep
-
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <functional>
-#include <limits>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <cmext/algorithm>
-
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
-#include "cmInstallGenerator.h"
-#include "cmInstallSubdirectoryGenerator.h"
-#include "cmInstallTargetGenerator.h"
-#include "cmJsonObjectDictionary.h"
-#include "cmJsonObjects.h"
-#include "cmLinkLineComputer.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmProperty.h"
-#include "cmPropertyMap.h"
-#include "cmSourceFile.h"
-#include "cmState.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
-#include "cmStateTypes.h"
-#include "cmStringAlgorithms.h"
-#include "cmSystemTools.h"
-#include "cmTarget.h"
-#include "cmTest.h"
-#include "cmake.h"
-
-namespace {
-
-std::vector<std::string> getConfigurations(const cmake* cm)
-{
- std::vector<std::string> configurations;
- const auto& makefiles = cm->GetGlobalGenerator()->GetMakefiles();
- if (makefiles.empty()) {
- return configurations;
- }
-
- return makefiles[0]->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
-}
-
-bool hasString(const Json::Value& v, const std::string& s)
-{
- return !v.isNull() &&
- std::any_of(v.begin(), v.end(),
- [s](const Json::Value& i) { return i.asString() == s; });
-}
-
-template <class T>
-Json::Value fromStringList(const T& in)
-{
- Json::Value result = Json::arrayValue;
- for (std::string const& i : in) {
- result.append(i);
- }
- return result;
-}
-
-} // namespace
-
-void cmGetCMakeInputs(const cmGlobalGenerator* gg,
- const std::string& sourceDir,
- const std::string& buildDir,
- std::vector<std::string>* internalFiles,
- std::vector<std::string>* explicitFiles,
- std::vector<std::string>* tmpFiles)
-{
- const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/';
- auto const& makefiles = gg->GetMakefiles();
- for (const auto& mf : makefiles) {
- for (std::string const& lf : mf->GetListFiles()) {
-
- const std::string startOfFile = lf.substr(0, cmakeRootDir.size());
- const bool isInternal = (startOfFile == cmakeRootDir);
- const bool isTemporary =
- !isInternal && (cmHasPrefix(lf, buildDir + '/'));
-
- std::string toAdd = lf;
- if (!sourceDir.empty()) {
- const std::string& relative =
- cmSystemTools::RelativePath(sourceDir, lf);
- if (toAdd.size() > relative.size()) {
- toAdd = relative;
- }
- }
-
- if (isInternal) {
- if (internalFiles) {
- internalFiles->push_back(std::move(toAdd));
- }
- } else {
- if (isTemporary) {
- if (tmpFiles) {
- tmpFiles->push_back(std::move(toAdd));
- }
- } else {
- if (explicitFiles) {
- explicitFiles->push_back(std::move(toAdd));
- }
- }
- }
- }
- }
-}
-
-Json::Value cmDumpCMakeInputs(const cmake* cm)
-{
- const cmGlobalGenerator* gg = cm->GetGlobalGenerator();
- const std::string& buildDir = cm->GetHomeOutputDirectory();
- const std::string& sourceDir = cm->GetHomeDirectory();
-
- std::vector<std::string> internalFiles;
- std::vector<std::string> explicitFiles;
- std::vector<std::string> tmpFiles;
- cmGetCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles,
- &tmpFiles);
-
- Json::Value array = Json::arrayValue;
-
- Json::Value tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = true;
- tmp[kIS_TEMPORARY_KEY] = false;
- tmp[kSOURCES_KEY] = fromStringList(internalFiles);
- array.append(tmp);
-
- tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = false;
- tmp[kIS_TEMPORARY_KEY] = false;
- tmp[kSOURCES_KEY] = fromStringList(explicitFiles);
- array.append(tmp);
-
- tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = false;
- tmp[kIS_TEMPORARY_KEY] = true;
- tmp[kSOURCES_KEY] = fromStringList(tmpFiles);
- array.append(tmp);
-
- return array;
-}
-
-class LanguageData
-{
-public:
- bool operator==(const LanguageData& other) const;
-
- void SetDefines(const std::set<std::string>& defines);
-
- bool IsGenerated = false;
- std::string Language;
- std::string Flags;
- std::vector<std::string> Defines;
- std::vector<std::pair<std::string, bool>> IncludePathList;
-};
-
-bool LanguageData::operator==(const LanguageData& other) const
-{
- return Language == other.Language && Defines == other.Defines &&
- Flags == other.Flags && IncludePathList == other.IncludePathList &&
- IsGenerated == other.IsGenerated;
-}
-
-void LanguageData::SetDefines(const std::set<std::string>& defines)
-{
- std::vector<std::string> result;
- result.reserve(defines.size());
- for (std::string const& i : defines) {
- result.push_back(i);
- }
- std::sort(result.begin(), result.end());
- Defines = std::move(result);
-}
-
-namespace std {
-
-template <>
-struct hash<LanguageData>
-{
- std::size_t operator()(const LanguageData& in) const
- {
- using std::hash;
- size_t result =
- hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
- for (auto const& i : in.IncludePathList) {
- result = result ^
- (hash<std::string>()(i.first) ^
- (i.second ? std::numeric_limits<size_t>::max() : 0));
- }
- for (auto const& i : in.Defines) {
- result = result ^ hash<std::string>()(i);
- }
- result =
- result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0);
- return result;
- }
-};
-
-} // namespace std
-
-static Json::Value DumpSourceFileGroup(const LanguageData& data,
- const std::vector<std::string>& files,
- const std::string& baseDir)
-{
- Json::Value result = Json::objectValue;
-
- if (!data.Language.empty()) {
- result[kLANGUAGE_KEY] = data.Language;
- if (!data.Flags.empty()) {
- result[kCOMPILE_FLAGS_KEY] = data.Flags;
- }
- if (!data.IncludePathList.empty()) {
- Json::Value includes = Json::arrayValue;
- for (auto const& i : data.IncludePathList) {
- Json::Value tmp = Json::objectValue;
- tmp[kPATH_KEY] = i.first;
- if (i.second) {
- tmp[kIS_SYSTEM_KEY] = i.second;
- }
- includes.append(tmp);
- }
- result[kINCLUDE_PATH_KEY] = includes;
- }
- if (!data.Defines.empty()) {
- result[kDEFINES_KEY] = fromStringList(data.Defines);
- }
- }
-
- result[kIS_GENERATED_KEY] = data.IsGenerated;
-
- Json::Value sourcesValue = Json::arrayValue;
- for (auto const& i : files) {
- const std::string relPath = cmSystemTools::RelativePath(baseDir, i);
- sourcesValue.append(relPath.size() < i.size() ? relPath : i);
- }
-
- result[kSOURCES_KEY] = sourcesValue;
- return result;
-}
-
-static Json::Value DumpSourceFilesList(
- cmGeneratorTarget* target, const std::string& config,
- const std::map<std::string, LanguageData>& languageDataMap)
-{
- // Collect sourcefile groups:
-
- std::vector<cmSourceFile*> files;
- target->GetSourceFiles(files, config);
-
- std::unordered_map<LanguageData, std::vector<std::string>> fileGroups;
- for (cmSourceFile* file : files) {
- LanguageData fileData;
- fileData.Language = file->GetOrDetermineLanguage();
- if (!fileData.Language.empty()) {
- const LanguageData& ld = languageDataMap.at(fileData.Language);
- cmLocalGenerator* lg = target->GetLocalGenerator();
- cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
- fileData.Language);
-
- std::string compileFlags = ld.Flags;
- const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (cmProp cflags = file->GetProperty(COMPILE_FLAGS)) {
- lg->AppendFlags(compileFlags,
- genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
- }
- const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
- if (cmProp coptions = file->GetProperty(COMPILE_OPTIONS)) {
- lg->AppendCompileOptions(
- compileFlags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
- }
- fileData.Flags = compileFlags;
-
- // Add include directories from source file properties.
- std::vector<std::string> includes;
-
- const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
- if (cmProp cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) {
- const std::string& evaluatedIncludes =
- genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES);
- lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file);
-
- for (const auto& include : includes) {
- fileData.IncludePathList.emplace_back(
- include,
- target->IsSystemIncludeDirectory(include, config,
- fileData.Language));
- }
- }
-
- fileData.IncludePathList.insert(fileData.IncludePathList.end(),
- ld.IncludePathList.begin(),
- ld.IncludePathList.end());
-
- const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
- std::set<std::string> defines;
- if (cmProp defs = file->GetProperty(COMPILE_DEFINITIONS)) {
- lg->AppendDefines(
- defines, genexInterpreter.Evaluate(*defs, COMPILE_DEFINITIONS));
- }
-
- const std::string defPropName =
- "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
- if (cmProp config_defs = file->GetProperty(defPropName)) {
- lg->AppendDefines(
- defines,
- genexInterpreter.Evaluate(*config_defs, COMPILE_DEFINITIONS));
- }
-
- defines.insert(ld.Defines.begin(), ld.Defines.end());
-
- fileData.SetDefines(defines);
- }
-
- fileData.IsGenerated = file->GetIsGenerated();
- std::vector<std::string>& groupFileList = fileGroups[fileData];
- groupFileList.push_back(file->ResolveFullPath());
- }
-
- const std::string& baseDir = target->Makefile->GetCurrentSourceDirectory();
- Json::Value result = Json::arrayValue;
- for (auto const& it : fileGroups) {
- Json::Value group = DumpSourceFileGroup(it.first, it.second, baseDir);
- if (!group.isNull()) {
- result.append(group);
- }
- }
-
- return result;
-}
-
-static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo,
- const std::string& config)
-{
- Json::Value result = Json::objectValue;
- result[kCTEST_NAME] = testInfo->GetName();
-
- // Concat command entries together. After the first should be the arguments
- // for the command
- std::string command;
- for (auto const& cmd : testInfo->GetCommand()) {
- command.append(cmd);
- command.append(" ");
- }
-
- // Remove any config specific variables from the output.
- result[kCTEST_COMMAND] =
- cmGeneratorExpression::Evaluate(command, lg, config);
-
- // Build up the list of properties that may have been specified
- Json::Value properties = Json::arrayValue;
- for (auto& prop : testInfo->GetProperties().GetList()) {
- Json::Value entry = Json::objectValue;
- entry[kKEY_KEY] = prop.first;
-
- // Remove config variables from the value too.
- entry[kVALUE_KEY] =
- cmGeneratorExpression::Evaluate(prop.second, lg, config);
- properties.append(entry);
- }
- result[kPROPERTIES_KEY] = properties;
-
- return result;
-}
-
-static void DumpMakefileTests(cmLocalGenerator* lg, const std::string& config,
- Json::Value* result)
-{
- auto mf = lg->GetMakefile();
- std::vector<cmTest*> tests;
- mf->GetTests(config, tests);
- for (auto test : tests) {
- Json::Value tmp = DumpCTestInfo(lg, test, config);
- if (!tmp.isNull()) {
- result->append(tmp);
- }
- }
-}
-
-static Json::Value DumpCTestProjectList(const cmake* cm,
- std::string const& config)
-{
- Json::Value result = Json::arrayValue;
-
- auto globalGen = cm->GetGlobalGenerator();
-
- for (const auto& projectIt : globalGen->GetProjectMap()) {
- Json::Value pObj = Json::objectValue;
- pObj[kNAME_KEY] = projectIt.first;
-
- Json::Value tests = Json::arrayValue;
-
- // Gather tests for every generator
- for (const auto& lg : projectIt.second) {
- // Make sure they're generated.
- lg->GenerateTestFiles();
- DumpMakefileTests(lg, config, &tests);
- }
-
- pObj[kCTEST_INFO] = tests;
-
- result.append(pObj);
- }
-
- return result;
-}
-
-static Json::Value DumpCTestConfiguration(const cmake* cm,
- const std::string& config)
-{
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = config;
-
- result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config);
-
- return result;
-}
-
-static Json::Value DumpCTestConfigurationsList(const cmake* cm)
-{
- Json::Value result = Json::arrayValue;
-
- for (const std::string& c : getConfigurations(cm)) {
- result.append(DumpCTestConfiguration(cm, c));
- }
-
- return result;
-}
-
-Json::Value cmDumpCTestInfo(const cmake* cm)
-{
- Json::Value result = Json::objectValue;
- result[kCONFIGURATIONS_KEY] = DumpCTestConfigurationsList(cm);
- return result;
-}
-
-static Json::Value DumpTarget(cmGeneratorTarget* target,
- const std::string& config)
-{
- cmLocalGenerator* lg = target->GetLocalGenerator();
-
- const cmStateEnums::TargetType type = target->GetType();
- const std::string typeName = cmState::GetTargetTypeName(type);
-
- Json::Value ttl = Json::arrayValue;
- ttl.append("EXECUTABLE");
- ttl.append("STATIC_LIBRARY");
- ttl.append("SHARED_LIBRARY");
- ttl.append("MODULE_LIBRARY");
- ttl.append("OBJECT_LIBRARY");
- ttl.append("UTILITY");
- ttl.append("INTERFACE_LIBRARY");
-
- if (!hasString(ttl, typeName) || target->IsImported()) {
- return Json::Value();
- }
-
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = target->GetName();
- result[kIS_GENERATOR_PROVIDED_KEY] =
- target->Target->GetIsGeneratorProvided();
- result[kTYPE_KEY] = typeName;
- result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory();
- result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory();
-
- if (type == cmStateEnums::INTERFACE_LIBRARY) {
- return result;
- }
-
- result[kFULL_NAME_KEY] = target->GetFullName(config);
-
- if (target->Target->GetHaveInstallRule()) {
- result[kHAS_INSTALL_RULE] = true;
-
- Json::Value installPaths = Json::arrayValue;
- for (const auto& installGenerator :
- target->Makefile->GetInstallGenerators()) {
- auto installTargetGenerator =
- dynamic_cast<cmInstallTargetGenerator*>(installGenerator.get());
- if (installTargetGenerator != nullptr &&
- installTargetGenerator->GetTarget()->Target == target->Target) {
- auto dest = installTargetGenerator->GetDestination(config);
-
- std::string installPath;
- if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) {
- installPath = dest;
- } else {
- installPath = cmStrCat(
- target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"), '/',
- dest);
- }
-
- installPaths.append(installPath);
- }
- }
-
- result[kINSTALL_PATHS] = installPaths;
- }
-
- if (target->HaveWellDefinedOutputFiles()) {
- Json::Value artifacts = Json::arrayValue;
- artifacts.append(
- target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
- if (target->HasImportLibrary(config)) {
- artifacts.append(
- target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
- }
- if (target->IsDLLPlatform()) {
- const cmGeneratorTarget::OutputInfo* output =
- target->GetOutputInfo(config);
- if (output && !output->PdbDir.empty()) {
- artifacts.append(output->PdbDir + '/' + target->GetPDBName(config));
- }
- }
- result[kARTIFACTS_KEY] = artifacts;
-
- result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config);
-
- std::string linkLibs;
- std::string linkFlags;
- std::string linkLanguageFlags;
- std::string frameworkPath;
- std::string linkPath;
- cmLinkLineComputer linkLineComputer(lg,
- lg->GetStateSnapshot().GetDirectory());
- lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
- linkFlags, frameworkPath, linkPath, target);
-
- linkLibs = cmTrimWhitespace(linkLibs);
- linkFlags = cmTrimWhitespace(linkFlags);
- linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
- frameworkPath = cmTrimWhitespace(frameworkPath);
- linkPath = cmTrimWhitespace(linkPath);
-
- if (!cmTrimWhitespace(linkLibs).empty()) {
- result[kLINK_LIBRARIES_KEY] = linkLibs;
- }
- if (!cmTrimWhitespace(linkFlags).empty()) {
- result[kLINK_FLAGS_KEY] = linkFlags;
- }
- if (!cmTrimWhitespace(linkLanguageFlags).empty()) {
- result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
- }
- if (!frameworkPath.empty()) {
- result[kFRAMEWORK_PATH_KEY] = frameworkPath;
- }
- if (!linkPath.empty()) {
- result[kLINK_PATH_KEY] = linkPath;
- }
- const std::string sysroot =
- lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT");
- if (!sysroot.empty()) {
- result[kSYSROOT_KEY] = sysroot;
- }
- }
-
- std::set<std::string> languages;
- target->GetLanguages(languages, config);
- std::map<std::string, LanguageData> languageDataMap;
-
- for (std::string const& lang : languages) {
- LanguageData& ld = languageDataMap[lang];
- ld.Language = lang;
- lg->GetTargetCompileFlags(target, config, lang, ld.Flags);
- std::set<std::string> defines;
- lg->GetTargetDefines(target, config, lang, defines);
- ld.SetDefines(defines);
- std::vector<std::string> includePathList;
- lg->GetIncludeDirectories(includePathList, target, lang, config);
- for (std::string const& i : includePathList) {
- ld.IncludePathList.emplace_back(
- i, target->IsSystemIncludeDirectory(i, config, lang));
- }
- }
-
- Json::Value sourceGroupsValue =
- DumpSourceFilesList(target, config, languageDataMap);
- if (!sourceGroupsValue.empty()) {
- result[kFILE_GROUPS_KEY] = sourceGroupsValue;
- }
-
- return result;
-}
-
-static Json::Value DumpTargetsList(
- const std::vector<cmLocalGenerator*>& generators, const std::string& config)
-{
- Json::Value result = Json::arrayValue;
-
- std::vector<cmGeneratorTarget*> targetList;
- for (auto const& lgIt : generators) {
- cm::append(targetList, lgIt->GetGeneratorTargets());
- }
- std::sort(targetList.begin(), targetList.end());
-
- for (cmGeneratorTarget* target : targetList) {
- Json::Value tmp = DumpTarget(target, config);
- if (!tmp.isNull()) {
- result.append(tmp);
- }
- }
-
- return result;
-}
-
-static Json::Value DumpProjectList(const cmake* cm, std::string const& config)
-{
- Json::Value result = Json::arrayValue;
-
- auto globalGen = cm->GetGlobalGenerator();
-
- for (auto const& projectIt : globalGen->GetProjectMap()) {
- Json::Value pObj = Json::objectValue;
- pObj[kNAME_KEY] = projectIt.first;
-
- // All Projects must have at least one local generator
- assert(!projectIt.second.empty());
- const cmLocalGenerator* lg = projectIt.second.at(0);
-
- // Project structure information:
- const cmMakefile* mf = lg->GetMakefile();
- auto minVersion = mf->GetSafeDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
- pObj[kMINIMUM_CMAKE_VERSION] = minVersion;
- pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
- pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
- pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
-
- // For a project-level install rule it might be defined in any of its
- // associated generators.
- bool hasInstallRule = false;
- for (const auto generator : projectIt.second) {
- for (const auto& installGen :
- generator->GetMakefile()->GetInstallGenerators()) {
- if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen.get())) {
- hasInstallRule = true;
- break;
- }
- }
-
- if (hasInstallRule) {
- break;
- }
- }
-
- pObj[kHAS_INSTALL_RULE] = hasInstallRule;
-
- result.append(pObj);
- }
-
- return result;
-}
-
-static Json::Value DumpConfiguration(const cmake* cm,
- const std::string& config)
-{
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = config;
-
- result[kPROJECTS_KEY] = DumpProjectList(cm, config);
-
- return result;
-}
-
-static Json::Value DumpConfigurationsList(const cmake* cm)
-{
- Json::Value result = Json::arrayValue;
-
- for (std::string const& c : getConfigurations(cm)) {
- result.append(DumpConfiguration(cm, c));
- }
-
- return result;
-}
-
-Json::Value cmDumpCodeModel(const cmake* cm)
-{
- Json::Value result = Json::objectValue;
- result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(cm);
- return result;
-}
diff --git a/Source/cmJsonObjects.h b/Source/cmJsonObjects.h
deleted file mode 100644
index 80a483461..000000000
--- a/Source/cmJsonObjects.h
+++ /dev/null
@@ -1,24 +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>
-#include <vector>
-
-#include <cm3p/json/value.h>
-
-class cmake;
-class cmGlobalGenerator;
-
-extern void cmGetCMakeInputs(const cmGlobalGenerator* gg,
- const std::string& sourceDir,
- const std::string& buildDir,
- std::vector<std::string>* internalFiles,
- std::vector<std::string>* explicitFiles,
- std::vector<std::string>* tmpFiles);
-
-extern Json::Value cmDumpCodeModel(const cmake* cm);
-extern Json::Value cmDumpCTestInfo(const cmake* cm);
-extern Json::Value cmDumpCMakeInputs(const cmake* cm);
diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx
index dfdd3ff65..7ad8690fd 100644
--- a/Source/cmLinkItemGraphVisitor.cxx
+++ b/Source/cmLinkItemGraphVisitor.cxx
@@ -98,7 +98,8 @@ void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
std::string const& config,
DependencyMap& dependencies)
{
- auto implementationLibraries = target.GetLinkImplementationLibraries(config);
+ const auto* implementationLibraries =
+ target.GetLinkImplementationLibraries(config);
if (implementationLibraries != nullptr) {
for (auto const& lib : implementationLibraries->Libraries) {
auto const& name = lib.AsStr();
@@ -106,7 +107,7 @@ void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
}
}
- auto interfaceLibraries =
+ const auto* interfaceLibraries =
target.GetLinkInterfaceLibraries(config, &target, true);
if (interfaceLibraries != nullptr) {
for (auto const& lib : interfaceLibraries->Libraries) {
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 5739feca1..9cae92669 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -3,6 +3,7 @@
#include "cmLinkLineDeviceComputer.h"
+#include <algorithm>
#include <set>
#include <utility>
@@ -57,17 +58,15 @@ bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking(
using ItemVector = cmComputeLinkInformation::ItemVector;
ItemVector const& items = cli.GetItems();
std::string config = cli.GetConfig();
- for (auto const& item : items) {
- if (item.Target &&
- item.Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
- if ((!item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS")) &&
- item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
+ return std::any_of(
+ items.begin(), items.end(),
+ [](cmComputeLinkInformation::Item const& item) -> bool {
+ return item.Target &&
+ item.Target->GetType() == cmStateEnums::STATIC_LIBRARY &&
// this dependency requires us to device link it
- return true;
- }
- }
- }
- return false;
+ !item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS") &&
+ item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION");
+ });
}
void cmLinkLineDeviceComputer::ComputeLinkLibraries(
diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h
index d70176dfc..616bf7e76 100644
--- a/Source/cmLinkedTree.h
+++ b/Source/cmLinkedTree.h
@@ -133,9 +133,9 @@ public:
return iterator(const_cast<cmLinkedTree*>(this), 0);
}
- iterator Push(iterator it) { return Push_impl(it, T()); }
+ iterator Push(iterator it) { return this->Push_impl(it, T()); }
- iterator Push(iterator it, T t) { return Push_impl(it, std::move(t)); }
+ iterator Push(iterator it, T t) { return this->Push_impl(it, std::move(t)); }
bool IsLast(iterator it) { return it.Position == this->Data.size(); }
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index a2c14bd1a..fdddb4556 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -422,9 +422,10 @@ bool HandleJoinCommand(std::vector<std::string> const& args,
bool HandleRemoveItemCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- if (args.size() < 3) {
- status.SetError("sub-command REMOVE_ITEM requires two or more arguments.");
- return false;
+ assert(args.size() >= 2);
+
+ if (args.size() == 2) {
+ return true;
}
const std::string& listName = args[1];
@@ -609,9 +610,9 @@ public:
bool Validate(std::size_t count) override
{
- decltype(Indexes) indexes;
+ decltype(this->Indexes) indexes;
- for (auto index : Indexes) {
+ for (auto index : this->Indexes) {
indexes.push_back(this->NormalizeIndex(index, count));
}
this->Indexes = std::move(indexes);
@@ -750,7 +751,7 @@ bool HandleTransformCommand(std::vector<std::string> const& args,
{
}
- operator const std::string&() const { return Name; }
+ operator const std::string&() const { return this->Name; }
std::string Name;
int Arity = 0;
@@ -1093,8 +1094,9 @@ protected:
public:
cmStringSorter(Compare compare, CaseSensitivity caseSensitivity,
Order desc = Order::ASCENDING)
- : filters{ GetCompareFilter(compare), GetCaseFilter(caseSensitivity) }
- , sortMethod(GetComparisonFunction(compare))
+ : filters{ this->GetCompareFilter(compare),
+ this->GetCaseFilter(caseSensitivity) }
+ , sortMethod(this->GetComparisonFunction(compare))
, descending(desc == Order::DESCENDING)
{
}
@@ -1102,7 +1104,7 @@ public:
std::string ApplyFilter(const std::string& argument)
{
std::string result = argument;
- for (auto filter : filters) {
+ for (auto filter : this->filters) {
if (filter != nullptr) {
result = filter(result);
}
@@ -1112,13 +1114,13 @@ public:
bool operator()(const std::string& a, const std::string& b)
{
- std::string af = ApplyFilter(a);
- std::string bf = ApplyFilter(b);
+ std::string af = this->ApplyFilter(a);
+ std::string bf = this->ApplyFilter(b);
bool result;
- if (descending) {
- result = sortMethod(bf, af);
+ if (this->descending) {
+ result = this->sortMethod(bf, af);
} else {
- result = sortMethod(af, bf);
+ result = this->sortMethod(af, bf);
}
return result;
}
@@ -1424,7 +1426,7 @@ public:
bool operator()(const std::string& target)
{
- return regex.find(target) ^ includeMatches;
+ return this->regex.find(target) ^ this->includeMatches;
}
private:
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 70ef5af03..1464a14cc 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -30,6 +30,7 @@ struct cmListFileParser
bool ParseFunction(const char* name, long line);
bool AddArgument(cmListFileLexer_Token* token,
cmListFileArgument::Delimiter delim);
+ cm::optional<cmListFileContext> CheckNesting() const;
cmListFile* ListFile;
cmListFileBacktrace Backtrace;
cmMessenger* Messenger;
@@ -104,7 +105,7 @@ bool cmListFileParser::ParseFile(const char* filename)
return false;
}
- return Parse();
+ return this->Parse();
}
bool cmListFileParser::ParseString(const char* str,
@@ -117,7 +118,7 @@ bool cmListFileParser::ParseString(const char* str,
return false;
}
- return Parse();
+ return this->Parse();
}
bool cmListFileParser::Parse()
@@ -158,6 +159,17 @@ bool cmListFileParser::Parse()
return false;
}
}
+
+ // Check if all functions are nested properly.
+ if (auto badNesting = this->CheckNesting()) {
+ this->Messenger->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Flow control statements are not properly nested.",
+ this->Backtrace.Push(*badNesting));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
return true;
}
@@ -317,6 +329,112 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
return true;
}
+namespace {
+enum class NestingStateEnum
+{
+ If,
+ Else,
+ While,
+ Foreach,
+ Function,
+ Macro,
+};
+
+struct NestingState
+{
+ NestingStateEnum State;
+ cmListFileContext Context;
+};
+
+bool TopIs(std::vector<NestingState>& stack, NestingStateEnum state)
+{
+ return !stack.empty() && stack.back().State == state;
+}
+}
+
+cm::optional<cmListFileContext> cmListFileParser::CheckNesting() const
+{
+ std::vector<NestingState> stack;
+
+ for (auto const& func : this->ListFile->Functions) {
+ auto const& name = func.LowerCaseName();
+ if (name == "if") {
+ stack.push_back({
+ NestingStateEnum::If,
+ cmListFileContext::FromCommandContext(func, this->FileName),
+ });
+ } else if (name == "elseif") {
+ if (!TopIs(stack, NestingStateEnum::If)) {
+ return cmListFileContext::FromCommandContext(func, this->FileName);
+ }
+ stack.back() = {
+ NestingStateEnum::If,
+ cmListFileContext::FromCommandContext(func, this->FileName),
+ };
+ } else if (name == "else") {
+ if (!TopIs(stack, NestingStateEnum::If)) {
+ return cmListFileContext::FromCommandContext(func, this->FileName);
+ }
+ stack.back() = {
+ NestingStateEnum::Else,
+ cmListFileContext::FromCommandContext(func, this->FileName),
+ };
+ } else if (name == "endif") {
+ if (!TopIs(stack, NestingStateEnum::If) &&
+ !TopIs(stack, NestingStateEnum::Else)) {
+ return cmListFileContext::FromCommandContext(func, this->FileName);
+ }
+ stack.pop_back();
+ } else if (name == "while") {
+ stack.push_back({
+ NestingStateEnum::While,
+ cmListFileContext::FromCommandContext(func, this->FileName),
+ });
+ } else if (name == "endwhile") {
+ if (!TopIs(stack, NestingStateEnum::While)) {
+ return cmListFileContext::FromCommandContext(func, this->FileName);
+ }
+ stack.pop_back();
+ } else if (name == "foreach") {
+ stack.push_back({
+ NestingStateEnum::Foreach,
+ cmListFileContext::FromCommandContext(func, this->FileName),
+ });
+ } else if (name == "endforeach") {
+ if (!TopIs(stack, NestingStateEnum::Foreach)) {
+ return cmListFileContext::FromCommandContext(func, this->FileName);
+ }
+ stack.pop_back();
+ } else if (name == "function") {
+ stack.push_back({
+ NestingStateEnum::Function,
+ cmListFileContext::FromCommandContext(func, this->FileName),
+ });
+ } else if (name == "endfunction") {
+ if (!TopIs(stack, NestingStateEnum::Function)) {
+ return cmListFileContext::FromCommandContext(func, this->FileName);
+ }
+ stack.pop_back();
+ } else if (name == "macro") {
+ stack.push_back({
+ NestingStateEnum::Macro,
+ cmListFileContext::FromCommandContext(func, this->FileName),
+ });
+ } else if (name == "endmacro") {
+ if (!TopIs(stack, NestingStateEnum::Macro)) {
+ return cmListFileContext::FromCommandContext(func, this->FileName);
+ }
+ stack.pop_back();
+ }
+ }
+
+ if (!stack.empty()) {
+ return stack.back().Context;
+ }
+
+ return cm::nullopt;
+}
+
// We hold either the bottom scope of a directory or a call/file context.
// Discriminate these cases via the parent pointer.
struct cmListFileBacktrace::Entry
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 727fc6031..98cb4a772 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -89,6 +89,14 @@ public:
{
}
+#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ cmListFileContext(const cmListFileContext& /*other*/) = default;
+ cmListFileContext(cmListFileContext&& /*other*/) = default;
+
+ cmListFileContext& operator=(const cmListFileContext& /*other*/) = default;
+ cmListFileContext& operator=(cmListFileContext&& /*other*/) = delete;
+#endif
+
static cmListFileContext FromCommandContext(
cmCommandContext const& lfcc, std::string const& fileName,
cm::optional<std::string> deferId = {})
@@ -241,7 +249,7 @@ public:
BTs(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
: Value(std::move(v))
{
- Backtraces.emplace_back(std::move(bt));
+ this->Backtraces.emplace_back(std::move(bt));
}
T Value;
std::vector<cmListFileBacktrace> Backtraces;
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 5790e169c..5a7b30f19 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -3,10 +3,12 @@
#if !defined(_WIN32) && !defined(__sun)
// POSIX APIs are needed
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _POSIX_C_SOURCE 200809L
#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
// For isascii
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _XOPEN_SOURCE 700
#endif
@@ -24,20 +26,20 @@
#include "cmCommand.h"
#include "cmDynamicLoader.h"
#include "cmExecutionStatus.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+// NOLINTNEXTLINE(bugprone-suspicious-include)
#include "cmCPluginAPI.cxx"
#ifdef __QNX__
# include <malloc.h> /* for malloc/free on QNX */
#endif
-class cmListFileBacktrace;
-
namespace {
const char* LastName = nullptr;
@@ -256,10 +258,12 @@ bool cmLoadCommandCommand(std::vector<std::string> const& args,
// if the symbol is found call it to set the name on the
// function blocker
if (initFunction) {
- status.GetMakefile().GetState()->AddScriptedCommand(
+ return status.GetMakefile().GetState()->AddScriptedCommand(
args[0],
- cmLegacyCommandWrapper(cm::make_unique<cmLoadedCommand>(initFunction)));
- return true;
+ BT<cmState::Command>(
+ cmLegacyCommandWrapper(cm::make_unique<cmLoadedCommand>(initFunction)),
+ status.GetMakefile().GetBacktrace()),
+ status.GetMakefile());
}
status.SetError("Attempt to load command failed. "
"No init function found.");
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index b5580e7cc..73b6fbcf6 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -3,6 +3,7 @@
#include "cmLocalGenerator.h"
#include <algorithm>
+#include <array>
#include <cassert>
#include <cstdio>
#include <cstdlib>
@@ -16,9 +17,11 @@
#include <cm/memory>
#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
@@ -279,7 +282,7 @@ static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs,
});
}
-void cmLocalGenerator::TraceDependencies()
+void cmLocalGenerator::TraceDependencies() const
{
// Generate the rule files for each target.
const auto& targets = this->GetGeneratorTargets();
@@ -825,16 +828,13 @@ cmStateSnapshot cmLocalGenerator::GetStateSnapshot() const
return this->Makefile->GetStateSnapshot();
}
-const char* cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
- const std::string& prop)
+cmProp cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
+ const std::string& prop)
{
- cmProp p;
if (target) {
- p = target->GetProperty(prop);
- } else {
- p = this->Makefile->GetProperty(prop);
+ return target->GetProperty(prop);
}
- return p ? p->c_str() : nullptr;
+ return this->Makefile->GetProperty(prop);
}
std::string cmLocalGenerator::ConvertToIncludeReference(
@@ -1056,8 +1056,9 @@ cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
const std::string& target, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir, bool escapeOldStyle,
- bool uses_terminal, const std::string& depfile, const std::string& job_pool,
+ const char* comment, const char* workingDir,
+ cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle, bool uses_terminal,
+ const std::string& depfile, const std::string& job_pool,
bool command_expand_lists, cmObjectLibraryCommands objLibCommands,
bool stdPipesUTF8)
{
@@ -1070,7 +1071,8 @@ cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
detail::AddCustomCommandToTarget(
*this, this->DirectoryBacktrace, cmCommandOrigin::Generator, t, byproducts,
depends, commandLines, type, comment, workingDir, escapeOldStyle,
- uses_terminal, depfile, job_pool, command_expand_lists, stdPipesUTF8);
+ uses_terminal, depfile, job_pool, command_expand_lists, stdPipesUTF8,
+ cmp0116);
return t;
}
@@ -1078,16 +1080,17 @@ cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
const std::string& output, const std::vector<std::string>& depends,
const std::string& main_dependency, const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDir, bool replace,
- bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
- const std::string& depfile, const std::string& job_pool, bool stdPipesUTF8)
+ const char* comment, const char* workingDir,
+ cmPolicies::PolicyStatus cmp0116, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool, bool stdPipesUTF8)
{
std::vector<std::string> no_byproducts;
cmImplicitDependsList no_implicit_depends;
return this->AddCustomCommandToOutput(
{ output }, no_byproducts, depends, main_dependency, no_implicit_depends,
- commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile, job_pool, stdPipesUTF8);
+ commandLines, comment, workingDir, cmp0116, replace, escapeOldStyle,
+ uses_terminal, command_expand_lists, depfile, job_pool, stdPipesUTF8);
}
cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
@@ -1096,9 +1099,9 @@ cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
const std::vector<std::string>& depends, const std::string& main_dependency,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8)
+ const char* workingDir, cmPolicies::PolicyStatus cmp0116, bool replace,
+ bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
+ const std::string& depfile, const std::string& job_pool, bool stdPipesUTF8)
{
// Make sure there is at least one output.
if (outputs.empty()) {
@@ -1110,16 +1113,16 @@ cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
*this, this->DirectoryBacktrace, cmCommandOrigin::Generator, outputs,
byproducts, depends, main_dependency, implicit_depends, commandLines,
comment, workingDir, replace, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile, job_pool, stdPipesUTF8);
+ command_expand_lists, depfile, job_pool, stdPipesUTF8, cmp0116);
}
cmTarget* cmLocalGenerator::AddUtilityCommand(
const std::string& utilityName, bool excludeFromAll, const char* workingDir,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, bool escapeOldStyle,
- const char* comment, bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool, bool stdPipesUTF8)
+ const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
+ bool escapeOldStyle, const char* comment, bool uses_terminal,
+ bool command_expand_lists, const std::string& job_pool, bool stdPipesUTF8)
{
cmTarget* target =
this->Makefile->AddNewUtilityTarget(utilityName, excludeFromAll);
@@ -1131,9 +1134,8 @@ cmTarget* cmLocalGenerator::AddUtilityCommand(
detail::AddUtilityCommand(
*this, this->DirectoryBacktrace, cmCommandOrigin::Generator, target,
- this->Makefile->GetUtilityOutput(target), workingDir, byproducts, depends,
- commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists,
- job_pool, stdPipesUTF8);
+ workingDir, byproducts, depends, commandLines, escapeOldStyle, comment,
+ uses_terminal, command_expand_lists, job_pool, stdPipesUTF8, cmp0116);
return target;
}
@@ -1856,17 +1858,12 @@ bool cmLocalGenerator::AllAppleArchSysrootsAreTheSame(
return false;
}
- for (std::string const& arch : archs) {
- std::string const& archSysroot = this->AppleArchSysroots[arch];
- if (cmIsOff(archSysroot)) {
- continue;
- }
- if (archSysroot != sysroot) {
- return false;
- }
- }
-
- return true;
+ return std::all_of(archs.begin(), archs.end(),
+ [this, &sysroot](std::string const& arch) -> bool {
+ std::string const& archSysroot =
+ this->AppleArchSysroots[arch];
+ return cmIsOff(archSysroot) || archSysroot == sysroot;
+ });
}
void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
@@ -2500,8 +2497,10 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
target->GetSourceFiles(sources, config);
const std::string configUpper = cmSystemTools::UpperCase(config);
+ static const std::array<std::string, 4> langs = { { "C", "CXX", "OBJC",
+ "OBJCXX" } };
- for (const std::string& lang : { "C", "CXX", "OBJC", "OBJCXX" }) {
+ for (const std::string& lang : langs) {
auto langSources = std::count_if(
sources.begin(), sources.end(), [lang](cmSourceFile* sf) {
return lang == sf->GetLanguage() &&
@@ -2554,7 +2553,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
cmProp ReuseFrom =
target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
- auto pch_sf = this->Makefile->GetOrCreateSource(
+ auto* pch_sf = this->Makefile->GetOrCreateSource(
pchSource, false, cmSourceFileLocationKind::Known);
if (!this->GetGlobalGenerator()->IsXcode()) {
@@ -2571,7 +2570,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
"OBJECT_OUTPUTS",
cmStrCat("$<$<CONFIG:", config, ">:", pchFile, ">"));
} else {
- auto reuseTarget =
+ auto* reuseTarget =
this->GlobalGenerator->FindGeneratorTarget(*ReuseFrom);
if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) {
@@ -2608,24 +2607,33 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
}
if (editAndContinueDebugInfo || msvc2008OrLess) {
- CopyPchCompilePdb(config, target, *ReuseFrom, reuseTarget,
- { ".pdb", ".idb" });
+ this->CopyPchCompilePdb(config, target, *ReuseFrom,
+ reuseTarget, { ".pdb", ".idb" });
} else if (enableDebuggingInformation) {
- CopyPchCompilePdb(config, target, *ReuseFrom, reuseTarget,
- { ".pdb" });
+ this->CopyPchCompilePdb(config, target, *ReuseFrom,
+ reuseTarget, { ".pdb" });
}
}
- if (reuseTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- std::string pchSourceObj =
- reuseTarget->GetPchFileObject(config, lang, arch);
+ // Link to the pch object file
+ std::string pchSourceObj =
+ reuseTarget->GetPchFileObject(config, lang, arch);
- // Link to the pch object file
+ if (target->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ std::string linkerProperty = "LINK_FLAGS_";
+ if (target->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ linkerProperty = "STATIC_LIBRARY_FLAGS_";
+ }
target->Target->AppendProperty(
- cmStrCat("LINK_FLAGS_", configUpper),
+ cmStrCat(linkerProperty, configUpper),
cmStrCat(" ",
this->ConvertToOutputFormat(pchSourceObj, SHELL)),
true);
+ } else {
+ target->Target->AppendProperty(
+ "INTERFACE_LINK_LIBRARIES",
+ cmStrCat("$<$<CONFIG:", config,
+ ">:$<LINK_ONLY:", pchSourceObj, ">>"));
}
}
} else {
@@ -2634,15 +2642,17 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
// Add pchHeader to source files, which will
// be grouped as "Precompile Header File"
- auto pchHeader_sf = this->Makefile->GetOrCreateSource(
- pchHeader, true, cmSourceFileLocationKind::Known);
+ auto* pchHeader_sf = this->Makefile->GetOrCreateSource(
+ pchHeader, false, cmSourceFileLocationKind::Known);
std::string err;
pchHeader_sf->ResolveFullPath(&err);
-
- // The pch file is generated, but mark it as not generated
- // so that a clean operation will not remove it from disk
- pchHeader_sf->SetProperty("GENERATED", "0");
-
+ if (!err.empty()) {
+ std::ostringstream msg;
+ msg << "Unable to resolve full path of PCH-header '" << pchHeader
+ << "' assigned to target " << target->GetName()
+ << ", although its path is supposed to be known!";
+ this->IssueMessage(MessageType::FATAL_ERROR, msg.str());
+ }
target->AddSource(pchHeader);
}
}
@@ -2732,6 +2742,7 @@ void cmLocalGenerator::CopyPchCompilePdb(
const std::vector<std::string> no_deps;
const char* no_message = "";
const char* no_current_dir = nullptr;
+ const cmPolicies::PolicyStatus cmp0116_new = cmPolicies::NEW;
std::vector<std::string> no_byproducts;
std::vector<std::string> outputs;
@@ -2741,14 +2752,15 @@ void cmLocalGenerator::CopyPchCompilePdb(
if (this->GetGlobalGenerator()->IsVisualStudio()) {
this->AddCustomCommandToTarget(
target->GetName(), outputs, no_deps, commandLines,
- cmCustomCommandType::PRE_BUILD, no_message, no_current_dir, true, false,
- "", "", false, cmObjectLibraryCommands::Reject, stdPipesUTF8);
+ cmCustomCommandType::PRE_BUILD, no_message, no_current_dir, cmp0116_new,
+ true, false, "", "", false, cmObjectLibraryCommands::Accept,
+ stdPipesUTF8);
} else {
cmImplicitDependsList no_implicit_depends;
cmSourceFile* copy_rule = this->AddCustomCommandToOutput(
outputs, no_byproducts, no_deps, no_main_dependency, no_implicit_depends,
- commandLines, no_message, no_current_dir, false, true, false, false, "",
- "", stdPipesUTF8);
+ commandLines, no_message, no_current_dir, cmp0116_new, false, true,
+ false, false, "", "", stdPipesUTF8);
if (copy_rule) {
target->AddSource(copy_rule->ResolveFullPath());
@@ -2767,12 +2779,34 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf,
target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
}
+}
-inline void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file,
- std::string const& sf_full_path,
- cmProp beforeInclude,
- cmProp afterInclude)
+void cmLocalGenerator::IncludeFileInUnitySources(
+ cmGeneratedFileStream& unity_file, std::string const& sf_full_path,
+ cmProp beforeInclude, cmProp afterInclude, cmProp uniqueIdName) const
{
+ if (uniqueIdName && !uniqueIdName->empty()) {
+ std::string pathToHash;
+ auto PathEqOrSubDir = [](std::string const& a, std::string const& b) {
+ return (cmSystemTools::ComparePath(a, b) ||
+ cmSystemTools::IsSubDirectory(a, b));
+ };
+ const auto path = cmSystemTools::GetFilenamePath(sf_full_path);
+ if (PathEqOrSubDir(path, this->GetBinaryDirectory())) {
+ pathToHash = "BLD_" +
+ cmSystemTools::RelativePath(this->GetBinaryDirectory(), sf_full_path);
+ } else if (PathEqOrSubDir(path, this->GetSourceDirectory())) {
+ pathToHash = "SRC_" +
+ cmSystemTools::RelativePath(this->GetSourceDirectory(), sf_full_path);
+ } else {
+ pathToHash = "ABS_" + sf_full_path;
+ }
+ unity_file << "/* " << pathToHash << " */\n"
+ << "#undef " << *uniqueIdName << "\n"
+ << "#define " << *uniqueIdName << " unity_"
+ << cmSystemTools::ComputeStringMD5(pathToHash) << "\n";
+ }
+
if (beforeInclude) {
unity_file << *beforeInclude << "\n";
}
@@ -2782,9 +2816,10 @@ inline void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file,
if (afterInclude) {
unity_file << *afterInclude << "\n";
}
+ unity_file << "\n";
}
-std::vector<std::string> AddUnityFilesModeAuto(
+std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto(
cmGeneratorTarget* target, std::string const& lang,
std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
cmProp afterInclude, std::string const& filename_base, size_t batchSize)
@@ -2793,6 +2828,8 @@ std::vector<std::string> AddUnityFilesModeAuto(
batchSize = filtered_sources.size();
}
+ cmProp uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
+
std::vector<std::string> unity_files;
for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0;
itemsLeft > 0; itemsLeft -= chunk, ++batch) {
@@ -2816,7 +2853,7 @@ std::vector<std::string> AddUnityFilesModeAuto(
cmSourceFile* sf = filtered_sources[begin];
RegisterUnitySources(target, sf, filename);
IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude,
- afterInclude);
+ afterInclude, uniqueIdName);
}
}
cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
@@ -2825,7 +2862,7 @@ std::vector<std::string> AddUnityFilesModeAuto(
return unity_files;
}
-std::vector<std::string> AddUnityFilesModeGroup(
+std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup(
cmGeneratorTarget* target, std::string const& lang,
std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
cmProp afterInclude, std::string const& filename_base)
@@ -2847,6 +2884,8 @@ std::vector<std::string> AddUnityFilesModeGroup(
}
}
+ cmProp uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
+
for (auto const& item : explicit_mapping) {
auto const& name = item.first;
std::string filename = cmStrCat(filename_base, "unity_", name,
@@ -2862,7 +2901,7 @@ std::vector<std::string> AddUnityFilesModeGroup(
for (cmSourceFile* sf : item.second) {
RegisterUnitySources(target, sf, filename);
IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude,
- afterInclude);
+ afterInclude, uniqueIdName);
}
}
cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
@@ -2871,7 +2910,6 @@ std::vector<std::string> AddUnityFilesModeGroup(
return unity_files;
}
-}
void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
{
@@ -2934,7 +2972,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
}
for (auto const& file : unity_files) {
- auto unity = this->GetMakefile()->GetOrCreateSource(file);
+ auto* unity = this->GetMakefile()->GetOrCreateSource(file);
target->AddSource(file, true);
unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON");
unity->SetProperty("UNITY_SOURCE_FILE", file.c_str());
@@ -3235,7 +3273,7 @@ std::string cmLocalGenerator::GetProjectName() const
}
std::string cmLocalGenerator::ConstructComment(
- cmCustomCommandGenerator const& ccg, const char* default_comment)
+ cmCustomCommandGenerator const& ccg, const char* default_comment) const
{
// Check for a comment provided with the command.
if (ccg.GetComment()) {
@@ -3551,11 +3589,11 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
// we don't end up having:
// CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/generated_source_file.obj
cmProp unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE");
- cmProp psExtension = source.GetProperty("PCH_EXTENSION");
+ cmProp pchExtension = source.GetProperty("PCH_EXTENSION");
const bool isPchObject = objectName.find("cmake_pch") != std::string::npos;
- if (unitySourceFile || psExtension || isPchObject) {
- if (psExtension) {
- customOutputExtension = psExtension->c_str();
+ if (unitySourceFile || pchExtension || isPchObject) {
+ if (pchExtension) {
+ customOutputExtension = pchExtension->c_str();
}
cmsys::RegularExpression var("(CMakeFiles/[^/]+.dir/)");
@@ -3793,7 +3831,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT");
- mf->ConfigureFile(inFile, fname, false, false, false, true);
+ mf->ConfigureFile(inFile, fname, false, false, false);
}
void cmLocalGenerator::GenerateFrameworkInfoPList(
@@ -3828,49 +3866,107 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION");
- mf->ConfigureFile(inFile, fname, false, false, false, true);
+ mf->ConfigureFile(inFile, fname, false, false, false);
}
namespace {
+cm::string_view CustomOutputRoleKeyword(cmLocalGenerator::OutputRole role)
+{
+ return (role == cmLocalGenerator::OutputRole::Primary ? "OUTPUT"_s
+ : "BYPRODUCTS"_s);
+}
+
void CreateGeneratedSource(cmLocalGenerator& lg, const std::string& output,
+ cmLocalGenerator::OutputRole role,
cmCommandOrigin origin,
const cmListFileBacktrace& lfbt)
{
- if (cmGeneratorExpression::Find(output) == std::string::npos) {
- // Outputs without generator expressions from the project are already
- // created and marked as generated. Do not mark them again, because
- // other commands might have overwritten the property.
- if (origin == cmCommandOrigin::Generator) {
- lg.GetMakefile()->GetOrCreateGeneratedSource(output);
- }
- } else {
+ if (cmGeneratorExpression::Find(output) != std::string::npos) {
lg.GetCMakeInstance()->IssueMessage(
MessageType::FATAL_ERROR,
"Generator expressions in custom command outputs are not implemented!",
lfbt);
+ return;
+ }
+
+ // Make sure the file will not be generated into the source
+ // directory during an out of source build.
+ if (!lg.GetMakefile()->CanIWriteThisFile(output)) {
+ lg.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(CustomOutputRoleKeyword(role), " path\n ", output,
+ "\nin a source directory as an output of custom command."),
+ lfbt);
+ return;
+ }
+
+ // Make sure the output file name has no invalid characters.
+ std::string::size_type pos = output.find_first_of("#<>");
+ if (pos != std::string::npos) {
+ lg.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(CustomOutputRoleKeyword(role), " containing a \"", output[pos],
+ "\" is not allowed."),
+ lfbt);
+ return;
+ }
+
+ // Outputs without generator expressions from the project are already
+ // created and marked as generated. Do not mark them again, because
+ // other commands might have overwritten the property.
+ if (origin == cmCommandOrigin::Generator) {
+ lg.GetMakefile()->GetOrCreateGeneratedSource(output);
}
}
-void CreateGeneratedSources(cmLocalGenerator& lg,
- const std::vector<std::string>& outputs,
- cmCommandOrigin origin,
- const cmListFileBacktrace& lfbt)
+std::string ComputeCustomCommandRuleFileName(cmLocalGenerator& lg,
+ cmListFileBacktrace const& bt,
+ std::string const& output)
{
- for (std::string const& o : outputs) {
- CreateGeneratedSource(lg, o, origin, lfbt);
+ // If the output path has no generator expressions, use it directly.
+ if (cmGeneratorExpression::Find(output) == std::string::npos) {
+ return output;
+ }
+
+ // 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.
+
+ // If the only genex is $<CONFIG>, replace that gracefully.
+ {
+ std::string simple = output;
+ cmSystemTools::ReplaceString(simple, "$<CONFIG>", "(CONFIG)");
+ if (cmGeneratorExpression::Find(simple) == std::string::npos) {
+ return simple;
+ }
}
+
+ // If the genex evaluates to the same value in all configurations, use that.
+ {
+ std::vector<std::string> allConfigOutputs =
+ lg.ExpandCustomCommandOutputGenex(output, bt);
+ if (allConfigOutputs.size() == 1) {
+ return allConfigOutputs.front();
+ }
+ }
+
+ // Fall back to a deterministic unique name.
+ cmCryptoHash h(cmCryptoHash::AlgoSHA256);
+ return cmStrCat(lg.GetCurrentBinaryDirectory(), "/CMakeFiles/",
+ h.HashString(output).substr(0, 16));
}
cmSourceFile* AddCustomCommand(
cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
- const std::vector<std::string>& outputs,
+ cmCommandOrigin origin, const std::vector<std::string>& outputs,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends, const std::string& main_dependency,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
const char* workingDir, bool replace, bool escapeOldStyle,
bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8)
+ const std::string& job_pool, bool stdPipesUTF8,
+ cmPolicies::PolicyStatus cmp0116)
{
cmMakefile* mf = lg.GetMakefile();
@@ -3900,7 +3996,8 @@ cmSourceFile* AddCustomCommand(
cmGlobalGenerator* gg = lg.GetGlobalGenerator();
// Construct a rule file associated with the first output produced.
- std::string outName = gg->GenerateRuleFile(outputs[0]);
+ std::string outName = gg->GenerateRuleFile(
+ ComputeCustomCommandRuleFileName(lg, lfbt, outputs[0]));
// Check if the rule file already exists.
file = mf->GetSource(outName, cmSourceFileLocationKind::Known);
@@ -3941,12 +4038,38 @@ cmSourceFile* AddCustomCommand(
cc->SetCommandExpandLists(command_expand_lists);
cc->SetDepfile(depfile);
cc->SetJobPool(job_pool);
+ cc->SetCMP0116Status(cmp0116);
file->SetCustomCommand(std::move(cc));
- mf->AddSourceOutputs(file, outputs, byproducts);
+ lg.AddSourceOutputs(file, outputs, cmLocalGenerator::OutputRole::Primary,
+ lfbt, origin);
+ lg.AddSourceOutputs(file, byproducts,
+ cmLocalGenerator::OutputRole::Byproduct, lfbt, origin);
}
return file;
}
+
+bool AnyOutputMatches(const std::string& name,
+ const std::vector<std::string>& outputs)
+{
+ return std::any_of(outputs.begin(), outputs.end(),
+ [&name](std::string const& output) -> bool {
+ std::string::size_type pos = output.rfind(name);
+ // If the output matches exactly
+ return (pos != std::string::npos &&
+ pos == output.size() - name.size() &&
+ (pos == 0 || output[pos - 1] == '/'));
+ });
+}
+
+bool AnyTargetCommandOutputMatches(
+ const std::string& name, const std::vector<cmCustomCommand>& commands)
+{
+ return std::any_of(commands.begin(), commands.end(),
+ [&name](cmCustomCommand const& command) -> bool {
+ return AnyOutputMatches(name, command.GetByproducts());
+ });
+}
}
namespace detail {
@@ -3960,13 +4083,9 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
const char* workingDir, bool escapeOldStyle,
bool uses_terminal, const std::string& depfile,
const std::string& job_pool,
- bool command_expand_lists, bool stdPipesUTF8)
+ bool command_expand_lists, bool stdPipesUTF8,
+ cmPolicies::PolicyStatus cmp0116)
{
- cmMakefile* mf = lg.GetMakefile();
-
- // Always create the byproduct sources and mark them generated.
- CreateGeneratedSources(lg, byproducts, origin, lfbt);
-
// Add the command to the appropriate build step for the target.
std::vector<std::string> no_output;
cmCustomCommand cc(no_output, byproducts, depends, commandLines, lfbt,
@@ -3977,6 +4096,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
cc.SetCommandExpandLists(command_expand_lists);
cc.SetDepfile(depfile);
cc.SetJobPool(job_pool);
+ cc.SetCMP0116Status(cmp0116);
switch (type) {
case cmCustomCommandType::PRE_BUILD:
target->AddPreBuildCommand(std::move(cc));
@@ -3989,7 +4109,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
break;
}
- mf->AddTargetByproducts(target, byproducts);
+ lg.AddTargetByproducts(target, byproducts, lfbt, origin);
}
cmSourceFile* AddCustomCommandToOutput(
@@ -4001,16 +4121,14 @@ cmSourceFile* AddCustomCommandToOutput(
const cmCustomCommandLines& commandLines, const char* comment,
const char* workingDir, bool replace, bool escapeOldStyle,
bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8)
+ const std::string& job_pool, bool stdPipesUTF8,
+ cmPolicies::PolicyStatus cmp0116)
{
- // Always create the output sources and mark them generated.
- CreateGeneratedSources(lg, outputs, origin, lfbt);
- CreateGeneratedSources(lg, byproducts, origin, lfbt);
-
- return AddCustomCommand(
- lg, lfbt, outputs, byproducts, depends, main_dependency, implicit_depends,
- commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile, job_pool, stdPipesUTF8);
+ return AddCustomCommand(lg, lfbt, origin, outputs, byproducts, depends,
+ main_dependency, implicit_depends, commandLines,
+ comment, workingDir, replace, escapeOldStyle,
+ uses_terminal, command_expand_lists, depfile,
+ job_pool, stdPipesUTF8, cmp0116);
}
void AppendCustomCommandToOutput(cmLocalGenerator& lg,
@@ -4021,7 +4139,22 @@ void AppendCustomCommandToOutput(cmLocalGenerator& lg,
const cmCustomCommandLines& commandLines)
{
// Lookup an existing command.
- if (cmSourceFile* sf = lg.GetMakefile()->GetSourceFileWithOutput(output)) {
+ cmSourceFile* sf = nullptr;
+ if (cmGeneratorExpression::Find(output) == std::string::npos) {
+ sf = lg.GetSourceFileWithOutput(output);
+ } else {
+ // This output path has a generator expression. Evaluate it to
+ // find the output for any configurations.
+ for (std::string const& out :
+ lg.ExpandCustomCommandOutputGenex(output, lfbt)) {
+ sf = lg.GetSourceFileWithOutput(out);
+ if (sf) {
+ break;
+ }
+ }
+ }
+
+ if (sf) {
if (cmCustomCommand* cc = sf->GetCustomCommand()) {
cc->AppendCommands(commandLines);
cc->AppendDepends(depends);
@@ -4033,44 +4166,43 @@ void AppendCustomCommandToOutput(cmLocalGenerator& lg,
// No existing command found.
lg.GetCMakeInstance()->IssueMessage(
MessageType::FATAL_ERROR,
- cmStrCat("Attempt to append to output\n ", output,
+ cmStrCat("Attempt to APPEND to custom command with output\n ", output,
"\nwhich is not already a custom command output."),
lfbt);
}
void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
cmCommandOrigin origin, cmTarget* target,
- const cmUtilityOutput& force, const char* workingDir,
+ const char* workingDir,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
bool escapeOldStyle, const char* comment,
bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool, bool stdPipesUTF8)
+ const std::string& job_pool, bool stdPipesUTF8,
+ cmPolicies::PolicyStatus cmp0116)
{
- // Always create the byproduct sources and mark them generated.
- CreateGeneratedSource(lg, force.Name, origin, lfbt);
- CreateGeneratedSources(lg, byproducts, origin, lfbt);
-
// Use an empty comment to avoid generation of default comment.
if (!comment) {
comment = "";
}
+ // Create the generated symbolic output name of the utility target.
+ std::string output =
+ lg.CreateUtilityOutput(target->GetName(), byproducts, lfbt);
+
std::string no_main_dependency;
cmImplicitDependsList no_implicit_depends;
cmSourceFile* rule = AddCustomCommand(
- lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency,
+ lg, lfbt, origin, { output }, byproducts, depends, no_main_dependency,
no_implicit_depends, commandLines, comment, workingDir,
/*replace=*/false, escapeOldStyle, uses_terminal, command_expand_lists,
- /*depfile=*/"", job_pool, stdPipesUTF8);
+ /*depfile=*/"", job_pool, stdPipesUTF8, cmp0116);
if (rule) {
- lg.GetMakefile()->AddTargetByproducts(target, byproducts);
+ lg.AddTargetByproducts(target, byproducts, lfbt, origin);
}
- if (!force.NameCMP0049.empty()) {
- target->AddSource(force.NameCMP0049);
- }
+ target->AddSource(output);
}
std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target)
@@ -4121,3 +4253,247 @@ std::vector<std::string> ComputeISPCExtraObjects(
return computedObjects;
}
}
+
+cmSourcesWithOutput cmLocalGenerator::GetSourcesWithOutput(
+ const std::string& name) const
+{
+ // Linear search? Also see GetSourceFileWithOutput for detail.
+ if (!cmSystemTools::FileIsFullPath(name)) {
+ cmSourcesWithOutput sources;
+ sources.Target = this->LinearGetTargetWithOutput(name);
+ sources.Source = this->LinearGetSourceFileWithOutput(
+ name, cmSourceOutputKind::OutputOrByproduct, sources.SourceIsByproduct);
+ return sources;
+ }
+ // Otherwise we use an efficient lookup map.
+ auto o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end()) {
+ return o->second.Sources;
+ }
+ return {};
+}
+
+cmSourceFile* cmLocalGenerator::GetSourceFileWithOutput(
+ const std::string& name, cmSourceOutputKind kind) const
+{
+ // If the queried path is not absolute we use the backward compatible
+ // linear-time search for an output with a matching suffix.
+ if (!cmSystemTools::FileIsFullPath(name)) {
+ bool byproduct = false;
+ return this->LinearGetSourceFileWithOutput(name, kind, byproduct);
+ }
+ // Otherwise we use an efficient lookup map.
+ auto o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end() &&
+ (!o->second.Sources.SourceIsByproduct ||
+ kind == cmSourceOutputKind::OutputOrByproduct)) {
+ // Source file could also be null pointer for example if we found the
+ // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD
+ // command of a target, or a not yet created custom command.
+ return o->second.Sources.Source;
+ }
+ return nullptr;
+}
+
+std::string cmLocalGenerator::CreateUtilityOutput(
+ std::string const& targetName, std::vector<std::string> const&,
+ cmListFileBacktrace const&)
+{
+ std::string force =
+ cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", targetName);
+ // The output is not actually created so mark it symbolic.
+ if (cmSourceFile* sf = this->Makefile->GetOrCreateGeneratedSource(force)) {
+ sf->SetProperty("SYMBOLIC", "1");
+ } else {
+ cmSystemTools::Error("Could not get source file entry for " + force);
+ }
+ return force;
+}
+
+std::vector<cmCustomCommandGenerator>
+cmLocalGenerator::MakeCustomCommandGenerators(cmCustomCommand const& cc,
+ std::string const& config)
+{
+ std::vector<cmCustomCommandGenerator> ccgs;
+ ccgs.emplace_back(cc, config, this);
+ return ccgs;
+}
+
+std::vector<std::string> cmLocalGenerator::ExpandCustomCommandOutputPaths(
+ cmCompiledGeneratorExpression const& cge, std::string const& config)
+{
+ std::vector<std::string> paths = cmExpandedList(cge.Evaluate(this, config));
+ for (std::string& p : paths) {
+ p = cmSystemTools::CollapseFullPath(p, this->GetCurrentBinaryDirectory());
+ }
+ return paths;
+}
+
+std::vector<std::string> cmLocalGenerator::ExpandCustomCommandOutputGenex(
+ std::string const& o, cmListFileBacktrace const& bt)
+{
+ std::vector<std::string> allConfigOutputs;
+ cmGeneratorExpression ge(bt);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(o);
+ std::vector<std::string> configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ for (std::string const& config : configs) {
+ std::vector<std::string> configOutputs =
+ this->ExpandCustomCommandOutputPaths(*cge, config);
+ allConfigOutputs.reserve(allConfigOutputs.size() + configOutputs.size());
+ std::move(configOutputs.begin(), configOutputs.end(),
+ std::back_inserter(allConfigOutputs));
+ }
+ auto endUnique =
+ cmRemoveDuplicates(allConfigOutputs.begin(), allConfigOutputs.end());
+ allConfigOutputs.erase(endUnique, allConfigOutputs.end());
+ return allConfigOutputs;
+}
+
+void cmLocalGenerator::AddTargetByproducts(
+ cmTarget* target, const std::vector<std::string>& byproducts,
+ cmListFileBacktrace const& bt, cmCommandOrigin origin)
+{
+ for (std::string const& o : byproducts) {
+ if (cmGeneratorExpression::Find(o) == std::string::npos) {
+ this->UpdateOutputToSourceMap(o, target, bt, origin);
+ continue;
+ }
+
+ // This byproduct path has a generator expression. Evaluate it to
+ // register the byproducts for all configurations.
+ for (std::string const& b : this->ExpandCustomCommandOutputGenex(o, bt)) {
+ this->UpdateOutputToSourceMap(b, target, bt, cmCommandOrigin::Generator);
+ }
+ }
+}
+
+void cmLocalGenerator::AddSourceOutputs(
+ cmSourceFile* source, const std::vector<std::string>& outputs,
+ OutputRole role, cmListFileBacktrace const& bt, cmCommandOrigin origin)
+{
+ for (std::string const& o : outputs) {
+ if (cmGeneratorExpression::Find(o) == std::string::npos) {
+ this->UpdateOutputToSourceMap(o, source, role, bt, origin);
+ continue;
+ }
+
+ // This output path has a generator expression. Evaluate it to
+ // register the outputs for all configurations.
+ for (std::string const& out :
+ this->ExpandCustomCommandOutputGenex(o, bt)) {
+ this->UpdateOutputToSourceMap(out, source, role, bt,
+ cmCommandOrigin::Generator);
+ }
+ }
+}
+
+void cmLocalGenerator::UpdateOutputToSourceMap(std::string const& byproduct,
+ cmTarget* target,
+ cmListFileBacktrace const& bt,
+ cmCommandOrigin origin)
+{
+ SourceEntry entry;
+ entry.Sources.Target = target;
+
+ auto pr = this->OutputToSource.emplace(byproduct, entry);
+ if (pr.second) {
+ CreateGeneratedSource(*this, byproduct, OutputRole::Byproduct, origin, bt);
+ } else {
+ SourceEntry& current = pr.first->second;
+ // Has the target already been set?
+ if (!current.Sources.Target) {
+ current.Sources.Target = target;
+ } else {
+ // Multiple custom commands/targets produce the same output (source file
+ // or target). See also comment in other UpdateOutputToSourceMap
+ // overload.
+ //
+ // TODO: Warn the user about this case.
+ }
+ }
+}
+
+void cmLocalGenerator::UpdateOutputToSourceMap(std::string const& output,
+ cmSourceFile* source,
+ OutputRole role,
+ cmListFileBacktrace const& bt,
+ cmCommandOrigin origin)
+{
+ SourceEntry entry;
+ entry.Sources.Source = source;
+ entry.Sources.SourceIsByproduct = role == OutputRole::Byproduct;
+
+ auto pr = this->OutputToSource.emplace(output, entry);
+ if (pr.second) {
+ CreateGeneratedSource(*this, output, role, origin, bt);
+ } else {
+ SourceEntry& current = pr.first->second;
+ // Outputs take precedence over byproducts
+ if (!current.Sources.Source ||
+ (current.Sources.SourceIsByproduct && role == OutputRole::Primary)) {
+ current.Sources.Source = source;
+ current.Sources.SourceIsByproduct = false;
+ } else {
+ // Multiple custom commands produce the same output but may
+ // be attached to a different source file (MAIN_DEPENDENCY).
+ // LinearGetSourceFileWithOutput would return the first one,
+ // so keep the mapping for the first one.
+ //
+ // TODO: Warn the user about this case. However, the VS 8 generator
+ // triggers it for separate generate.stamp rules in ZERO_CHECK and
+ // individual targets.
+ }
+ }
+}
+
+cmTarget* cmLocalGenerator::LinearGetTargetWithOutput(
+ const std::string& name) const
+{
+ // We go through the ordered vector of targets to get reproducible results
+ // should multiple names match.
+ for (cmTarget* t : this->Makefile->GetOrderedTargets()) {
+ // Does the output of any command match the source file name?
+ if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
+ return t;
+ }
+ if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
+ return t;
+ }
+ if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
+ return t;
+ }
+ }
+ return nullptr;
+}
+
+cmSourceFile* cmLocalGenerator::LinearGetSourceFileWithOutput(
+ const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
+{
+ // Outputs take precedence over byproducts.
+ byproduct = false;
+ cmSourceFile* fallback = nullptr;
+
+ // Look through all the source files that have custom commands and see if the
+ // custom command has the passed source file as an output.
+ for (const auto& src : this->Makefile->GetSourceFiles()) {
+ // Does this source file have a custom command?
+ if (src->GetCustomCommand()) {
+ // Does the output of the custom command match the source file name?
+ if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
+ // Return the first matching output.
+ return src.get();
+ }
+ if (kind == cmSourceOutputKind::OutputOrByproduct) {
+ if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
+ // Do not return the source yet as there might be a matching output.
+ fallback = src.get();
+ }
+ }
+ }
+ }
+
+ // Did we find a byproduct?
+ byproduct = fallback != nullptr;
+ return fallback;
+}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 0fa875924..e48849a57 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <iosfwd>
#include <map>
#include <memory>
@@ -22,9 +23,12 @@
#include "cmProperty.h"
#include "cmStateSnapshot.h"
+class cmCompiledGeneratorExpression;
class cmComputeLinkInformation;
+class cmCustomCommand;
class cmCustomCommandGenerator;
class cmCustomCommandLines;
+class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmImplicitDependsList;
@@ -36,6 +40,31 @@ class cmState;
class cmTarget;
class cmake;
+/** Flag if byproducts shall also be considered. */
+enum class cmSourceOutputKind
+{
+ OutputOnly,
+ OutputOrByproduct
+};
+
+/** What scanner to use for dependencies lookup. */
+enum class cmDependencyScannerKind
+{
+ CMake,
+ Compiler
+};
+
+/** Target and source file which have a specific output. */
+struct cmSourcesWithOutput
+{
+ /** Target with byproduct. */
+ cmTarget* Target = nullptr;
+
+ /** Source file with output or byproduct. */
+ cmSourceFile* Source = nullptr;
+ bool SourceIsByproduct = false;
+};
+
/** \class cmLocalGenerator
* \brief Create required build files for a directory.
*
@@ -59,7 +88,7 @@ public:
/**
* Calls TraceVSDependencies() on all targets of this generator.
*/
- void TraceDependencies();
+ void TraceDependencies() const;
virtual void AddHelperCommands() {}
@@ -295,7 +324,8 @@ public:
const std::string& target, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir, bool escapeOldStyle = true,
+ const char* comment, const char* workingDir,
+ cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle = true,
bool uses_terminal = false, const std::string& depfile = "",
const std::string& job_pool = "", bool command_expand_lists = false,
cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject,
@@ -308,7 +338,8 @@ public:
const std::string& output, const std::vector<std::string>& depends,
const std::string& main_dependency,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace = false, bool escapeOldStyle = true,
+ const char* workingDir, cmPolicies::PolicyStatus cmp0116,
+ bool replace = false, bool escapeOldStyle = true,
bool uses_terminal = false, bool command_expand_lists = false,
const std::string& depfile = "", const std::string& job_pool = "",
bool stdPipesUTF8 = false);
@@ -319,7 +350,8 @@ public:
const std::string& main_dependency,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace = false, bool escapeOldStyle = true,
+ const char* workingDir, cmPolicies::PolicyStatus cmp0116,
+ bool replace = false, bool escapeOldStyle = true,
bool uses_terminal = false, bool command_expand_lists = false,
const std::string& depfile = "", const std::string& job_pool = "",
bool stdPipesUTF8 = false);
@@ -332,10 +364,59 @@ public:
const std::string& utilityName, bool excludeFromAll,
const char* workingDir, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
- const char* comment = nullptr, bool uses_terminal = false,
- bool command_expand_lists = false, const std::string& job_pool = "",
- bool stdPipesUTF8 = false);
+ const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
+ bool escapeOldStyle = true, const char* comment = nullptr,
+ bool uses_terminal = false, bool command_expand_lists = false,
+ const std::string& job_pool = "", bool stdPipesUTF8 = false);
+
+ virtual std::string CreateUtilityOutput(
+ std::string const& targetName, std::vector<std::string> const& byproducts,
+ cmListFileBacktrace const& bt);
+
+ virtual std::vector<cmCustomCommandGenerator> MakeCustomCommandGenerators(
+ cmCustomCommand const& cc, std::string const& config);
+
+ std::vector<std::string> ExpandCustomCommandOutputPaths(
+ cmCompiledGeneratorExpression const& cge, std::string const& config);
+ std::vector<std::string> ExpandCustomCommandOutputGenex(
+ std::string const& o, cmListFileBacktrace const& bt);
+
+ /**
+ * Add target byproducts.
+ */
+ void AddTargetByproducts(cmTarget* target,
+ const std::vector<std::string>& byproducts,
+ cmListFileBacktrace const& bt,
+ cmCommandOrigin origin);
+
+ enum class OutputRole
+ {
+ Primary,
+ Byproduct,
+ };
+
+ /**
+ * Add source file outputs.
+ */
+ void AddSourceOutputs(cmSourceFile* source,
+ std::vector<std::string> const& outputs,
+ OutputRole role, cmListFileBacktrace const& bt,
+ cmCommandOrigin origin);
+
+ /**
+ * Return the target if the provided source name is a byproduct of a utility
+ * target or a PRE_BUILD, PRE_LINK, or POST_BUILD command.
+ * Return the source file which has the provided source name as output.
+ */
+ cmSourcesWithOutput GetSourcesWithOutput(const std::string& name) const;
+
+ /**
+ * Is there a source file that has the provided source name as an output?
+ * If so then return it.
+ */
+ cmSourceFile* GetSourceFileWithOutput(
+ const std::string& name,
+ cmSourceOutputKind kind = cmSourceOutputKind::OutputOnly) const;
std::string GetProjectName() const;
@@ -405,7 +486,7 @@ public:
const std::string& fname);
/** Construct a comment for a custom command. */
std::string ConstructComment(cmCustomCommandGenerator const& ccg,
- const char* default_comment = "");
+ const char* default_comment = "") const;
// Compute object file names.
std::string GetObjectFileNameWithoutTarget(
const cmSourceFile& source, std::string const& dir_max,
@@ -473,8 +554,7 @@ public:
void CreateEvaluationFileOutputs(const std::string& config);
void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
- const char* GetRuleLauncher(cmGeneratorTarget* target,
- const std::string& prop);
+ cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop);
protected:
//! put all the libraries for a target on into the given stream
@@ -534,6 +614,36 @@ protected:
bool BackwardsCompatibilityFinal;
private:
+ /**
+ * See LinearGetSourceFileWithOutput for background information
+ */
+ cmTarget* LinearGetTargetWithOutput(const std::string& name) const;
+
+ /**
+ * Generalized old version of GetSourceFileWithOutput kept for
+ * backward-compatibility. It implements a linear search and supports
+ * relative file paths. It is used as a fall back by GetSourceFileWithOutput
+ * and GetSourcesWithOutput.
+ */
+ cmSourceFile* LinearGetSourceFileWithOutput(const std::string& name,
+ cmSourceOutputKind kind,
+ bool& byproduct) const;
+ struct SourceEntry
+ {
+ cmSourcesWithOutput Sources;
+ };
+
+ // A map for fast output to input look up.
+ using OutputToSourceMap = std::unordered_map<std::string, SourceEntry>;
+ OutputToSourceMap OutputToSource;
+
+ void UpdateOutputToSourceMap(std::string const& byproduct, cmTarget* target,
+ cmListFileBacktrace const& bt,
+ cmCommandOrigin origin);
+ void UpdateOutputToSourceMap(std::string const& output, cmSourceFile* source,
+ OutputRole role, cmListFileBacktrace const& bt,
+ cmCommandOrigin origin);
+
void AddSharedFlags(std::string& flags, const std::string& lang,
bool shared);
bool GetShouldUseOldFlags(bool shared, const std::string& lang) const;
@@ -548,6 +658,18 @@ private:
const std::string& ReuseFrom,
cmGeneratorTarget* reuseTarget,
std::vector<std::string> const& extensions);
+ void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file,
+ std::string const& sf_full_path,
+ cmProp beforeInclude, cmProp afterInclude,
+ cmProp uniqueIdName) const;
+ std::vector<std::string> AddUnityFilesModeAuto(
+ cmGeneratorTarget* target, std::string const& lang,
+ std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
+ cmProp afterInclude, std::string const& filename_base, size_t batchSize);
+ std::vector<std::string> AddUnityFilesModeGroup(
+ cmGeneratorTarget* target, std::string const& lang,
+ std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
+ cmProp afterInclude, std::string const& filename_base);
};
#if !defined(CMAKE_BOOTSTRAP)
@@ -567,7 +689,8 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
const char* workingDir, bool escapeOldStyle,
bool uses_terminal, const std::string& depfile,
const std::string& job_pool,
- bool command_expand_lists, bool stdPipesUTF8);
+ bool command_expand_lists, bool stdPipesUTF8,
+ cmPolicies::PolicyStatus cmp0116);
cmSourceFile* AddCustomCommandToOutput(
cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
@@ -578,7 +701,8 @@ cmSourceFile* AddCustomCommandToOutput(
const cmCustomCommandLines& commandLines, const char* comment,
const char* workingDir, bool replace, bool escapeOldStyle,
bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8);
+ const std::string& job_pool, bool stdPipesUTF8,
+ cmPolicies::PolicyStatus cmp0116);
void AppendCustomCommandToOutput(cmLocalGenerator& lg,
const cmListFileBacktrace& lfbt,
@@ -589,13 +713,14 @@ void AppendCustomCommandToOutput(cmLocalGenerator& lg,
void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
cmCommandOrigin origin, cmTarget* target,
- const cmUtilityOutput& force, const char* workingDir,
+ const char* workingDir,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
bool escapeOldStyle, const char* comment,
bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool, bool stdPipesUTF8);
+ const std::string& job_pool, bool stdPipesUTF8,
+ cmPolicies::PolicyStatus cmp0116);
std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target);
std::vector<std::string> ComputeISPCExtraObjects(
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index ad782ee39..8ed411a3c 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -10,6 +10,8 @@
#include <sstream>
#include <utility>
+#include <cmext/string_view>
+
#include "cmsys/FStream.hxx"
#include "cmCryptoHash.h"
@@ -22,7 +24,9 @@
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmNinjaTargetGenerator.h"
+#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
@@ -36,7 +40,6 @@
cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
cmMakefile* mf)
: cmLocalCommonGenerator(gg, mf, mf->GetState()->GetBinaryDirectory())
- , HomeRelativeOutputPath("")
{
}
@@ -553,9 +556,13 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(
std::string launcher = this->MakeCustomLauncher(ccg);
for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
+ std::string c = ccg.GetCommand(i);
+ if (c.empty()) {
+ continue;
+ }
cmdLines.push_back(launcher +
this->ConvertToOutputFormat(
- ccg.GetCommand(i),
+ c,
gg->IsMultiConfig() ? cmOutputConverter::NINJAMULTI
: cmOutputConverter::SHELL));
@@ -565,71 +572,252 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(
}
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
- cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps,
- const std::string& config)
+ cmCustomCommand const* cc, const std::set<cmGeneratorTarget*>& targets,
+ const std::string& fileConfig)
{
cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator();
- if (gg->SeenCustomCommand(cc, config)) {
+ if (gg->SeenCustomCommand(cc, fileConfig)) {
return;
}
- cmCustomCommandGenerator ccg(*cc, config, this);
+ auto ccgs = this->MakeCustomCommandGenerators(*cc, fileConfig);
+ for (cmCustomCommandGenerator const& ccg : ccgs) {
+ cmNinjaDeps orderOnlyDeps;
- const std::vector<std::string>& outputs = ccg.GetOutputs();
- const std::vector<std::string>& byproducts = ccg.GetByproducts();
-
- bool symbolic = false;
- for (std::string const& output : outputs) {
- if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
- if (sf->GetPropertyAsBool("SYMBOLIC")) {
- symbolic = true;
- break;
+ // A custom command may appear on multiple targets. However, some build
+ // systems exist where the target dependencies on some of the targets are
+ // overspecified, leading to a dependency cycle. If we assume all target
+ // dependencies are a superset of the true target dependencies for this
+ // custom command, we can take the set intersection of all target
+ // dependencies to obtain a correct dependency list.
+ //
+ // FIXME: This won't work in certain obscure scenarios involving indirect
+ // dependencies.
+ auto j = targets.begin();
+ assert(j != targets.end());
+ this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(
+ *j, orderOnlyDeps, ccg.GetOutputConfig(), fileConfig, ccgs.size() > 1);
+ std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end());
+ ++j;
+
+ for (; j != targets.end(); ++j) {
+ std::vector<std::string> jDeps;
+ std::vector<std::string> depsIntersection;
+ this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(
+ *j, jDeps, ccg.GetOutputConfig(), fileConfig, ccgs.size() > 1);
+ std::sort(jDeps.begin(), jDeps.end());
+ std::set_intersection(orderOnlyDeps.begin(), orderOnlyDeps.end(),
+ jDeps.begin(), jDeps.end(),
+ std::back_inserter(depsIntersection));
+ orderOnlyDeps = depsIntersection;
+ }
+
+ const std::vector<std::string>& outputs = ccg.GetOutputs();
+ const std::vector<std::string>& byproducts = ccg.GetByproducts();
+
+ bool symbolic = false;
+ for (std::string const& output : outputs) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
+ if (sf->GetPropertyAsBool("SYMBOLIC")) {
+ symbolic = true;
+ break;
+ }
+ }
+ }
+
+ 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());
+
+ for (std::string const& ninjaOutput : ninjaOutputs) {
+ gg->SeenCustomCommandOutput(ninjaOutput);
+ }
+
+ cmNinjaDeps ninjaDeps;
+ this->AppendCustomCommandDeps(ccg, ninjaDeps, fileConfig);
+
+ std::vector<std::string> cmdLines;
+ this->AppendCustomCommandLines(ccg, cmdLines);
+
+ if (cmdLines.empty()) {
+ cmNinjaBuild build("phony");
+ build.Comment = "Phony custom command for " + ninjaOutputs[0];
+ build.Outputs = std::move(ninjaOutputs);
+ build.ExplicitDeps = std::move(ninjaDeps);
+ build.OrderOnlyDeps = orderOnlyDeps;
+ gg->WriteBuild(this->GetImplFileStream(fileConfig), build);
+ } else {
+ std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+ // Hash full path to make unique.
+ customStep += '-';
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+
+ std::string depfile = cc->GetDepfile();
+ if (!depfile.empty()) {
+ switch (cc->GetCMP0116Status()) {
+ case cmPolicies::WARN:
+ if (this->GetCurrentBinaryDirectory() !=
+ this->GetBinaryDirectory() ||
+ this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0116")) {
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0116),
+ cc->GetBacktrace());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ cmSystemTools::MakeDirectory(
+ cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles/d"));
+ depfile = ccg.GetInternalDepfile();
+ break;
+ }
}
+
+ gg->WriteCustomCommandBuild(
+ this->BuildCommandLine(cmdLines, customStep),
+ this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
+ depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
+ /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig,
+ ninjaDeps, orderOnlyDeps);
}
}
+}
-#if 0
-# error TODO: Once CC in an ExternalProject target must provide the \
- file of each imported target that has an add_dependencies pointing \
- at us. How to know which ExternalProject step actually provides it?
-#endif
- 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());
+bool cmLocalNinjaGenerator::HasUniqueByproducts(
+ std::vector<std::string> const& byproducts, cmListFileBacktrace const& bt)
+{
+ std::vector<std::string> configs =
+ this->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ cmGeneratorExpression ge(bt);
+ for (std::string const& p : byproducts) {
+ if (cmGeneratorExpression::Find(p) == std::string::npos) {
+ return false;
+ }
+ std::set<std::string> seen;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(p);
+ for (std::string const& config : configs) {
+ for (std::string const& b :
+ this->ExpandCustomCommandOutputPaths(*cge, config)) {
+ if (!seen.insert(b).second) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
- for (std::string const& ninjaOutput : ninjaOutputs) {
- gg->SeenCustomCommandOutput(ninjaOutput);
+namespace {
+bool HasUniqueOutputs(std::vector<cmCustomCommandGenerator> const& ccgs)
+{
+ std::set<std::string> allOutputs;
+ std::set<std::string> allByproducts;
+ for (cmCustomCommandGenerator const& ccg : ccgs) {
+ for (std::string const& output : ccg.GetOutputs()) {
+ if (!allOutputs.insert(output).second) {
+ return false;
+ }
+ }
+ for (std::string const& byproduct : ccg.GetByproducts()) {
+ if (!allByproducts.insert(byproduct).second) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+}
+
+std::string cmLocalNinjaGenerator::CreateUtilityOutput(
+ std::string const& targetName, std::vector<std::string> const& byproducts,
+ cmListFileBacktrace const& bt)
+{
+ // In Ninja Multi-Config, we can only produce cross-config utility
+ // commands if all byproducts are per-config.
+ if (!this->GetGlobalGenerator()->IsMultiConfig() ||
+ !this->HasUniqueByproducts(byproducts, bt)) {
+ return this->cmLocalGenerator::CreateUtilityOutput(targetName, byproducts,
+ bt);
+ }
+
+ std::string const base = cmStrCat(this->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", targetName, '-');
+ // The output is not actually created so mark it symbolic.
+ for (std::string const& config :
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) {
+ std::string const force = cmStrCat(base, config);
+ if (cmSourceFile* sf = this->Makefile->GetOrCreateGeneratedSource(force)) {
+ sf->SetProperty("SYMBOLIC", "1");
+ } else {
+ cmSystemTools::Error("Could not get source file entry for " + force);
+ }
}
+ this->GetGlobalNinjaGenerator()->AddPerConfigUtilityTarget(targetName);
+ return cmStrCat(base, "$<CONFIG>"_s);
+}
+
+std::vector<cmCustomCommandGenerator>
+cmLocalNinjaGenerator::MakeCustomCommandGenerators(
+ cmCustomCommand const& cc, std::string const& fileConfig)
+{
+ cmGlobalNinjaGenerator const* gg = this->GetGlobalNinjaGenerator();
- cmNinjaDeps ninjaDeps;
- this->AppendCustomCommandDeps(ccg, ninjaDeps, config);
+ bool transformDepfile = false;
+ switch (cc.GetCMP0116Status()) {
+ case cmPolicies::OLD:
+ case cmPolicies::WARN:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ transformDepfile = true;
+ break;
+ }
- std::vector<std::string> cmdLines;
- this->AppendCustomCommandLines(ccg, cmdLines);
+ // Start with the build graph's configuration.
+ std::vector<cmCustomCommandGenerator> ccgs;
+ ccgs.emplace_back(cc, fileConfig, this, transformDepfile);
- if (cmdLines.empty()) {
- cmNinjaBuild build("phony");
- build.Comment = "Phony custom command for " + ninjaOutputs[0];
- build.Outputs = std::move(ninjaOutputs);
- build.ExplicitDeps = std::move(ninjaDeps);
- build.OrderOnlyDeps = orderOnlyDeps;
- gg->WriteBuild(this->GetImplFileStream(config), build);
- } else {
- std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
- // Hash full path to make unique.
- customStep += '-';
- cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
- customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+ // Consider adding cross configurations.
+ if (!gg->EnableCrossConfigBuild()) {
+ return ccgs;
+ }
+
+ // Outputs and byproducts must be expressed using generator expressions.
+ for (std::string const& output : cc.GetOutputs()) {
+ if (cmGeneratorExpression::Find(output) == std::string::npos) {
+ return ccgs;
+ }
+ }
+ for (std::string const& byproduct : cc.GetByproducts()) {
+ if (cmGeneratorExpression::Find(byproduct) == std::string::npos) {
+ return ccgs;
+ }
+ }
- gg->WriteCustomCommandBuild(
- this->BuildCommandLine(cmdLines, customStep),
- this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
- cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(),
- /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config,
- ninjaDeps, orderOnlyDeps);
+ // Tentatively add the other cross configurations.
+ for (std::string const& config : gg->GetCrossConfigs(fileConfig)) {
+ if (fileConfig != config) {
+ ccgs.emplace_back(cc, fileConfig, this, transformDepfile, config);
+ }
+ }
+
+ // If outputs and byproducts are not unique to each configuration,
+ // drop the cross configurations.
+ if (!HasUniqueOutputs(ccgs)) {
+ ccgs.erase(ccgs.begin() + 1, ccgs.end());
}
+
+ return ccgs;
}
void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
@@ -645,42 +833,13 @@ void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
}
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements(
- const std::string& config)
+ const std::string& fileConfig)
{
for (cmCustomCommand const* customCommand : this->CustomCommands) {
auto i = this->CustomCommandTargets.find(customCommand);
assert(i != this->CustomCommandTargets.end());
- // A custom command may appear on multiple targets. However, some build
- // systems exist where the target dependencies on some of the targets are
- // overspecified, leading to a dependency cycle. If we assume all target
- // dependencies are a superset of the true target dependencies for this
- // custom command, we can take the set intersection of all target
- // dependencies to obtain a correct dependency list.
- //
- // FIXME: This won't work in certain obscure scenarios involving indirect
- // dependencies.
- auto j = i->second.begin();
- assert(j != i->second.end());
- std::vector<std::string> ccTargetDeps;
- this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(
- *j, ccTargetDeps, config);
- std::sort(ccTargetDeps.begin(), ccTargetDeps.end());
- ++j;
-
- for (; j != i->second.end(); ++j) {
- std::vector<std::string> jDeps;
- std::vector<std::string> depsIntersection;
- this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps,
- config);
- std::sort(jDeps.begin(), jDeps.end());
- std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(),
- jDeps.begin(), jDeps.end(),
- std::back_inserter(depsIntersection));
- ccTargetDeps = depsIntersection;
- }
-
- this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps, config);
+ this->WriteCustomCommandBuildStatement(i->first, i->second, fileConfig);
}
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index e81402cb4..5b850f3d0 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
+#include "cmListFileCache.h"
#include "cmLocalCommonGenerator.h"
#include "cmNinjaTypes.h"
#include "cmOutputConverter.h"
@@ -70,6 +71,13 @@ public:
const std::string& fileConfig,
cmNinjaTargetDepends depends);
+ std::string CreateUtilityOutput(std::string const& targetName,
+ std::vector<std::string> const& byproducts,
+ cmListFileBacktrace const& bt) override;
+
+ std::vector<cmCustomCommandGenerator> MakeCustomCommandGenerators(
+ cmCustomCommand const& cc, std::string const& config) override;
+
void AddCustomCommandTarget(cmCustomCommand const* cc,
cmGeneratorTarget* target);
void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg,
@@ -78,6 +86,9 @@ public:
cmNinjaDeps& ninjaDeps,
const std::string& config);
+ bool HasUniqueByproducts(std::vector<std::string> const& byproducts,
+ cmListFileBacktrace const& bt);
+
protected:
std::string ConvertToIncludeReference(
std::string const& path,
@@ -99,9 +110,9 @@ private:
void WriteProcessedMakefile(std::ostream& os);
void WritePools(std::ostream& os);
- void WriteCustomCommandBuildStatement(cmCustomCommand const* cc,
- const cmNinjaDeps& orderOnlyDeps,
- const std::string& config);
+ void WriteCustomCommandBuildStatement(
+ cmCustomCommand const* cc, const std::set<cmGeneratorTarget*>& targets,
+ const std::string& config);
void WriteCustomCommandBuildStatements(const std::string& config);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index c877cf859..464df6854 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -5,18 +5,23 @@
#include <algorithm>
#include <cassert>
#include <cstdio>
+#include <functional>
#include <sstream>
#include <utility>
#include <cm/memory>
+#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmsys/FStream.hxx"
#include "cmsys/Terminal.h"
+#include "cmCMakePath.h"
#include "cmCustomCommand.h" // IWYU pragma: keep
#include "cmCustomCommandGenerator.h"
+#include "cmDependsCompiler.h"
#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
@@ -50,8 +55,9 @@
# include "cmDependsJava.h"
#endif
+namespace {
// Helper function used below.
-static std::string cmSplitExtension(std::string const& in, std::string& base)
+std::string cmSplitExtension(std::string const& in, std::string& base)
{
std::string ext;
std::string::size_type dot_pos = in.rfind('.');
@@ -65,6 +71,43 @@ static std::string cmSplitExtension(std::string const& in, std::string& base)
return ext;
}
+// Helper predicate for removing absolute paths that don't point to the
+// source or binary directory. It is used when CMAKE_DEPENDS_IN_PROJECT_ONLY
+// is set ON, to only consider in-project dependencies during the build.
+class NotInProjectDir
+{
+public:
+ // Constructor with the source and binary directory's path
+ NotInProjectDir(cm::string_view sourceDir, cm::string_view binaryDir)
+ : SourceDir(sourceDir)
+ , BinaryDir(binaryDir)
+ {
+ }
+
+ // Operator evaluating the predicate
+ bool operator()(const std::string& p) const
+ {
+ auto path = cmCMakePath(p).Normal();
+
+ // Keep all relative paths:
+ if (path.IsRelative()) {
+ return false;
+ }
+
+ // If it's an absolute path, check if it starts with the source
+ // directory:
+ return !(cmCMakePath(this->SourceDir).IsPrefix(path) ||
+ cmCMakePath(this->BinaryDir).IsPrefix(path));
+ }
+
+private:
+ // The path to the source directory
+ cm::string_view SourceDir;
+ // The path to the binary directory
+ cm::string_view BinaryDir;
+};
+}
+
cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
cmGlobalGenerator* gg, cmMakefile* mf)
: cmLocalCommonGenerator(gg, mf, mf->GetCurrentBinaryDirectory())
@@ -108,8 +151,8 @@ void cmLocalUnixMakefileGenerator3::Generate()
}
auto& gtVisited = this->GetCommandsVisited(gt);
- auto& deps = this->GlobalGenerator->GetTargetDirectDepends(gt);
- for (auto& d : deps) {
+ const auto& deps = this->GlobalGenerator->GetTargetDirectDepends(gt);
+ for (const auto& d : deps) {
// Take the union of visited source files of custom commands
auto depVisited = this->GetCommandsVisited(d);
gtVisited.insert(depVisited.begin(), depVisited.end());
@@ -552,8 +595,10 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
}
}
- // Write the list of commands.
- os << cmWrap("\t", commands, "", "\n") << "\n";
+ if (!commands.empty()) {
+ // Write the list of commands.
+ os << cmWrap("\t", commands, "", "\n") << "\n";
+ }
if (symbolic && !this->IsWatcomWMake()) {
os << ".PHONY : " << tgt << "\n";
}
@@ -673,7 +718,7 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop(
constexpr const char* vcs_rules[] = {
"%,v", "RCS/%", "RCS/%,v", "SCCS/s.%", "s.%",
};
- for (auto vcs_rule : vcs_rules) {
+ for (const auto* vcs_rule : vcs_rules) {
std::vector<std::string> vcs_depend;
vcs_depend.emplace_back(vcs_rule);
this->WriteMakeRule(makefileStream, "Disable VCS-based implicit rules.",
@@ -960,7 +1005,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
std::string launcher;
// Short-circuit if there is no launcher.
- const char* val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
+ cmProp val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
if (cmNonempty(val)) {
// Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
@@ -980,7 +1025,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
}
vars.Output = output.c_str();
- launcher = val;
+ launcher = *val;
rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
if (!launcher.empty()) {
launcher += " ";
@@ -1298,91 +1343,153 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
cmSystemTools::Error("Target DependInfo.cmake file not found");
}
+ bool status = true;
+
// Check if any multiple output pairs have a missing file.
this->CheckMultipleOutputs(verbose);
std::string const targetDir = cmSystemTools::GetFilenamePath(tgtInfo);
- std::string const internalDependFile = targetDir + "/depend.internal";
- std::string const dependFile = targetDir + "/depend.make";
-
- // If the target DependInfo.cmake file has changed since the last
- // time dependencies were scanned then force rescanning. This may
- // happen when a new source file is added and CMake regenerates the
- // project but no other sources were touched.
- bool needRescanDependInfo = false;
- cmFileTimeCache* ftc =
- this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache();
- {
- int result;
- if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) {
- if (verbose) {
- cmSystemTools::Stdout(cmStrCat("Dependee \"", tgtInfo,
- "\" is newer than depender \"",
- internalDependFile, "\".\n"));
+ if (!this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES").empty()) {
+ // dependencies are managed by CMake itself
+
+ std::string const internalDependFile = targetDir + "/depend.internal";
+ std::string const dependFile = targetDir + "/depend.make";
+
+ // If the target DependInfo.cmake file has changed since the last
+ // time dependencies were scanned then force rescanning. This may
+ // happen when a new source file is added and CMake regenerates the
+ // project but no other sources were touched.
+ bool needRescanDependInfo = false;
+ cmFileTimeCache* ftc =
+ this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache();
+ {
+ int result;
+ if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) {
+ if (verbose) {
+ cmSystemTools::Stdout(cmStrCat("Dependee \"", tgtInfo,
+ "\" is newer than depender \"",
+ internalDependFile, "\".\n"));
+ }
+ needRescanDependInfo = true;
}
- needRescanDependInfo = true;
}
- }
- // If the directory information is newer than depend.internal, include dirs
- // may have changed. In this case discard all old dependencies.
- bool needRescanDirInfo = false;
- {
- std::string dirInfoFile =
- cmStrCat(this->GetCurrentBinaryDirectory(),
- "/CMakeFiles/CMakeDirectoryInformation.cmake");
- int result;
- if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
- result < 0) {
- if (verbose) {
- cmSystemTools::Stdout(cmStrCat("Dependee \"", dirInfoFile,
- "\" is newer than depender \"",
- internalDependFile, "\".\n"));
+ // If the directory information is newer than depend.internal, include
+ // dirs may have changed. In this case discard all old dependencies.
+ bool needRescanDirInfo = false;
+ {
+ std::string dirInfoFile =
+ cmStrCat(this->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeDirectoryInformation.cmake");
+ int result;
+ if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
+ result < 0) {
+ if (verbose) {
+ cmSystemTools::Stdout(cmStrCat("Dependee \"", dirInfoFile,
+ "\" is newer than depender \"",
+ internalDependFile, "\".\n"));
+ }
+ needRescanDirInfo = true;
}
- needRescanDirInfo = true;
+ }
+
+ // Check the implicit dependencies to see if they are up to date.
+ // The build.make file may have explicit dependencies for the object
+ // files but these will not affect the scanning process so they need
+ // not be considered.
+ cmDepends::DependencyMap validDependencies;
+ bool needRescanDependencies = false;
+ if (!needRescanDirInfo) {
+ cmDependsC checker;
+ checker.SetVerbose(verbose);
+ checker.SetFileTimeCache(ftc);
+ // cmDependsC::Check() fills the vector validDependencies() with the
+ // dependencies for those files where they are still valid, i.e.
+ // neither the files themselves nor any files they depend on have
+ // changed. We don't do that if the CMakeDirectoryInformation.cmake
+ // file has changed, because then potentially all dependencies have
+ // changed. This information is given later on to cmDependsC, which
+ // then only rescans the files where it did not get valid dependencies
+ // via this dependency vector. This means that in the normal case, when
+ // only few or one file have been edited, then also only this one file
+ // is actually scanned again, instead of all files for this target.
+ needRescanDependencies =
+ !checker.Check(dependFile, internalDependFile, validDependencies);
+ }
+
+ if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
+ // The dependencies must be regenerated.
+ std::string targetName = cmSystemTools::GetFilenameName(targetDir);
+ targetName = targetName.substr(0, targetName.length() - 4);
+ std::string message =
+ cmStrCat("Scanning dependencies of target ", targetName);
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, color);
+
+ status = this->ScanDependencies(targetDir, dependFile,
+ internalDependFile, validDependencies);
}
}
- // Check the implicit dependencies to see if they are up to date.
- // The build.make file may have explicit dependencies for the object
- // files but these will not affect the scanning process so they need
- // not be considered.
- cmDepends::DependencyMap validDependencies;
- bool needRescanDependencies = false;
- if (!needRescanDirInfo) {
- cmDependsC checker;
- checker.SetVerbose(verbose);
- checker.SetFileTimeCache(ftc);
- // cmDependsC::Check() fills the vector validDependencies() with the
- // dependencies for those files where they are still valid, i.e. neither
- // the files themselves nor any files they depend on have changed.
- // We don't do that if the CMakeDirectoryInformation.cmake file has
- // changed, because then potentially all dependencies have changed.
- // This information is given later on to cmDependsC, which then only
- // rescans the files where it did not get valid dependencies via this
- // dependency vector. This means that in the normal case, when only
- // few or one file have been edited, then also only this one file is
- // actually scanned again, instead of all files for this target.
- needRescanDependencies =
- !checker.Check(dependFile, internalDependFile, validDependencies);
- }
-
- if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
- // The dependencies must be regenerated.
- std::string targetName = cmSystemTools::GetFilenameName(targetDir);
- targetName = targetName.substr(0, targetName.length() - 4);
- std::string message =
- cmStrCat("Scanning dependencies of target ", targetName);
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, color);
-
- return this->ScanDependencies(targetDir, dependFile, internalDependFile,
- validDependencies);
+ auto depends =
+ this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
+ if (!depends.empty()) {
+ // dependencies are managed by compiler
+ auto depFiles = cmExpandedList(depends, true);
+ std::string const internalDepFile =
+ targetDir + "/compiler_depend.internal";
+ std::string const depFile = targetDir + "/compiler_depend.make";
+ cmDepends::DependencyMap dependencies;
+ cmDependsCompiler depsManager;
+ bool projectOnly = cmIsOn(
+ this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_IN_PROJECT_ONLY"));
+
+ depsManager.SetVerbose(verbose);
+ depsManager.SetLocalGenerator(this);
+
+ if (!depsManager.CheckDependencies(
+ internalDepFile, depFiles, dependencies,
+ projectOnly ? NotInProjectDir(this->GetSourceDirectory(),
+ this->GetBinaryDirectory())
+ : std::function<bool(const std::string&)>())) {
+ // regenerate dependencies files
+ std::string targetName =
+ cmCMakePath(targetDir).GetFileName().RemoveExtension().GenericString();
+ auto message = cmStrCat(
+ "Consolidate compiler generated dependencies of target ", targetName);
+ cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, color);
+
+ // Open the make depends file. This should be copy-if-different
+ // because the make tool may try to reload it needlessly otherwise.
+ cmGeneratedFileStream ruleFileStream(
+ depFile, false, this->GlobalGenerator->GetMakefileEncoding());
+ ruleFileStream.SetCopyIfDifferent(true);
+ if (!ruleFileStream) {
+ return false;
+ }
+
+ // Open the cmake dependency tracking file. This should not be
+ // copy-if-different because dependencies are re-scanned when it is
+ // older than the DependInfo.cmake.
+ cmGeneratedFileStream internalRuleFileStream(
+ internalDepFile, false, this->GlobalGenerator->GetMakefileEncoding());
+ if (!internalRuleFileStream) {
+ return false;
+ }
+
+ this->WriteDisclaimer(ruleFileStream);
+ this->WriteDisclaimer(internalRuleFileStream);
+
+ depsManager.WriteDependencies(dependencies, ruleFileStream,
+ internalRuleFileStream);
+ }
}
// The dependencies are already up-to-date.
- return true;
+ return status;
}
bool cmLocalUnixMakefileGenerator3::ScanDependencies(
@@ -1721,178 +1828,207 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
cmDepends clearer;
clearer.SetVerbose(verbose);
for (std::string const& file : files) {
- std::string dir = cmSystemTools::GetFilenamePath(file);
+ auto snapshot = mf->GetState()->CreateBaseSnapshot();
+ cmMakefile lmf(mf->GetGlobalGenerator(), snapshot);
+ lmf.ReadListFile(file);
- // Clear the implicit dependency makefile.
- std::string dependFile = dir + "/depend.make";
- clearer.Clear(dependFile);
+ if (!lmf.GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES").empty()) {
+ std::string dir = cmSystemTools::GetFilenamePath(file);
- // Remove the internal dependency check file to force
- // regeneration.
- std::string internalDependFile = dir + "/depend.internal";
- cmSystemTools::RemoveFile(internalDependFile);
- }
-}
-
-namespace {
-// Helper predicate for removing absolute paths that don't point to the
-// source or binary directory. It is used when CMAKE_DEPENDS_IN_PROJECT_ONLY
-// is set ON, to only consider in-project dependencies during the build.
-class NotInProjectDir
-{
-public:
- // Constructor with the source and binary directory's path
- NotInProjectDir(std::string sourceDir, std::string binaryDir)
- : SourceDir(std::move(sourceDir))
- , BinaryDir(std::move(binaryDir))
- {
- }
+ // Clear the implicit dependency makefile.
+ std::string dependFile = dir + "/depend.make";
+ clearer.Clear(dependFile);
- // Operator evaluating the predicate
- bool operator()(const std::string& path) const
- {
- // Keep all relative paths:
- if (!cmSystemTools::FileIsFullPath(path)) {
- return false;
+ // Remove the internal dependency check file to force
+ // regeneration.
+ std::string internalDependFile = dir + "/depend.internal";
+ cmSystemTools::RemoveFile(internalDependFile);
}
- // If it's an absolute path, check if it starts with the source
- // directory:
- return (
- !(IsInDirectory(SourceDir, path) || IsInDirectory(BinaryDir, path)));
- }
-private:
- // Helper function used by the predicate
- static bool IsInDirectory(const std::string& baseDir,
- const std::string& testDir)
- {
- // First check if the test directory "starts with" the base directory:
- if (!cmHasPrefix(testDir, baseDir)) {
- return false;
+ auto depsFiles = lmf.GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
+ if (!depsFiles.empty()) {
+ auto dir = cmCMakePath(file).GetParentPath();
+ // Clear the implicit dependency makefile.
+ auto depFile = cmCMakePath(dir).Append("compiler_depend.make");
+ clearer.Clear(depFile.GenericString());
+
+ // Remove the internal dependency check file
+ auto internalDepFile =
+ cmCMakePath(dir).Append("compiler_depend.internal");
+ cmSystemTools::RemoveFile(internalDepFile.GenericString());
+
+ // Touch timestamp file to force dependencies regeneration
+ auto DepTimestamp = cmCMakePath(dir).Append("compiler_depend.ts");
+ cmSystemTools::Touch(DepTimestamp.GenericString(), true);
+
+ // clear the dependencies files generated by the compiler
+ std::vector<std::string> dependencies = cmExpandedList(depsFiles);
+ cmDependsCompiler depsManager;
+ depsManager.SetVerbose(verbose);
+ depsManager.ClearDependencies(dependencies);
}
- // If it does, then check that it's either the same string, or that the
- // next character is a slash:
- return ((testDir.size() == baseDir.size()) ||
- (testDir[baseDir.size()] == '/'));
}
-
- // The path to the source directory
- std::string SourceDir;
- // The path to the binary directory
- std::string BinaryDir;
-};
}
void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
std::ostream& cmakefileStream, cmGeneratorTarget* target)
{
- ImplicitDependLanguageMap const& implicitLangs =
- this->GetImplicitDepends(target);
+ // To enable dependencies filtering
+ cmakefileStream << "\n"
+ << "# Consider dependencies only in project.\n"
+ << "set(CMAKE_DEPENDS_IN_PROJECT_ONLY "
+ << (cmIsOn(this->Makefile->GetSafeDefinition(
+ "CMAKE_DEPENDS_IN_PROJECT_ONLY"))
+ ? "ON"
+ : "OFF")
+ << ")\n\n";
+
+ auto const& implicitLangs =
+ this->GetImplicitDepends(target, cmDependencyScannerKind::CMake);
// list the languages
- cmakefileStream
- << "# The set of languages for which implicit dependencies are needed:\n";
+ cmakefileStream << "# The set of languages for which implicit "
+ "dependencies are needed:\n";
cmakefileStream << "set(CMAKE_DEPENDS_LANGUAGES\n";
for (auto const& implicitLang : implicitLangs) {
cmakefileStream << " \"" << implicitLang.first << "\"\n";
}
cmakefileStream << " )\n";
- // now list the files for each language
- cmakefileStream
- << "# The set of files for implicit dependencies of each language:\n";
- for (auto const& implicitLang : implicitLangs) {
- cmakefileStream << "set(CMAKE_DEPENDS_CHECK_" << implicitLang.first
- << "\n";
- ImplicitDependFileMap const& implicitPairs = implicitLang.second;
-
- // for each file pair
- for (auto const& implicitPair : implicitPairs) {
- for (auto const& di : implicitPair.second) {
- cmakefileStream << " \"" << di << "\" ";
- cmakefileStream << "\"" << implicitPair.first << "\"\n";
+ if (!implicitLangs.empty()) {
+ // now list the files for each language
+ cmakefileStream
+ << "# The set of files for implicit dependencies of each language:\n";
+ for (auto const& implicitLang : implicitLangs) {
+ const auto& lang = implicitLang.first;
+
+ cmakefileStream << "set(CMAKE_DEPENDS_CHECK_" << lang << "\n";
+ auto const& implicitPairs = implicitLang.second;
+
+ // for each file pair
+ for (auto const& implicitPair : implicitPairs) {
+ for (auto const& di : implicitPair.second) {
+ cmakefileStream << " \"" << di << "\" ";
+ cmakefileStream << "\"" << implicitPair.first << "\"\n";
+ }
}
- }
- cmakefileStream << " )\n";
-
- // Tell the dependency scanner what compiler is used.
- std::string cidVar =
- cmStrCat("CMAKE_", implicitLang.first, "_COMPILER_ID");
- cmProp cid = this->Makefile->GetDefinition(cidVar);
- if (cmNonempty(cid)) {
- cmakefileStream << "set(CMAKE_" << implicitLang.first
- << "_COMPILER_ID \"" << *cid << "\")\n";
- }
+ cmakefileStream << " )\n";
- if (implicitLang.first == "Fortran") {
- std::string smodSep =
- this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
- std::string smodExt =
- this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
- cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_SEP \"" << smodSep
- << "\")\n";
- cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_EXT \"" << smodExt
- << "\")\n";
- }
+ // Tell the dependency scanner what compiler is used.
+ std::string cidVar = cmStrCat("CMAKE_", lang, "_COMPILER_ID");
+ cmProp cid = this->Makefile->GetDefinition(cidVar);
+ if (cmNonempty(cid)) {
+ cmakefileStream << "set(CMAKE_" << lang << "_COMPILER_ID \"" << *cid
+ << "\")\n";
+ }
- // Build a list of preprocessor definitions for the target.
- std::set<std::string> defines;
- this->GetTargetDefines(target, this->GetConfigName(), implicitLang.first,
- defines);
- if (!defines.empty()) {
- /* clang-format off */
+ if (lang == "Fortran") {
+ std::string smodSep =
+ this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
+ std::string smodExt =
+ this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
+ cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_SEP \"" << smodSep
+ << "\")\n";
+ cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_EXT \"" << smodExt
+ << "\")\n";
+ }
+
+ // Build a list of preprocessor definitions for the target.
+ std::set<std::string> defines;
+ this->GetTargetDefines(target, this->GetConfigName(), lang, defines);
+ if (!defines.empty()) {
+ /* clang-format off */
cmakefileStream
<< "\n"
<< "# Preprocessor definitions for this target.\n"
- << "set(CMAKE_TARGET_DEFINITIONS_" << implicitLang.first << "\n";
- /* clang-format on */
- for (std::string const& define : defines) {
- cmakefileStream << " " << cmOutputConverter::EscapeForCMake(define)
- << "\n";
+ << "set(CMAKE_TARGET_DEFINITIONS_" << lang << "\n";
+ /* clang-format on */
+ for (std::string const& define : defines) {
+ cmakefileStream << " " << cmOutputConverter::EscapeForCMake(define)
+ << "\n";
+ }
+ cmakefileStream << " )\n";
+ }
+
+ // Target-specific include directories:
+ cmakefileStream << "\n"
+ << "# The include file search paths:\n";
+ cmakefileStream << "set(CMAKE_" << lang << "_TARGET_INCLUDE_PATH\n";
+ std::vector<std::string> includes;
+
+ this->GetIncludeDirectories(includes, target, lang,
+ this->GetConfigName());
+ std::string const& binaryDir = this->GetState()->GetBinaryDirectory();
+ if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
+ std::string const& sourceDir = this->GetState()->GetSourceDirectory();
+ cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir));
+ }
+ for (std::string const& include : includes) {
+ cmakefileStream << " \""
+ << this->MaybeConvertToRelativePath(binaryDir, include)
+ << "\"\n";
}
cmakefileStream << " )\n";
}
- // Target-specific include directories:
- cmakefileStream << "\n"
- << "# The include file search paths:\n";
- cmakefileStream << "set(CMAKE_" << implicitLang.first
- << "_TARGET_INCLUDE_PATH\n";
- std::vector<std::string> includes;
-
- this->GetIncludeDirectories(includes, target, implicitLang.first,
- this->GetConfigName());
- std::string binaryDir = this->GetState()->GetBinaryDirectory();
- if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
- std::string const& sourceDir = this->GetState()->GetSourceDirectory();
- cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir));
+ // Store include transform rule properties. Write the directory
+ // rules first because they may be overridden by later target rules.
+ std::vector<std::string> transformRules;
+ if (cmProp xform =
+ this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
+ cmExpandList(*xform, transformRules);
}
- for (std::string const& include : includes) {
- cmakefileStream << " \""
- << this->MaybeConvertToRelativePath(binaryDir, include)
- << "\"\n";
+ if (cmProp xform =
+ target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
+ cmExpandList(*xform, transformRules);
+ }
+ if (!transformRules.empty()) {
+ cmakefileStream << "\nset(CMAKE_INCLUDE_TRANSFORMS\n";
+ for (std::string const& tr : transformRules) {
+ cmakefileStream << " " << cmOutputConverter::EscapeForCMake(tr)
+ << "\n";
+ }
+ cmakefileStream << " )\n";
}
- cmakefileStream << " )\n";
}
- // Store include transform rule properties. Write the directory
- // rules first because they may be overridden by later target rules.
- std::vector<std::string> transformRules;
- if (cmProp xform =
- this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
- cmExpandList(*xform, transformRules);
- }
- if (cmProp xform =
- target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
- cmExpandList(*xform, transformRules);
- }
- if (!transformRules.empty()) {
- cmakefileStream << "set(CMAKE_INCLUDE_TRANSFORMS\n";
- for (std::string const& tr : transformRules) {
- cmakefileStream << " " << cmOutputConverter::EscapeForCMake(tr) << "\n";
+ auto const& compilerLangs =
+ this->GetImplicitDepends(target, cmDependencyScannerKind::Compiler);
+
+ // list the dependency files managed by the compiler
+ cmakefileStream << "\n# The set of dependency files which are needed:\n";
+ cmakefileStream << "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n";
+ for (auto const& compilerLang : compilerLangs) {
+ auto const& compilerPairs = compilerLang.second;
+ if (compilerLang.first == "CUSTOM"_s) {
+ for (auto const& compilerPair : compilerPairs) {
+ for (auto const& src : compilerPair.second) {
+ cmakefileStream << R"( "" ")"
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), compilerPair.first)
+ << R"(" "custom" ")"
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), src)
+ << "\"\n";
+ }
+ }
+ } else {
+ auto depFormat = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
+ for (auto const& compilerPair : compilerPairs) {
+ for (auto const& src : compilerPair.second) {
+ cmakefileStream << " \"" << src << "\" \""
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), compilerPair.first)
+ << "\" \"" << depFormat << "\" \""
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), compilerPair.first)
+ << ".d\"\n";
+ }
+ }
}
- cmakefileStream << " )\n";
}
+ cmakefileStream << " )\n";
}
void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
@@ -2049,16 +2185,18 @@ std::string cmLocalUnixMakefileGenerator3::GetTargetDirectory(
}
cmLocalUnixMakefileGenerator3::ImplicitDependLanguageMap const&
-cmLocalUnixMakefileGenerator3::GetImplicitDepends(const cmGeneratorTarget* tgt)
+cmLocalUnixMakefileGenerator3::GetImplicitDepends(
+ const cmGeneratorTarget* tgt, cmDependencyScannerKind scanner)
{
- return this->ImplicitDepends[tgt->GetName()];
+ return this->ImplicitDepends[tgt->GetName()][scanner];
}
void cmLocalUnixMakefileGenerator3::AddImplicitDepends(
const cmGeneratorTarget* tgt, const std::string& lang,
- const std::string& obj, const std::string& src)
+ const std::string& obj, const std::string& src,
+ cmDependencyScannerKind scanner)
{
- this->ImplicitDepends[tgt->GetName()][lang][obj].push_back(src);
+ this->ImplicitDepends[tgt->GetName()][scanner][lang][obj].push_back(src);
}
void cmLocalUnixMakefileGenerator3::CreateCDCommand(
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 8286d673f..14dd0baf4 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -13,6 +13,7 @@
#include "cmDepends.h"
#include "cmLocalCommonGenerator.h"
+#include "cmLocalGenerator.h"
class cmCustomCommand;
class cmCustomCommandGenerator;
@@ -152,23 +153,21 @@ public:
// File pairs for implicit dependency scanning. The key of the map
// is the depender and the value is the explicit dependee.
- struct ImplicitDependFileMap : public cmDepends::DependencyMap
- {
- };
- struct ImplicitDependLanguageMap
- : public std::map<std::string, ImplicitDependFileMap>
- {
- };
- struct ImplicitDependTargetMap
- : public std::map<std::string, ImplicitDependLanguageMap>
- {
- };
+ using ImplicitDependFileMap = cmDepends::DependencyMap;
+ using ImplicitDependLanguageMap =
+ std::map<std::string, ImplicitDependFileMap>;
+ using ImplicitDependScannerMap =
+ std::map<cmDependencyScannerKind, ImplicitDependLanguageMap>;
+ using ImplicitDependTargetMap =
+ std::map<std::string, ImplicitDependScannerMap>;
ImplicitDependLanguageMap const& GetImplicitDepends(
- cmGeneratorTarget const* tgt);
+ cmGeneratorTarget const* tgt,
+ cmDependencyScannerKind scanner = cmDependencyScannerKind::CMake);
- void AddImplicitDepends(cmGeneratorTarget const* tgt,
- const std::string& lang, const std::string& obj,
- const std::string& src);
+ void AddImplicitDepends(
+ cmGeneratorTarget const* tgt, const std::string& lang,
+ const std::string& obj, const std::string& src,
+ cmDependencyScannerKind scanner = cmDependencyScannerKind::CMake);
// write the target rules for the local Makefile into the stream
void WriteLocalAllRules(std::ostream& ruleFileStream);
@@ -178,11 +177,11 @@ public:
/** Get whether to create rules to generate preprocessed and
assembly sources. This could be converted to a variable lookup
later. */
- bool GetCreatePreprocessedSourceRules()
+ bool GetCreatePreprocessedSourceRules() const
{
return !this->SkipPreprocessedSourceRules;
}
- bool GetCreateAssemblySourceRules()
+ bool GetCreateAssemblySourceRules() const
{
return !this->SkipAssemblySourceRules;
}
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index d2cdb99a0..a3940ead6 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -121,7 +121,7 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
}
if (cmSourceFile* file = this->AddCustomCommandToOutput(
force, no_depends, no_main_dependency, force_commands, " ",
- nullptr, true)) {
+ nullptr, cmPolicies::NEW, true)) {
l->AddSource(file->ResolveFullPath());
}
}
@@ -245,9 +245,10 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
"--check-stamp-file", stampName });
std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
const char* no_working_directory = nullptr;
- this->AddCustomCommandToOutput(
- stampName, listFiles, makefileIn, commandLines, comment.c_str(),
- no_working_directory, true, false, false, false, "", "", stdPipesUTF8);
+ this->AddCustomCommandToOutput(stampName, listFiles, makefileIn,
+ commandLines, comment.c_str(),
+ no_working_directory, cmPolicies::NEW, true,
+ false, false, false, "", "", stdPipesUTF8);
if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
// Finalize the source file path now since we're adding this after
// the generator validated all project-named sources.
@@ -1010,7 +1011,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
this->GetStaticLibraryFlags(
libflags, configName, target->GetLinkerLanguage(configName), target);
if (!libflags.empty()) {
- fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
+ fout << "\t\t\t\tAdditionalOptions=\"" << this->EscapeForXML(libflags)
+ << "\"\n";
}
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(libpath) << "\"/>\n";
diff --git a/Source/cmMSVC60LinkLineComputer.cxx b/Source/cmMSVC60LinkLineComputer.cxx
index 74c94351c..8cf37659d 100644
--- a/Source/cmMSVC60LinkLineComputer.cxx
+++ b/Source/cmMSVC60LinkLineComputer.cxx
@@ -36,5 +36,5 @@ std::string cmMSVC60LinkLineComputer::ConvertToLinkReference(
}
#endif
- return cmLinkLineComputer::ConvertToLinkReference(lib);
+ return this->cmLinkLineComputer::ConvertToLinkReference(lib);
}
diff --git a/Source/cmMachO.h b/Source/cmMachO.h
index be92c9550..faa024b9b 100644
--- a/Source/cmMachO.h
+++ b/Source/cmMachO.h
@@ -7,8 +7,8 @@
#include <iosfwd>
#include <string>
-#if !defined(CMAKE_USE_MACH_PARSER)
-# error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled."
+#if !defined(CMake_USE_MACH_PARSER)
+# error "This file may be included only if CMake_USE_MACH_PARSER is enabled."
#endif
class cmMachOInternal;
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 98f88c105..8c4b2a71d 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -171,8 +171,11 @@ bool cmMacroFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
f.Functions = std::move(functions);
f.FilePath = this->GetStartingContext().FilePath;
mf.RecordPolicies(f.Policies);
- mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
- return true;
+ return mf.GetState()->AddScriptedCommand(
+ this->Args[0],
+ BT<cmState::Command>(std::move(f),
+ mf.GetBacktrace().Push(this->GetStartingContext())),
+ mf);
}
}
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 39468417e..78cae0e98 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -29,15 +29,12 @@
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
-#include "cm_sys_stat.h"
-
#include "cmCommandArgumentParserHelper.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmExpandedCommandArgument.h" // IWYU pragma: keep
#include "cmExportBuildFileGenerator.h"
-#include "cmFSPermissions.h"
#include "cmFileLockPool.h"
#include "cmFunctionBlocker.h"
#include "cmGeneratedFileStream.h"
@@ -72,8 +69,6 @@
class cmMessenger;
-using namespace cmFSPermissions;
-
cmDirectoryId::cmDirectoryId(std::string s)
: String(std::move(s))
{
@@ -871,12 +866,13 @@ void cmMakefile::AddEvaluationFile(
const std::string& inputFile, const std::string& targetName,
std::unique_ptr<cmCompiledGeneratorExpression> outputName,
std::unique_ptr<cmCompiledGeneratorExpression> condition,
- bool inputIsContent)
+ const std::string& newLineCharacter, mode_t permissions, bool inputIsContent)
{
this->EvaluationFiles.push_back(
cm::make_unique<cmGeneratorExpressionEvaluationFile>(
inputFile, targetName, std::move(outputName), std::move(condition),
- inputIsContent, this->GetPolicyStatus(cmPolicies::CMP0070)));
+ inputIsContent, newLineCharacter, permissions,
+ this->GetPolicyStatus(cmPolicies::CMP0070)));
}
const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>&
@@ -939,8 +935,6 @@ void cmMakefile::DoGenerate(cmLocalGenerator& lg)
action.Value(lg, action.Backtrace);
}
this->GeneratorActionsInvoked = true;
- this->DelayedOutputFiles.clear();
- this->DelayedOutputFilesHaveGenex = false;
// go through all configured files and see which ones still exist.
// we don't want cmake to re-run if a configured file is created and deleted
@@ -984,7 +978,7 @@ struct BacktraceGuard
this->Backtrace = std::move(current);
}
- ~BacktraceGuard() { this->Backtrace = std::move(Previous); }
+ ~BacktraceGuard() { this->Backtrace = std::move(this->Previous); }
private:
cmListFileBacktrace& Backtrace;
@@ -1091,8 +1085,9 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
const std::string& target, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir, bool escapeOldStyle,
- bool uses_terminal, const std::string& depfile, const std::string& job_pool,
+ const char* comment, const char* workingDir,
+ cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle, bool uses_terminal,
+ const std::string& depfile, const std::string& job_pool,
bool command_expand_lists, bool stdPipesUTF8)
{
cmTarget* t = this->GetCustomCommandTarget(
@@ -1104,7 +1099,7 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
}
// Always create the byproduct sources and mark them generated.
- this->CreateGeneratedByproducts(byproducts);
+ this->CreateGeneratedOutputs(byproducts);
// Strings could be moved into the callback function with C++14.
cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -1118,7 +1113,7 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
lg, lfbt, cmCommandOrigin::Project, t, byproducts, depends,
commandLines, type, GetCStrOrNull(commentStr),
GetCStrOrNull(workingStr), escapeOldStyle, uses_terminal, depfile,
- job_pool, command_expand_lists, stdPipesUTF8);
+ job_pool, command_expand_lists, stdPipesUTF8, cmp0116);
});
return t;
@@ -1128,16 +1123,18 @@ void cmMakefile::AddCustomCommandToOutput(
const std::string& output, const std::vector<std::string>& depends,
const std::string& main_dependency, const cmCustomCommandLines& commandLines,
const char* comment, const char* workingDir,
- const CommandSourceCallback& callback, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ cmPolicies::PolicyStatus cmp0116, const CommandSourceCallback& callback,
+ bool replace, bool escapeOldStyle, bool uses_terminal,
+ bool command_expand_lists, const std::string& depfile,
const std::string& job_pool, bool stdPipesUTF8)
{
std::vector<std::string> no_byproducts;
cmImplicitDependsList no_implicit_depends;
this->AddCustomCommandToOutput(
{ output }, no_byproducts, depends, main_dependency, no_implicit_depends,
- commandLines, comment, workingDir, callback, replace, escapeOldStyle,
- uses_terminal, command_expand_lists, depfile, job_pool, stdPipesUTF8);
+ commandLines, comment, workingDir, cmp0116, callback, replace,
+ escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool,
+ stdPipesUTF8);
}
void cmMakefile::AddCustomCommandToOutput(
@@ -1146,9 +1143,10 @@ void cmMakefile::AddCustomCommandToOutput(
const std::vector<std::string>& depends, const std::string& main_dependency,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, const CommandSourceCallback& callback, bool replace,
- bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
- const std::string& depfile, const std::string& job_pool, bool stdPipesUTF8)
+ const char* workingDir, cmPolicies::PolicyStatus cmp0116,
+ const CommandSourceCallback& callback, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool, bool stdPipesUTF8)
{
// Make sure there is at least one output.
if (outputs.empty()) {
@@ -1163,7 +1161,7 @@ void cmMakefile::AddCustomCommandToOutput(
// Always create the output sources and mark them generated.
this->CreateGeneratedOutputs(outputs);
- this->CreateGeneratedByproducts(byproducts);
+ this->CreateGeneratedOutputs(byproducts);
// Strings could be moved into the callback function with C++14.
cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -1178,7 +1176,7 @@ void cmMakefile::AddCustomCommandToOutput(
main_dependency, implicit_depends, commandLines,
GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), replace,
escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool,
- stdPipesUTF8);
+ stdPipesUTF8, cmp0116);
if (callback && sf) {
callback(sf);
}
@@ -1188,7 +1186,8 @@ void cmMakefile::AddCustomCommandToOutput(
void cmMakefile::AddCustomCommandOldStyle(
const std::string& target, const std::vector<std::string>& outputs,
const std::vector<std::string>& depends, const std::string& source,
- const cmCustomCommandLines& commandLines, const char* comment)
+ const cmCustomCommandLines& commandLines, const char* comment,
+ cmPolicies::PolicyStatus cmp0116)
{
// Translate the old-style signature to one of the new-style
// signatures.
@@ -1199,7 +1198,7 @@ void cmMakefile::AddCustomCommandOldStyle(
std::vector<std::string> no_byproducts;
this->AddCustomCommandToTarget(
target, no_byproducts, depends, commandLines,
- cmCustomCommandType::POST_BUILD, comment, nullptr);
+ cmCustomCommandType::POST_BUILD, comment, nullptr, cmp0116);
return;
}
@@ -1222,16 +1221,18 @@ void cmMakefile::AddCustomCommandOldStyle(
};
// Each output must get its own copy of this rule.
- cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|m|mm|"
- "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
- "hm|hpp|hxx|in|txx|inl)$");
+ cmsys::RegularExpression sourceFiles(
+ "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|mpp|cu|m|mm|"
+ "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
+ "hm|hpp|hxx|in|txx|inl)$");
// Choose whether to use a main dependency.
if (sourceFiles.find(source)) {
// The source looks like a real file. Use it as the main dependency.
for (std::string const& output : outputs) {
this->AddCustomCommandToOutput(output, depends, source, commandLines,
- comment, nullptr, addRuleFileToTarget);
+ comment, nullptr, cmp0116,
+ addRuleFileToTarget);
}
} else {
std::string no_main_dependency;
@@ -1241,22 +1242,17 @@ void cmMakefile::AddCustomCommandOldStyle(
// The source may not be a real file. Do not use a main dependency.
for (std::string const& output : outputs) {
this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
- commandLines, comment, nullptr,
+ commandLines, comment, nullptr, cmp0116,
addRuleFileToTarget);
}
}
}
-bool cmMakefile::AppendCustomCommandToOutput(
+void cmMakefile::AppendCustomCommandToOutput(
const std::string& output, const std::vector<std::string>& depends,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines)
{
- // Check as good as we can if there will be a command for this output.
- if (!this->MightHaveCustomCommand(output)) {
- return false;
- }
-
// Validate custom commands.
if (this->ValidateCustomCommand(commandLines)) {
// Dispatch command creation to allow generator expressions in outputs.
@@ -1267,38 +1263,15 @@ bool cmMakefile::AppendCustomCommandToOutput(
implicit_depends, commandLines);
});
}
-
- return true;
-}
-
-cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target)
-{
- std::string force = cmStrCat(this->GetCurrentBinaryDirectory(),
- "/CMakeFiles/", target->GetName());
- std::string forceCMP0049 = target->GetSourceCMP0049(force);
- {
- cmSourceFile* sf = nullptr;
- if (!forceCMP0049.empty()) {
- sf = this->GetOrCreateSource(forceCMP0049, false,
- cmSourceFileLocationKind::Known);
- }
- // The output is not actually created so mark it symbolic.
- if (sf) {
- sf->SetProperty("SYMBOLIC", "1");
- } else {
- cmSystemTools::Error("Could not get source file entry for " + force);
- }
- }
- return { std::move(force), std::move(forceCMP0049) };
}
cmTarget* cmMakefile::AddUtilityCommand(
const std::string& utilityName, bool excludeFromAll, const char* workingDir,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, bool escapeOldStyle,
- const char* comment, bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool, bool stdPipesUTF8)
+ const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
+ bool escapeOldStyle, const char* comment, bool uses_terminal,
+ bool command_expand_lists, const std::string& job_pool, bool stdPipesUTF8)
{
cmTarget* target = this->AddNewUtilityTarget(utilityName, excludeFromAll);
@@ -1308,12 +1281,8 @@ cmTarget* cmMakefile::AddUtilityCommand(
return target;
}
- // Get the output name of the utility target and mark it generated.
- cmUtilityOutput force = this->GetUtilityOutput(target);
- this->GetOrCreateGeneratedSource(force.Name);
-
// Always create the byproduct sources and mark them generated.
- this->CreateGeneratedByproducts(byproducts);
+ this->CreateGeneratedOutputs(byproducts);
// Strings could be moved into the callback function with C++14.
cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -1323,11 +1292,11 @@ cmTarget* cmMakefile::AddUtilityCommand(
this->AddGeneratorAction(
[=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
BacktraceGuard guard(this->Backtrace, lfbt);
- detail::AddUtilityCommand(lg, lfbt, cmCommandOrigin::Project, target,
- force, GetCStrOrNull(workingStr), byproducts,
- depends, commandLines, escapeOldStyle,
- GetCStrOrNull(commentStr), uses_terminal,
- command_expand_lists, job_pool, stdPipesUTF8);
+ detail::AddUtilityCommand(
+ lg, lfbt, cmCommandOrigin::Project, target, GetCStrOrNull(workingStr),
+ byproducts, depends, commandLines, escapeOldStyle,
+ GetCStrOrNull(commentStr), uses_terminal, command_expand_lists,
+ job_pool, stdPipesUTF8, cmp0116);
});
return target;
@@ -1496,15 +1465,14 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
// Include transform property. There is no per-config version.
{
const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM";
- cmProp p = parent->GetProperty(prop);
- this->SetProperty(prop, cmToCStr(p));
+ this->SetProperty(prop, cmToCStr(parent->GetProperty(prop)));
}
// compile definitions property and per-config versions
cmPolicies::PolicyStatus polSt = this->GetPolicyStatus(cmPolicies::CMP0043);
if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
- cmProp p = parent->GetProperty("COMPILE_DEFINITIONS");
- this->SetProperty("COMPILE_DEFINITIONS", cmToCStr(p));
+ this->SetProperty("COMPILE_DEFINITIONS",
+ cmToCStr(parent->GetProperty("COMPILE_DEFINITIONS")));
std::vector<std::string> configs =
this->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
for (std::string const& config : configs) {
@@ -1516,12 +1484,11 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
}
// labels
- cmProp p = parent->GetProperty("LABELS");
- this->SetProperty("LABELS", cmToCStr(p));
+ this->SetProperty("LABELS", cmToCStr(parent->GetProperty("LABELS")));
// link libraries
- p = parent->GetProperty("LINK_LIBRARIES");
- this->SetProperty("LINK_LIBRARIES", cmToCStr(p));
+ this->SetProperty("LINK_LIBRARIES",
+ cmToCStr(parent->GetProperty("LINK_LIBRARIES")));
// the initial project name
this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName());
@@ -1863,7 +1830,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
auto subMfu =
cm::make_unique<cmMakefile>(this->GlobalGenerator, newSnapshot);
- auto subMf = subMfu.get();
+ auto* subMf = subMfu.get();
this->GetGlobalGenerator()->AddMakefile(std::move(subMfu));
if (excludeFromAll) {
@@ -1877,7 +1844,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
}
this->AddInstallGenerator(cm::make_unique<cmInstallSubdirectoryGenerator>(
- subMf, binPath, excludeFromAll));
+ subMf, binPath, excludeFromAll, this->GetBacktrace()));
}
const std::string& cmMakefile::GetCurrentSourceDirectory() const
@@ -2038,7 +2005,7 @@ void cmMakefile::RemoveDefinition(const std::string& name)
#endif
}
-void cmMakefile::RemoveCacheDefinition(const std::string& name)
+void cmMakefile::RemoveCacheDefinition(const std::string& name) const
{
this->GetState()->RemoveCacheEntry(name);
}
@@ -2154,213 +2121,6 @@ cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
}
namespace {
-bool AnyOutputMatches(const std::string& name,
- const std::vector<std::string>& outputs)
-{
- for (std::string const& output : outputs) {
- std::string::size_type pos = output.rfind(name);
- // If the output matches exactly
- if (pos != std::string::npos && pos == output.size() - name.size() &&
- (pos == 0 || output[pos - 1] == '/')) {
- return true;
- }
- }
- return false;
-}
-
-bool AnyTargetCommandOutputMatches(
- const std::string& name, const std::vector<cmCustomCommand>& commands)
-{
- for (cmCustomCommand const& command : commands) {
- if (AnyOutputMatches(name, command.GetByproducts())) {
- return true;
- }
- }
- return false;
-}
-}
-
-cmTarget* cmMakefile::LinearGetTargetWithOutput(const std::string& name) const
-{
- // We go through the ordered vector of targets to get reproducible results
- // should multiple names match.
- for (cmTarget* t : this->OrderedTargets) {
- // Does the output of any command match the source file name?
- if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
- return t;
- }
- if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
- return t;
- }
- if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
- return t;
- }
- }
- return nullptr;
-}
-
-cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput(
- const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
-{
- // Outputs take precedence over byproducts.
- byproduct = false;
- cmSourceFile* fallback = nullptr;
-
- // Look through all the source files that have custom commands and see if the
- // custom command has the passed source file as an output.
- for (const auto& src : this->SourceFiles) {
- // Does this source file have a custom command?
- if (src->GetCustomCommand()) {
- // Does the output of the custom command match the source file name?
- if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
- // Return the first matching output.
- return src.get();
- }
- if (kind == cmSourceOutputKind::OutputOrByproduct) {
- if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
- // Do not return the source yet as there might be a matching output.
- fallback = src.get();
- }
- }
- }
- }
-
- // Did we find a byproduct?
- byproduct = fallback != nullptr;
- return fallback;
-}
-
-cmSourcesWithOutput cmMakefile::GetSourcesWithOutput(
- const std::string& name) const
-{
- // Linear search? Also see GetSourceFileWithOutput for detail.
- if (!cmSystemTools::FileIsFullPath(name)) {
- cmSourcesWithOutput sources;
- sources.Target = this->LinearGetTargetWithOutput(name);
- sources.Source = this->LinearGetSourceFileWithOutput(
- name, cmSourceOutputKind::OutputOrByproduct, sources.SourceIsByproduct);
- return sources;
- }
- // Otherwise we use an efficient lookup map.
- auto o = this->OutputToSource.find(name);
- if (o != this->OutputToSource.end()) {
- return o->second.Sources;
- }
- return {};
-}
-
-cmSourceFile* cmMakefile::GetSourceFileWithOutput(
- const std::string& name, cmSourceOutputKind kind) const
-{
- // If the queried path is not absolute we use the backward compatible
- // linear-time search for an output with a matching suffix.
- if (!cmSystemTools::FileIsFullPath(name)) {
- bool byproduct = false;
- return this->LinearGetSourceFileWithOutput(name, kind, byproduct);
- }
- // Otherwise we use an efficient lookup map.
- auto o = this->OutputToSource.find(name);
- if (o != this->OutputToSource.end() &&
- (!o->second.Sources.SourceIsByproduct ||
- kind == cmSourceOutputKind::OutputOrByproduct)) {
- // Source file could also be null pointer for example if we found the
- // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD
- // command of a target, or a not yet created custom command.
- return o->second.Sources.Source;
- }
- return nullptr;
-}
-
-bool cmMakefile::MightHaveCustomCommand(const std::string& name) const
-{
- if (this->DelayedOutputFilesHaveGenex ||
- cmGeneratorExpression::Find(name) != std::string::npos) {
- // Could be more restrictive, but for now we assume that there could always
- // be a match when generator expressions are involved.
- return true;
- }
- // Also see LinearGetSourceFileWithOutput.
- if (!cmSystemTools::FileIsFullPath(name)) {
- return AnyOutputMatches(name, this->DelayedOutputFiles);
- }
- // Otherwise we use an efficient lookup map.
- auto o = this->OutputToSource.find(name);
- if (o != this->OutputToSource.end()) {
- return o->second.SourceMightBeOutput;
- }
- return false;
-}
-
-void cmMakefile::AddTargetByproducts(
- cmTarget* target, const std::vector<std::string>& byproducts)
-{
- for (std::string const& o : byproducts) {
- this->UpdateOutputToSourceMap(o, target);
- }
-}
-
-void cmMakefile::AddSourceOutputs(cmSourceFile* source,
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts)
-{
- for (std::string const& o : outputs) {
- this->UpdateOutputToSourceMap(o, source, false);
- }
- for (std::string const& o : byproducts) {
- this->UpdateOutputToSourceMap(o, source, true);
- }
-}
-
-void cmMakefile::UpdateOutputToSourceMap(std::string const& byproduct,
- cmTarget* target)
-{
- SourceEntry entry;
- entry.Sources.Target = target;
-
- auto pr = this->OutputToSource.emplace(byproduct, entry);
- if (!pr.second) {
- SourceEntry& current = pr.first->second;
- // Has the target already been set?
- if (!current.Sources.Target) {
- current.Sources.Target = target;
- } else {
- // Multiple custom commands/targets produce the same output (source file
- // or target). See also comment in other UpdateOutputToSourceMap
- // overload.
- //
- // TODO: Warn the user about this case.
- }
- }
-}
-
-void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
- cmSourceFile* source, bool byproduct)
-{
- SourceEntry entry;
- entry.Sources.Source = source;
- entry.Sources.SourceIsByproduct = byproduct;
- entry.SourceMightBeOutput = !byproduct;
-
- auto pr = this->OutputToSource.emplace(output, entry);
- if (!pr.second) {
- SourceEntry& current = pr.first->second;
- // Outputs take precedence over byproducts
- if (!current.Sources.Source ||
- (current.Sources.SourceIsByproduct && !byproduct)) {
- current.Sources.Source = source;
- current.Sources.SourceIsByproduct = false;
- current.SourceMightBeOutput = true;
- } else {
- // Multiple custom commands produce the same output but may
- // be attached to a different source file (MAIN_DEPENDENCY).
- // LinearGetSourceFileWithOutput would return the first one,
- // so keep the mapping for the first one.
- //
- // TODO: Warn the user about this case. However, the VS 8 generator
- // triggers it for separate generate.stamp rules in ZERO_CHECK and
- // individual targets.
- }
- }
}
#if !defined(CMAKE_BOOTSTRAP)
@@ -2685,7 +2445,7 @@ cmMakefile::AppleSDK cmMakefile::GetAppleSDKType() const
bool cmMakefile::PlatformIsAppleEmbedded() const
{
- return GetAppleSDKType() != AppleSDK::MacOS;
+ return this->GetAppleSDKType() != AppleSDK::MacOS;
}
const char* cmMakefile::GetSONameFlag(const std::string& language) const
@@ -2696,7 +2456,7 @@ const char* cmMakefile::GetSONameFlag(const std::string& language) const
name += language;
}
name += "_FLAG";
- return cmToCStr(GetDefinition(name));
+ return cmToCStr(this->GetDefinition(name));
}
bool cmMakefile::CanIWriteThisFile(std::string const& fileName) const
@@ -2719,7 +2479,7 @@ const std::string& cmMakefile::GetRequiredDefinition(
const std::string& name) const
{
static std::string const empty;
- const std::string* def = GetDefinition(name);
+ const std::string* def = this->GetDefinition(name);
if (!def) {
cmSystemTools::Error("Error required internal CMake variable not "
"set, cmake may not be built correctly.\n"
@@ -2779,7 +2539,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 = GetDefinition(name);
+ const std::string* def = this->GetDefinition(name);
if (!def) {
return empty;
}
@@ -2845,24 +2605,24 @@ const std::string& cmMakefile::ExpandVariablesInString(
// Suppress variable watches to avoid calling hooks twice. Suppress new
// dereferences since the OLD behavior is still what is actually used.
this->SuppressSideEffects = true;
- newError = ExpandVariablesInStringNew(newErrorstr, newResult,
- escapeQuotes, noEscapes, atOnly,
- filename, line, replaceAt);
+ newError = this->ExpandVariablesInStringNew(
+ newErrorstr, newResult, escapeQuotes, noEscapes, atOnly, filename,
+ line, replaceAt);
this->SuppressSideEffects = false;
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
- mtype =
- ExpandVariablesInStringOld(errorstr, source, escapeQuotes, noEscapes,
- atOnly, filename, line, removeEmpty, true);
+ mtype = this->ExpandVariablesInStringOld(errorstr, source, escapeQuotes,
+ noEscapes, atOnly, filename,
+ line, removeEmpty, true);
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
// Messaging here would be *very* verbose.
case cmPolicies::NEW:
- mtype =
- ExpandVariablesInStringNew(errorstr, source, escapeQuotes, noEscapes,
- atOnly, filename, line, replaceAt);
+ mtype = this->ExpandVariablesInStringNew(errorstr, source, escapeQuotes,
+ noEscapes, atOnly, filename,
+ line, replaceAt);
break;
}
@@ -3055,7 +2815,7 @@ void cmMakefile::SetRecursionDepth(int recursionDepth)
this->RecursionDepth = recursionDepth;
}
-std::string cmMakefile::NewDeferId()
+std::string cmMakefile::NewDeferId() const
{
return this->GetGlobalGenerator()->NewDeferId();
}
@@ -3616,7 +3376,7 @@ cmSourceFile* cmMakefile::GetSource(const std::string& sourceName,
#endif
auto sfsi = this->SourceFileSearchIndex.find(name);
if (sfsi != this->SourceFileSearchIndex.end()) {
- for (auto sf : sfsi->second) {
+ for (auto* sf : sfsi->second) {
if (sf->Matches(sfl)) {
return sf;
}
@@ -3629,11 +3389,7 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName,
bool generated,
cmSourceFileLocationKind kind)
{
- auto sf = cm::make_unique<cmSourceFile>(this, sourceName, kind);
- if (generated) {
- sf->SetProperty("GENERATED", "1");
- }
-
+ auto sf = cm::make_unique<cmSourceFile>(this, sourceName, generated, kind);
auto name =
this->GetCMakeInstance()->StripExtension(sf->GetLocation().GetName());
#if defined(_WIN32) || defined(__APPLE__)
@@ -3665,7 +3421,7 @@ cmSourceFile* cmMakefile::GetOrCreateGeneratedSource(
{
cmSourceFile* sf =
this->GetOrCreateSource(sourceName, true, cmSourceFileLocationKind::Known);
- sf->SetProperty("GENERATED", "1");
+ sf->MarkAsGenerated(); // In case we did not create the source file.
return sf;
}
@@ -3675,38 +3431,10 @@ void cmMakefile::CreateGeneratedOutputs(
for (std::string const& o : outputs) {
if (cmGeneratorExpression::Find(o) == std::string::npos) {
this->GetOrCreateGeneratedSource(o);
- this->AddDelayedOutput(o);
- } else {
- this->DelayedOutputFilesHaveGenex = true;
}
}
}
-void cmMakefile::CreateGeneratedByproducts(
- const std::vector<std::string>& byproducts)
-{
- for (std::string const& o : byproducts) {
- if (cmGeneratorExpression::Find(o) == std::string::npos) {
- this->GetOrCreateGeneratedSource(o);
- }
- }
-}
-
-void cmMakefile::AddDelayedOutput(std::string const& output)
-{
- // Note that this vector might contain the output names in a different order
- // than in source file iteration order.
- this->DelayedOutputFiles.push_back(output);
-
- SourceEntry entry;
- entry.SourceMightBeOutput = true;
-
- auto pr = this->OutputToSource.emplace(output, entry);
- if (!pr.second) {
- pr.first->second.SourceMightBeOutput = true;
- }
-}
-
void cmMakefile::AddTargetObject(std::string const& tgtName,
std::string const& objFile)
{
@@ -4094,8 +3822,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
int cmMakefile::ConfigureFile(const std::string& infile,
const std::string& outfile, bool copyonly,
bool atOnly, bool escapeQuotes,
- bool use_source_permissions,
- cmNewLineStyle newLine)
+ mode_t permissions, cmNewLineStyle newLine)
{
int res = 1;
if (!this->CanIWriteThisFile(outfile)) {
@@ -4117,12 +3844,8 @@ int cmMakefile::ConfigureFile(const std::string& infile,
// output files that now don't exist.
this->AddCMakeOutputFile(soutfile);
- mode_t perm = 0;
- if (!use_source_permissions) {
- perm = perm | mode_owner_read | mode_owner_write | mode_group_read |
- mode_world_read;
- } else {
- cmSystemTools::GetPermissions(sinfile, perm);
+ if (permissions == 0) {
+ cmSystemTools::GetPermissions(sinfile, permissions);
}
std::string::size_type pos = soutfile.rfind('/');
@@ -4137,7 +3860,7 @@ int cmMakefile::ConfigureFile(const std::string& infile,
cmSystemTools::GetLastSystemError());
return 0;
}
- if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+ if (!cmSystemTools::SetPermissions(soutfile, permissions)) {
this->IssueMessage(MessageType::FATAL_ERROR,
cmSystemTools::GetLastSystemError());
return 0;
@@ -4194,7 +3917,7 @@ int cmMakefile::ConfigureFile(const std::string& infile,
cmSystemTools::GetLastSystemError());
res = 0;
} else {
- if (!cmSystemTools::SetPermissions(soutfile, perm)) {
+ if (!cmSystemTools::SetPermissions(soutfile, permissions)) {
this->IssueMessage(MessageType::FATAL_ERROR,
cmSystemTools::GetLastSystemError());
res = 0;
@@ -4283,7 +4006,7 @@ cmTest* cmMakefile::GetTest(const std::string& testName) const
}
void cmMakefile::GetTests(const std::string& config,
- std::vector<cmTest*>& tests)
+ std::vector<cmTest*>& tests) const
{
for (const auto& generator : this->GetTestGenerators()) {
if (generator->TestsForConfig(config)) {
@@ -4633,7 +4356,7 @@ cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id,
return this->StateSnapshot.GetPolicy(id, parent_scope);
}
-bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var)
+bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var) const
{
// Check for an explicit CMAKE_POLICY_WARNING_CMP<NNNN> setting.
if (cmProp val = this->GetDefinition(var)) {
@@ -4670,7 +4393,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::CMP0072 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0075 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
@@ -4738,7 +4461,7 @@ bool cmMakefile::HasCMP0054AlreadyBeenReported(
return !this->CMP0054ReportedIds.insert(context).second;
}
-void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
+void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) const
{
/* Record the setting of every policy. */
using PolicyID = cmPolicies::PolicyID;
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index c7940fb40..71d765c71 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -20,6 +20,8 @@
#include "cmsys/RegularExpression.hxx"
+#include "cm_sys_stat.h"
+
#include "cmAlgorithms.h"
#include "cmCustomCommandTypes.h"
#include "cmListFileCache.h"
@@ -59,24 +61,6 @@ class cmTestGenerator;
class cmVariableWatch;
class cmake;
-/** Flag if byproducts shall also be considered. */
-enum class cmSourceOutputKind
-{
- OutputOnly,
- OutputOrByproduct
-};
-
-/** Target and source file which have a specific output. */
-struct cmSourcesWithOutput
-{
- /** Target with byproduct. */
- cmTarget* Target = nullptr;
-
- /** Source file with output or byproduct. */
- cmSourceFile* Source = nullptr;
- bool SourceIsByproduct = false;
-};
-
/** A type-safe wrapper for a string representing a directory id. */
class cmDirectoryId
{
@@ -185,7 +169,8 @@ public:
const std::string& target, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir, bool escapeOldStyle = true,
+ const char* comment, const char* workingDir,
+ cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle = true,
bool uses_terminal = false, const std::string& depfile = "",
const std::string& job_pool = "", bool command_expand_lists = false,
bool stdPipesUTF8 = false);
@@ -202,11 +187,11 @@ public:
const std::string& output, const std::vector<std::string>& depends,
const std::string& main_dependency,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, const CommandSourceCallback& callback = nullptr,
- bool replace = false, bool escapeOldStyle = true,
- bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& depfile = "", const std::string& job_pool = "",
- bool stdPipesUTF8 = false);
+ const char* workingDir, cmPolicies::PolicyStatus cmp0116,
+ const CommandSourceCallback& callback = nullptr, bool replace = false,
+ bool escapeOldStyle = true, bool uses_terminal = false,
+ bool command_expand_lists = false, const std::string& depfile = "",
+ const std::string& job_pool = "", bool stdPipesUTF8 = false);
void AddCustomCommandToOutput(
const std::vector<std::string>& outputs,
const std::vector<std::string>& byproducts,
@@ -214,36 +199,24 @@ public:
const std::string& main_dependency,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, const CommandSourceCallback& callback = nullptr,
- bool replace = false, bool escapeOldStyle = true,
- bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& depfile = "", const std::string& job_pool = "",
- bool stdPipesUTF8 = false);
+ const char* workingDir, cmPolicies::PolicyStatus cmp0116,
+ const CommandSourceCallback& callback = nullptr, bool replace = false,
+ bool escapeOldStyle = true, bool uses_terminal = false,
+ bool command_expand_lists = false, const std::string& depfile = "",
+ const std::string& job_pool = "", bool stdPipesUTF8 = false);
void AddCustomCommandOldStyle(const std::string& target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const std::string& source,
const cmCustomCommandLines& commandLines,
- const char* comment);
- bool AppendCustomCommandToOutput(
+ const char* comment,
+ cmPolicies::PolicyStatus cmp0116);
+ void AppendCustomCommandToOutput(
const std::string& output, const std::vector<std::string>& depends,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines);
/**
- * Add target byproducts.
- */
- void AddTargetByproducts(cmTarget* target,
- const std::vector<std::string>& byproducts);
-
- /**
- * Add source file outputs.
- */
- void AddSourceOutputs(cmSourceFile* source,
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts);
-
- /**
* Add a define flag to the build.
*/
void AddDefineFlag(std::string const& definition);
@@ -272,11 +245,6 @@ public:
bool excludeFromAll = false);
/**
- * Return the utility target output source file name and the CMP0049 name.
- */
- cmUtilityOutput GetUtilityOutput(cmTarget* target);
-
- /**
* Dispatch adding a utility to the build. A utility target is a command
* that is run every time the target is built.
*/
@@ -284,10 +252,10 @@ public:
const std::string& utilityName, bool excludeFromAll,
const char* workingDir, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
- const char* comment = nullptr, bool uses_terminal = false,
- bool command_expand_lists = false, const std::string& job_pool = "",
- bool stdPipesUTF8 = false);
+ const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
+ bool escapeOldStyle = true, const char* comment = nullptr,
+ bool uses_terminal = false, bool command_expand_lists = false,
+ const std::string& job_pool = "", bool stdPipesUTF8 = false);
/**
* Add a subdirectory to the build.
@@ -326,7 +294,7 @@ public:
const char* doc, cmStateEnums::CacheEntryType type,
bool force = false)
{
- AddCacheDefinition(name, value.c_str(), doc, type, force);
+ this->AddCacheDefinition(name, value.c_str(), doc, type, force);
}
/**
@@ -335,7 +303,7 @@ public:
*/
void RemoveDefinition(const std::string& name);
//! Remove a definition from the cache.
- void RemoveCacheDefinition(const std::string& name);
+ void RemoveCacheDefinition(const std::string& name) const;
/**
* Specify the name of the project for this build.
@@ -376,7 +344,7 @@ public:
bool parent_scope = false) const;
bool SetPolicyVersion(std::string const& version_min,
std::string const& version_max);
- void RecordPolicies(cmPolicies::PolicyMap& pm);
+ void RecordPolicies(cmPolicies::PolicyMap& pm) const;
//@}
/** Helper class to push and pop policies automatically. */
@@ -430,8 +398,7 @@ public:
}
const char* GetIncludeRegularExpression() const
{
- cmProp p = this->GetProperty("INCLUDE_REGULAR_EXPRESSION");
- return p ? p->c_str() : nullptr;
+ return cmToCStr(this->GetProperty("INCLUDE_REGULAR_EXPRESSION"));
}
/**
@@ -690,8 +657,7 @@ public:
*/
int ConfigureFile(const std::string& infile, const std::string& outfile,
bool copyonly, bool atOnly, bool escapeQuotes,
- bool use_source_permissions,
- cmNewLineStyle = cmNewLineStyle());
+ mode_t permissions = 0, cmNewLineStyle = cmNewLineStyle());
/**
* Print a command's invocation
@@ -753,20 +719,10 @@ public:
return this->SourceFiles;
}
- /**
- * Return the target if the provided source name is a byproduct of a utility
- * target or a PRE_BUILD, PRE_LINK, or POST_BUILD command.
- * Return the source file which has the provided source name as output.
- */
- cmSourcesWithOutput GetSourcesWithOutput(const std::string& name) const;
-
- /**
- * Is there a source file that has the provided source name as an output?
- * If so then return it.
- */
- cmSourceFile* GetSourceFileWithOutput(
- const std::string& name,
- cmSourceOutputKind kind = cmSourceOutputKind::OutputOnly) const;
+ std::vector<cmTarget*> const& GetOrderedTargets() const
+ {
+ return this->OrderedTargets;
+ }
//! Add a new cmTest to the list of tests for this makefile.
cmTest* CreateTest(const std::string& testName);
@@ -779,7 +735,7 @@ public:
/**
* Get all tests that run under the given configuration.
*/
- void GetTests(const std::string& config, std::vector<cmTest*>& tests);
+ void GetTests(const std::string& config, std::vector<cmTest*>& tests) const;
/**
* Return a location of a file in cmake or custom modules directory
@@ -926,7 +882,7 @@ public:
return this->SystemIncludeDirectories;
}
- bool PolicyOptionalWarningEnabled(std::string const& var);
+ bool PolicyOptionalWarningEnabled(std::string const& var) const;
void PushLoopBlock();
void PopLoopBlock();
@@ -945,6 +901,7 @@ public:
const std::string& inputFile, const std::string& targetName,
std::unique_ptr<cmCompiledGeneratorExpression> outputName,
std::unique_ptr<cmCompiledGeneratorExpression> condition,
+ const std::string& newLineCharacter, mode_t permissions,
bool inputIsContent);
const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>&
GetEvaluationFiles() const;
@@ -967,7 +924,7 @@ public:
int GetRecursionDepth() const;
void SetRecursionDepth(int recursionDepth);
- std::string NewDeferId();
+ std::string NewDeferId() const;
bool DeferCall(std::string id, std::string fileName, cmListFileFunction lff);
bool DeferCancelCall(std::string const& id);
cm::optional<std::string> DeferGetCallIds() const;
@@ -983,8 +940,7 @@ protected:
mutable cmTargetMap Targets;
std::map<std::string, std::string> AliasTargets;
- using TargetsVec = std::vector<cmTarget*>;
- TargetsVec OrderedTargets;
+ std::vector<cmTarget*> OrderedTargets;
std::vector<std::unique_ptr<cmSourceFile>> SourceFiles;
@@ -1129,48 +1085,9 @@ private:
bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
void CreateGeneratedOutputs(const std::vector<std::string>& outputs);
- void CreateGeneratedByproducts(const std::vector<std::string>& byproducts);
std::vector<BT<GeneratorAction>> GeneratorActions;
bool GeneratorActionsInvoked = false;
- bool DelayedOutputFilesHaveGenex = false;
- std::vector<std::string> DelayedOutputFiles;
-
- void AddDelayedOutput(std::string const& output);
-
- /**
- * See LinearGetSourceFileWithOutput for background information
- */
- cmTarget* LinearGetTargetWithOutput(const std::string& name) const;
-
- /**
- * Generalized old version of GetSourceFileWithOutput kept for
- * backward-compatibility. It implements a linear search and supports
- * relative file paths. It is used as a fall back by GetSourceFileWithOutput
- * and GetSourcesWithOutput.
- */
- cmSourceFile* LinearGetSourceFileWithOutput(const std::string& name,
- cmSourceOutputKind kind,
- bool& byproduct) const;
-
- struct SourceEntry
- {
- cmSourcesWithOutput Sources;
- bool SourceMightBeOutput = false;
- };
-
- // A map for fast output to input look up.
- using OutputToSourceMap = std::unordered_map<std::string, SourceEntry>;
- OutputToSourceMap OutputToSource;
-
- void UpdateOutputToSourceMap(std::string const& byproduct, cmTarget* target);
- void UpdateOutputToSourceMap(std::string const& output, cmSourceFile* source,
- bool byproduct);
-
- /**
- * Return if the provided source file might have a custom command.
- */
- bool MightHaveCustomCommand(const std::string& name) const;
bool CheckSystemVars;
bool CheckCMP0000;
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 871878c0b..1750e37ad 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
#include "cmOutputConverter.h"
+#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -232,10 +233,10 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
std::string launcher;
- const char* val = this->LocalGenerator->GetRuleLauncher(
- this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
}
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -591,10 +592,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
std::string launcher;
- const char* val = this->LocalGenerator->GetRuleLauncher(
- this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
}
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index b32ea6a24..ce64e2cfa 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
#include "cmOutputConverter.h"
+#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -366,10 +367,10 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
std::string launcher;
- const char* val = this->LocalGenerator->GetRuleLauncher(
- this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
}
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -816,10 +817,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.LanguageCompileFlags = langFlags.c_str();
std::string launcher;
- const char* val = this->LocalGenerator->GetRuleLauncher(
- this->GeneratorTarget, "RULE_LAUNCH_LINK");
+ cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
}
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index c6d6c9946..4918bf676 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -12,7 +12,9 @@
#include <utility>
#include <cm/memory>
+#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
@@ -23,6 +25,7 @@
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmLocalCommonGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmMakefileExecutableTargetGenerator.h"
@@ -68,7 +71,8 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
this->CMP0113New = true;
break;
}
- MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this);
+ this->MacOSXContentGenerator =
+ cm::make_unique<MacOSXContentGeneratorType>(this);
}
cmMakefileTargetGenerator::~cmMakefileTargetGenerator() = default;
@@ -325,28 +329,80 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< cmSystemTools::ConvertToOutputPath(
this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull))
- << "\n\n";
+ << "\n";
- if (!this->NoRuleMessages) {
- // Include the progress variables for the target.
+ std::string depsUseCompiler = "CMAKE_DEPENDS_USE_COMPILER";
+ if (!this->Makefile->IsDefinitionSet(depsUseCompiler) ||
+ this->Makefile->IsOn(depsUseCompiler)) {
+ std::string compilerDependFile =
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
*this->BuildFileStream
- << "# Include the progress variables for this target.\n"
+ << "# Include any dependencies generated by the "
+ "compiler for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
- this->ProgressFileNameFull))
+ this->LocalGenerator->GetBinaryDirectory(), compilerDependFile))
<< "\n\n";
- }
- // make sure the depend file exists
- if (!cmSystemTools::FileExists(dependFileNameFull)) {
// Write an empty dependency file.
cmGeneratedFileStream depFileStream(
- dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
- depFileStream << "# Empty dependencies file for "
+ compilerDependFile, false, this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# Empty compiler generated dependencies file for "
<< this->GeneratorTarget->GetName() << ".\n"
<< "# This may be replaced when dependencies are built.\n";
+ // remove internal dependency file
+ cmSystemTools::RemoveFile(
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.internal"));
+
+ std::string compilerDependTimestamp =
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
+ if (!cmSystemTools::FileExists(compilerDependTimestamp)) {
+ // Write a dependency timestamp file.
+ cmGeneratedFileStream timestampFileStream(
+ compilerDependTimestamp, false,
+ this->GlobalGenerator->GetMakefileEncoding());
+ timestampFileStream
+ << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Timestamp file for compiler generated dependencies "
+ "management for "
+ << this->GeneratorTarget->GetName() << ".\n";
+ }
+
+ // deactivate no longer needed legacy dependency files
+ // Write an empty dependency file.
+ cmGeneratedFileStream legacyDepFileStream(
+ dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
+ legacyDepFileStream
+ << "# Empty dependencies file for " << this->GeneratorTarget->GetName()
+ << ".\n"
+ << "# This may be replaced when dependencies are built.\n";
+ // remove internal dependency file
+ cmSystemTools::RemoveFile(
+ cmStrCat(this->TargetBuildDirectoryFull, "/depend.internal"));
+ } else {
+ // make sure the depend file exists
+ if (!cmSystemTools::FileExists(dependFileNameFull)) {
+ // Write an empty dependency file.
+ cmGeneratedFileStream depFileStream(
+ dependFileNameFull, false,
+ this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# Empty dependencies file for "
+ << this->GeneratorTarget->GetName() << ".\n"
+ << "# This may be replaced when dependencies are built.\n";
+ }
+ }
+
+ if (!this->NoRuleMessages) {
+ // Include the progress variables for the target.
+ *this->BuildFileStream
+ << "# Include the progress variables for this target.\n"
+ << this->GlobalGenerator->IncludeDirective << " " << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ this->ProgressFileNameFull))
+ << "\n\n";
}
// Open the flags file. This should be copy-if-different because the
@@ -472,6 +528,14 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
return;
}
+ // Use compiler to generate dependencies, if supported.
+ bool compilerGenerateDeps =
+ this->GlobalGenerator->SupportsCompilerDependencies() &&
+ cmIsOn(this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_DEPENDS_USE_COMPILER")));
+ auto scanner = compilerGenerateDeps ? cmDependencyScannerKind::Compiler
+ : cmDependencyScannerKind::CMake;
+
// Get the full path name of the object file.
std::string const& objectName =
this->GeneratorTarget->GetObjectName(&source);
@@ -511,7 +575,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string srcFullPath =
cmSystemTools::CollapseFullPath(source.GetFullPath());
this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang,
- objFullPath, srcFullPath);
+ objFullPath, srcFullPath, scanner);
this->LocalGenerator->AppendRuleDepend(depends,
this->FlagFileNameFull.c_str());
@@ -553,8 +617,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
depends.push_back(
this->GeneratorTarget->GetPchFile(config, lang, arch));
}
- this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang,
- objFullPath, pchHeader);
+ this->LocalGenerator->AddImplicitDepends(
+ this->GeneratorTarget, lang, objFullPath, pchHeader, scanner);
}
}
@@ -573,6 +637,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// Build the set of compiler flags.
std::string flags;
+ // Explicitly add the explicit language flag before any other flag
+ // so user flags can override it.
+ this->GeneratorTarget->AddExplicitLanguageFlags(flags, source);
+
// Add language-specific flags.
std::string langFlags = cmStrCat("$(", lang, "_FLAGS", filterArch, ")");
this->LocalGenerator->AppendFlags(flags, langFlags);
@@ -693,7 +761,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
source.GetFullPath(), cmOutputConverter::SHELL);
// Construct the build message.
- std::vector<std::string> no_commands;
+ std::vector<std::string> no_depends;
std::vector<std::string> commands;
// add in a progress call if needed
@@ -747,6 +815,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// avoiding a trailing backslash in the argument.
targetOutPathCompilePDB.back() = '/';
}
+
+ std::string compilePdbOutputPath =
+ this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName());
+ cmSystemTools::MakeDirectory(compilePdbOutputPath);
}
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
@@ -787,13 +859,34 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
"$(" + lang + "_INCLUDES)");
vars.Includes = includesString.c_str();
+ std::string dependencyTarget;
+ std::string shellDependencyFile;
+ std::string dependencyTimestamp;
+ if (compilerGenerateDeps) {
+ dependencyTarget = this->LocalGenerator->EscapeForShell(
+ this->LocalGenerator->ConvertToMakefilePath(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(), relativeObj)));
+ vars.DependencyTarget = dependencyTarget.c_str();
+
+ auto depFile = cmStrCat(obj, ".d");
+ shellDependencyFile = this->LocalGenerator->ConvertToOutputFormat(
+ depFile, cmOutputConverter::SHELL);
+ vars.DependencyFile = shellDependencyFile.c_str();
+ this->CleanFiles.insert(depFile);
+
+ dependencyTimestamp = this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
+ }
+
// At the moment, it is assumed that C, C++, Fortran, and CUDA have both
// assembly and preprocessor capabilities. The same is true for the
// ability to export compile commands
bool lang_has_preprocessor =
((lang == "C") || (lang == "CXX") || (lang == "OBJC") ||
(lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA") ||
- lang == "ISPC");
+ lang == "ISPC" || lang == "ASM");
bool const lang_has_assembly = lang_has_preprocessor;
bool const lang_can_export_cmds = lang_has_preprocessor;
@@ -824,7 +917,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
cmExpandList(compileRule, compileCommands);
}
- if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
+ if (this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS") &&
lang_can_export_cmds && compileCommands.size() == 1) {
std::string compileCommand = compileCommands[0];
@@ -875,15 +968,21 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
}
// Maybe insert an include-what-you-use runner.
- if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) {
- std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
- cmProp iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
+ if (!compileCommands.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) {
std::string const tidy_prop = lang + "_CLANG_TIDY";
cmProp tidy = this->GeneratorTarget->GetProperty(tidy_prop);
- std::string const cpplint_prop = lang + "_CPPLINT";
- cmProp cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
- std::string const cppcheck_prop = lang + "_CPPCHECK";
- cmProp cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
+ cmProp iwyu = nullptr;
+ cmProp cpplint = nullptr;
+ cmProp cppcheck = nullptr;
+ if (lang == "C" || lang == "CXX") {
+ std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
+ iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
+ std::string const cpplint_prop = lang + "_CPPLINT";
+ cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
+ std::string const cppcheck_prop = lang + "_CPPCHECK";
+ cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
+ }
if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
cmNonempty(cppcheck)) {
std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
@@ -945,10 +1044,57 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string launcher;
{
- const char* val = this->LocalGenerator->GetRuleLauncher(
+ cmProp val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_COMPILE");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
+ }
+ }
+
+ std::string flagsWithDeps(flags);
+
+ if (compilerGenerateDeps) {
+ // Injects dependency computation
+ auto depFlags = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_DEPFILE_FLAGS_", lang));
+
+ if (!depFlags.empty()) {
+ // Add dependency flags
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ depFlags, vars);
+ flagsWithDeps.append(1, ' ');
+ flagsWithDeps.append(depFlags);
+ }
+ vars.Flags = flagsWithDeps.c_str();
+
+ const auto& extraCommands = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS"));
+ if (!extraCommands.empty()) {
+ auto commandList = cmExpandedList(extraCommands);
+ compileCommands.insert(compileCommands.end(), commandList.cbegin(),
+ commandList.cend());
+ }
+
+ const auto& depFormat = this->Makefile->GetRequiredDefinition(
+ cmStrCat("CMAKE_", lang, "_DEPFILE_FORMAT"));
+
+ if (depFormat == "msvc"_s) {
+ // compiler must be launched through a wrapper to pick-up dependencies
+ std::string depFilter =
+ "$(CMAKE_COMMAND) -E cmake_cl_compile_depends ";
+ depFilter += cmStrCat("--dep-file=", shellDependencyFile);
+ depFilter +=
+ cmStrCat(" --working-dir=",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ cmOutputConverter::SHELL));
+ const auto& prefix = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_CL_SHOWINCLUDES_PREFIX"));
+ depFilter += cmStrCat(" --filter-prefix=",
+ this->LocalGenerator->ConvertToOutputFormat(
+ prefix, cmOutputConverter::SHELL));
+ depFilter += " -- ";
+ compileCommands.front().insert(0, depFilter);
}
}
@@ -977,8 +1123,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
cmExpandList(evaluated_outputs, outputs);
}
}
- if (!ispcHeaderRelative
- .empty()) { // can't move ispcHeader as vars is using it
+ if (!ispcHeaderRelative.empty()) {
+ // can't move ispcHeader as vars is using it
outputs.emplace_back(ispcHeaderRelative);
}
@@ -986,10 +1132,19 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
this->CleanFiles.insert(outputs.begin() + 1, outputs.end());
}
+ if (compilerGenerateDeps) {
+ depends.push_back(dependencyTimestamp);
+ }
+
// Write the rule.
this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
commands);
+ if (compilerGenerateDeps) {
+ // set back flags without dependency generation
+ vars.Flags = flags.c_str();
+ }
+
bool do_preprocess_rules = lang_has_preprocessor &&
this->LocalGenerator->GetCreatePreprocessedSourceRules();
bool do_assembly_rules =
@@ -1386,10 +1541,10 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
std::string registerFileCmd;
- // The generated register file contains macros that when expanded register
- // the device routines. Because the routines are the same for all
- // architectures the register file will be the same too. Thus generate it
- // only on the first invocation to reduce overhead.
+ // The generated register file contains macros that when expanded
+ // register the device routines. Because the routines are the same for
+ // all architectures the register file will be the same too. Thus
+ // generate it only on the first invocation to reduce overhead.
if (fatbinaryDepends.size() == 1) {
std::string registerFileRel =
this->LocalGenerator->MaybeConvertToRelativePath(
@@ -1424,7 +1579,8 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
fatbinaryOutputRel, fatbinaryDepends,
{ fatbinaryCommand }, false);
- // Compile the stub that registers the kernels and contains the fatbinaries.
+ // Compile the stub that registers the kernels and contains the
+ // fatbinaries.
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
vars.CMTargetType =
@@ -1481,6 +1637,16 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
std::vector<std::string> depends;
this->LocalGenerator->AppendCustomDepend(depends, ccg);
+ if (!ccg.GetCC().GetDepfile().empty()) {
+ // Add dependency over timestamp file for dependencies management
+ auto dependTimestamp = cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));
+
+ depends.push_back(dependTimestamp);
+ }
+
// Write the rule.
const std::vector<std::string>& outputs = ccg.GetOutputs();
bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs,
@@ -1517,6 +1683,15 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
objFullPath, srcFullPath);
}
+ // Setup implicit depend for depfile if any
+ if (!ccg.GetCC().GetDepfile().empty()) {
+ std::string objFullPath = cmSystemTools::CollapseFullPath(
+ outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory());
+ this->LocalGenerator->AddImplicitDepends(
+ this->GeneratorTarget, "CUSTOM", objFullPath, ccg.GetFullDepfile(),
+ cmDependencyScannerKind::Compiler);
+ }
+
this->CustomCommandOutputs.insert(outputs.begin(), outputs.end());
}
@@ -1542,12 +1717,7 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
<< this->GeneratorTarget->GetName() << "\n"
<< variableName << " =";
std::string object;
- std::string lineContinue;
- if (cmProp p = this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE")) {
- lineContinue = *p;
- } else {
- lineContinue = "\\";
- }
+ const auto& lineContinue = this->GlobalGenerator->LineContinueDirective;
cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
@@ -1555,7 +1725,7 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) {
continue;
}
- *this->BuildFileStream << " " << lineContinue << "\n";
+ *this->BuildFileStream << " " << lineContinue;
*this->BuildFileStream
<< cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
obj, useWatcomQuote);
@@ -1578,7 +1748,7 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
for (std::string const& obj : this->ExternalObjects) {
object =
this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, obj);
- *this->BuildFileStream << " " << lineContinue << "\n";
+ *this->BuildFileStream << " " << lineContinue;
*this->BuildFileStream
<< cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
obj, useWatcomQuote);
@@ -1842,9 +2012,9 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
if (size_t const limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
// Compute the total length of our list of object files with room
// for argument separation and quoting. This does not convert paths
- // relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so the
- // actual list will likely be much shorter than this. However, in the
- // worst case all objects will remain as absolute paths.
+ // relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so
+ // the actual list will likely be much shorter than this. However, in
+ // the worst case all objects will remain as absolute paths.
size_t length = 0;
for (std::string const& obj : this->Objects) {
length += obj.size() + 3;
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index 6c18e482e..a885b1716 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -15,6 +15,7 @@
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
@@ -36,10 +37,42 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
*this->BuildFileStream << "# Utility rule file for "
<< this->GeneratorTarget->GetName() << ".\n\n";
+ const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
+ ? "$(CMAKE_BINARY_DIR)/"
+ : "");
+
+ // Include the dependencies for the target.
+ std::string dependFile =
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
+ *this->BuildFileStream
+ << "# Include any custom commands dependencies for this target.\n"
+ << this->GlobalGenerator->IncludeDirective << " " << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(), dependFile))
+ << "\n\n";
+ if (!cmSystemTools::FileExists(dependFile)) {
+ // Write an empty dependency file.
+ cmGeneratedFileStream depFileStream(
+ dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# Empty custom commands generated dependencies file for "
+ << this->GeneratorTarget->GetName() << ".\n"
+ << "# This may be replaced when dependencies are built.\n";
+ }
+
+ std::string dependTimestamp =
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
+ if (!cmSystemTools::FileExists(dependTimestamp)) {
+ // Write a dependency timestamp file.
+ cmGeneratedFileStream depFileStream(
+ dependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Timestamp file for custom commands dependencies "
+ "management for "
+ << this->GeneratorTarget->GetName() << ".\n";
+ }
+
if (!this->NoRuleMessages) {
- const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
- ? "$(CMAKE_BINARY_DIR)/"
- : "");
// Include the progress variables for the target.
*this->BuildFileStream
<< "# Include the progress variables for this target.\n"
diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx
index a121332b2..28baeb69d 100644
--- a/Source/cmNewLineStyle.cxx
+++ b/Source/cmNewLineStyle.cxx
@@ -8,13 +8,13 @@ cmNewLineStyle::cmNewLineStyle() = default;
bool cmNewLineStyle::IsValid() const
{
- return NewLineStyle != Invalid;
+ return this->NewLineStyle != Invalid;
}
bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args,
std::string& errorString)
{
- NewLineStyle = Invalid;
+ this->NewLineStyle = Invalid;
for (size_t i = 0; i < args.size(); i++) {
if (args[i] == "NEWLINE_STYLE") {
@@ -22,11 +22,11 @@ bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args,
if (args.size() > styleIndex) {
std::string const& eol = args[styleIndex];
if (eol == "LF" || eol == "UNIX") {
- NewLineStyle = LF;
+ this->NewLineStyle = LF;
return true;
}
if (eol == "CRLF" || eol == "WIN32" || eol == "DOS") {
- NewLineStyle = CRLF;
+ this->NewLineStyle = CRLF;
return true;
}
errorString = "NEWLINE_STYLE sets an unknown style, only LF, "
@@ -43,7 +43,7 @@ bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args,
std::string cmNewLineStyle::GetCharacters() const
{
- switch (NewLineStyle) {
+ switch (this->NewLineStyle) {
case Invalid:
return "";
case LF:
@@ -56,10 +56,10 @@ std::string cmNewLineStyle::GetCharacters() const
void cmNewLineStyle::SetStyle(Style style)
{
- NewLineStyle = style;
+ this->NewLineStyle = style;
}
cmNewLineStyle::Style cmNewLineStyle::GetStyle() const
{
- return NewLineStyle;
+ return this->NewLineStyle;
}
diff --git a/Source/cmNinjaLinkLineComputer.cxx b/Source/cmNinjaLinkLineComputer.cxx
index 7fbeeeaa3..2304ad284 100644
--- a/Source/cmNinjaLinkLineComputer.cxx
+++ b/Source/cmNinjaLinkLineComputer.cxx
@@ -18,5 +18,5 @@ cmNinjaLinkLineComputer::cmNinjaLinkLineComputer(
std::string cmNinjaLinkLineComputer::ConvertToLinkReference(
std::string const& lib) const
{
- return GG->ConvertToNinjaPath(lib);
+ return this->GG->ConvertToNinjaPath(lib);
}
diff --git a/Source/cmNinjaLinkLineDeviceComputer.cxx b/Source/cmNinjaLinkLineDeviceComputer.cxx
index 84c1b37d3..f66e2f511 100644
--- a/Source/cmNinjaLinkLineDeviceComputer.cxx
+++ b/Source/cmNinjaLinkLineDeviceComputer.cxx
@@ -16,5 +16,5 @@ cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer(
std::string cmNinjaLinkLineDeviceComputer::ConvertToLinkReference(
std::string const& lib) const
{
- return GG->ConvertToNinjaPath(lib);
+ return this->GG->ConvertToNinjaPath(lib);
}
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index ccb959b01..49e5e4cc6 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -12,6 +12,7 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/vector>
#include "cmComputeLinkInformation.h"
@@ -49,7 +50,7 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
// on Windows the output dir is already needed at compile time
// ensure the directory exists (OutDir test)
for (auto const& config : this->GetConfigNames()) {
- EnsureDirectoryExists(target->GetDirectory(config));
+ this->EnsureDirectoryExists(target->GetDirectory(config));
}
}
@@ -266,10 +267,10 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule(
vars.LanguageCompileFlags = "$LANGUAGE_COMPILE_FLAGS";
std::string launcher;
- const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+ cmProp val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
}
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -306,7 +307,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
{
const cmMakefile* mf = this->GetMakefile();
- cmNinjaRule rule(LanguageLinkerCudaDeviceRule(config));
+ cmNinjaRule rule(this->LanguageLinkerCudaDeviceRule(config));
rule.Command = this->GetLocalGenerator()->BuildCommandLine(
{ cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"),
" -arch=$ARCH $REGISTER -o=$out $in") });
@@ -334,13 +335,13 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
compileCmd, vars);
- rule.Name = LanguageLinkerCudaDeviceCompileRule(config);
+ rule.Name = this->LanguageLinkerCudaDeviceCompileRule(config);
rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd });
rule.Comment = "Rule for compiling CUDA device stubs.";
rule.Description = "Compiling CUDA device stub $out";
this->GetGlobalGenerator()->AddRule(rule);
- rule.Name = LanguageLinkerCudaFatbinaryRule(config);
+ rule.Name = this->LanguageLinkerCudaFatbinaryRule(config);
rule.Command = this->GetLocalGenerator()->BuildCommandLine(
{ cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"),
" -64 -cmdline=--compile-only -compress-all -link "
@@ -385,7 +386,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
// build response file name
std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
- cmProp flag = GetMakefile()->GetDefinition(cmakeLinkVar);
+ cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
if (flag) {
responseFlag = *flag;
@@ -452,10 +453,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
}
std::string launcher;
- const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+ cmProp val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
}
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -673,7 +674,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement(
targetOutputDir = globalGen->ExpandCFGIntDir(targetOutputDir, config);
std::string targetOutputReal =
- ConvertToNinjaPath(targetOutputDir + "cmake_device_link" + objExt);
+ this->ConvertToNinjaPath(targetOutputDir + "cmake_device_link" + objExt);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(targetOutputReal);
@@ -730,7 +731,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatements(
this->GetGlobalGenerator()->ConfigDirectory(config));
const std::string ninjaOutputDir = this->ConvertToNinjaPath(objectDir);
- cmNinjaBuild fatbinary(LanguageLinkerCudaFatbinaryRule(config));
+ cmNinjaBuild fatbinary(this->LanguageLinkerCudaFatbinaryRule(config));
// Link device code for each architecture.
for (const std::string& architectureKind : architectures) {
@@ -744,7 +745,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatements(
cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin);
fatbinary.ExplicitDeps.emplace_back(cubin);
- cmNinjaBuild dlink(LanguageLinkerCudaDeviceRule(config));
+ cmNinjaBuild dlink(this->LanguageLinkerCudaDeviceRule(config));
dlink.ExplicitDeps = explicitDeps;
dlink.Outputs = { cubin };
dlink.Variables["ARCH"] = cmStrCat("sm_", architecture);
@@ -767,7 +768,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatements(
fatbinary);
// Compile the stub that registers the kernels and contains the fatbinaries.
- cmNinjaBuild dcompile(LanguageLinkerCudaDeviceCompileRule(config));
+ cmNinjaBuild dcompile(this->LanguageLinkerCudaDeviceCompileRule(config));
dcompile.Outputs = { output };
dcompile.ExplicitDeps = { cmStrCat(ninjaOutputDir, "/cmake_cuda_fatbin.h") };
dcompile.Variables["FATBIN"] =
@@ -787,7 +788,7 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
cmGeneratorTarget* genTarget = this->GetGeneratorTarget();
cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator();
- std::string targetOutputImplib = ConvertToNinjaPath(
+ std::string targetOutputImplib = this->ConvertToNinjaPath(
genTarget->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
if (config != fileConfig) {
@@ -806,7 +807,7 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact)
.empty() &&
targetOutputImplib ==
- ConvertToNinjaPath(genTarget->GetFullPath(
+ this->ConvertToNinjaPath(genTarget->GetFullPath(
fileConfig, cmStateEnums::ImportLibraryArtifact))) {
return;
}
@@ -882,16 +883,16 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
- EnsureParentDirectoryExists(impLibPath);
+ this->EnsureParentDirectoryExists(impLibPath);
}
const std::string objPath =
- cmStrCat(GetGeneratorTarget()->GetSupportDirectory(),
+ cmStrCat(this->GetGeneratorTarget()->GetSupportDirectory(),
globalGen->ConfigDirectory(config));
vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
- EnsureDirectoryExists(objPath);
+ this->EnsureDirectoryExists(objPath);
this->SetMsvcTargetPdbVariable(vars, config);
@@ -933,21 +934,22 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator();
cmGeneratorTarget* gt = this->GetGeneratorTarget();
- std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(config));
- std::string targetOutputReal = ConvertToNinjaPath(
+ std::string targetOutput = this->ConvertToNinjaPath(gt->GetFullPath(config));
+ std::string targetOutputReal = this->ConvertToNinjaPath(
gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact,
/*realname=*/true));
- std::string targetOutputImplib = ConvertToNinjaPath(
+ std::string targetOutputImplib = this->ConvertToNinjaPath(
gt->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
if (config != fileConfig) {
- if (targetOutput == ConvertToNinjaPath(gt->GetFullPath(fileConfig))) {
+ if (targetOutput ==
+ this->ConvertToNinjaPath(gt->GetFullPath(fileConfig))) {
return;
}
if (targetOutputReal ==
- ConvertToNinjaPath(gt->GetFullPath(fileConfig,
- cmStateEnums::RuntimeBinaryArtifact,
- /*realname=*/true))) {
+ this->ConvertToNinjaPath(
+ gt->GetFullPath(fileConfig, cmStateEnums::RuntimeBinaryArtifact,
+ /*realname=*/true))) {
return;
}
if (!gt->GetFullName(config, cmStateEnums::ImportLibraryArtifact)
@@ -955,7 +957,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
!gt->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact)
.empty() &&
targetOutputImplib ==
- ConvertToNinjaPath(gt->GetFullPath(
+ this->ConvertToNinjaPath(gt->GetFullPath(
fileConfig, cmStateEnums::ImportLibraryArtifact))) {
return;
}
@@ -1095,7 +1097,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
std::vector<std::string> extraISPCObjects =
this->GetGeneratorTarget()->GetGeneratedISPCObjects(config);
std::transform(extraISPCObjects.begin(), extraISPCObjects.end(),
- std::back_inserter(linkBuild.ExplicitDeps), MapToNinjaPath());
+ std::back_inserter(linkBuild.ExplicitDeps),
+ this->MapToNinjaPath());
linkBuild.ImplicitDeps =
this->ComputeLinkDeps(this->TargetLinkLanguage(config), config);
@@ -1189,7 +1192,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
- EnsureParentDirectoryExists(impLibPath);
+ this->EnsureParentDirectoryExists(impLibPath);
if (gt->HasImportLibrary(config)) {
byproducts.push_back(targetOutputImplib);
if (firstForConfig) {
@@ -1218,7 +1221,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
cmStrCat(gt->GetSupportDirectory(), globalGen->ConfigDirectory(config));
vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
- EnsureDirectoryExists(objPath);
+ this->EnsureDirectoryExists(objPath);
std::string& linkLibraries = vars["LINK_LIBRARIES"];
std::string& link_path = vars["LINK_PATH"];
@@ -1236,22 +1239,25 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
std::vector<std::string> preLinkCmdLines;
std::vector<std::string> postBuildCmdLines;
- if (config == fileConfig) {
- std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
- &preLinkCmdLines,
- &postBuildCmdLines };
-
- for (unsigned i = 0; i != 3; ++i) {
- for (cmCustomCommand const& cc : *cmdLists[i]) {
- cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator());
+ std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
+ &preLinkCmdLines,
+ &postBuildCmdLines };
+
+ for (unsigned i = 0; i != 3; ++i) {
+ for (cmCustomCommand const& cc : *cmdLists[i]) {
+ if (config == fileConfig ||
+ this->GetLocalGenerator()->HasUniqueByproducts(cc.GetByproducts(),
+ cc.GetBacktrace())) {
+ cmCustomCommandGenerator ccg(cc, fileConfig, this->GetLocalGenerator(),
+ 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), MapToNinjaPath());
+ std::back_inserter(byproducts), this->MapToNinjaPath());
std::transform(
ccByproducts.begin(), ccByproducts.end(),
std::back_inserter(globalGen->GetByproductsForCleanTarget()),
- MapToNinjaPath());
+ this->MapToNinjaPath());
}
}
}
@@ -1272,7 +1278,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
obj_list_file, cmOutputConverter::SHELL);
- cmProp nm_executable = GetMakefile()->GetDefinition("CMAKE_NM");
+ cmProp nm_executable = this->GetMakefile()->GetDefinition("CMAKE_NM");
if (cmNonempty(nm_executable)) {
cmd += " --nm=";
cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
@@ -1325,7 +1331,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
// build response file name
std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
- cmProp flag = GetMakefile()->GetDefinition(cmakeLinkVar);
+ cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
bool const lang_supports_response =
!(this->TargetLinkLanguage(config) == "RC" ||
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index ffc405c70..30127fe8b 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -52,7 +52,6 @@ private:
std::vector<std::string> ComputeLinkCmd(const std::string& config);
std::vector<std::string> ComputeDeviceLinkCmd();
-private:
// Target name info.
cmGeneratorTarget::Names TargetNames(const std::string& config) const;
std::string TargetLinkLanguage(const std::string& config) const;
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index d41cbd286..672b5797e 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -12,7 +12,9 @@
#include <utility>
#include <cm/memory>
+#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include <cm3p/json/value.h>
#include <cm3p/json/writer.h>
@@ -33,6 +35,7 @@
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
+#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -105,7 +108,7 @@ std::string cmNinjaTargetGenerator::LanguageCompilerRule(
'_', config);
}
-std::string cmNinjaTargetGenerator::LanguagePreprocessRule(
+std::string cmNinjaTargetGenerator::LanguagePreprocessAndScanRule(
std::string const& lang, const std::string& config) const
{
return cmStrCat(
@@ -114,7 +117,7 @@ std::string cmNinjaTargetGenerator::LanguagePreprocessRule(
'_', config);
}
-std::string cmNinjaTargetGenerator::LanguageDependencyRule(
+std::string cmNinjaTargetGenerator::LanguageScanRule(
std::string const& lang, const std::string& config) const
{
return cmStrCat(
@@ -129,14 +132,7 @@ bool cmNinjaTargetGenerator::NeedExplicitPreprocessing(
return lang == "Fortran";
}
-bool cmNinjaTargetGenerator::UsePreprocessedSource(
- std::string const& lang) const
-{
- return lang == "Fortran";
-}
-
-bool cmNinjaTargetGenerator::CompilePreprocessedSourceWithDefines(
- std::string const& lang) const
+bool cmNinjaTargetGenerator::CompileWithDefines(std::string const& lang) const
{
return this->Makefile->IsOn(
cmStrCat("CMAKE_", lang, "_COMPILE_WITH_DEFINES"));
@@ -151,9 +147,26 @@ std::string cmNinjaTargetGenerator::LanguageDyndepRule(
'_', config);
}
-bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const
+bool cmNinjaTargetGenerator::NeedCxxModuleSupport(
+ std::string const& lang, std::string const& config) const
{
- return lang == "Fortran";
+ if (lang != "CXX") {
+ return false;
+ }
+ if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) {
+ return false;
+ }
+ cmGeneratorTarget const* tgt = this->GetGeneratorTarget();
+ cmStandardLevelResolver standardResolver(this->Makefile);
+ bool const uses_cxx20 =
+ standardResolver.HaveStandardAvailable(tgt, "CXX", config, "cxx_std_20");
+ return uses_cxx20 && this->GetGlobalGenerator()->CheckCxxModuleSupport();
+}
+
+bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang,
+ std::string const& config) const
+{
+ return lang == "Fortran" || this->NeedCxxModuleSupport(lang, config);
}
std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget(
@@ -190,7 +203,15 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
}
- std::string flags = this->GetFlags(language, config, filterArch);
+ std::string flags;
+ // Explicitly add the explicit language flag before any other flag
+ // so user flags can override it.
+ this->GeneratorTarget->AddExplicitLanguageFlags(flags, *source);
+
+ if (!flags.empty()) {
+ flags += " ";
+ }
+ flags += this->GetFlags(language, config, filterArch);
// Add Fortran format flags.
if (language == "Fortran") {
@@ -252,32 +273,6 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
this->LocalGenerator->AppendFlags(languageFlags, includeFlags);
}
-bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const
-{
- std::string const& deptype = this->GetMakefile()->GetSafeDefinition(
- cmStrCat("CMAKE_NINJA_DEPTYPE_", lang));
- if (deptype == "msvc") {
- return true;
- }
- if (deptype == "intel") {
- // Ninja does not really define "intel", but we use it to switch based
- // on whether this environment supports "gcc" or "msvc" deptype.
- if (!this->GetGlobalGenerator()->SupportsMultilineDepfile()) {
- // This ninja version is too old to support the Intel depfile format.
- // Fall back to msvc deptype.
- return true;
- }
- if ((this->Makefile->GetHomeDirectory().find(' ') != std::string::npos) ||
- (this->Makefile->GetHomeOutputDirectory().find(' ') !=
- std::string::npos)) {
- // The Intel compiler does not properly escape spaces in a depfile.
- // Fall back to msvc deptype.
- return true;
- }
- }
- return false;
-}
-
// TODO: Refactor with
// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
@@ -355,7 +350,8 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
const std::vector<std::string>& deps = cli->GetDepends();
cmNinjaDeps result(deps.size());
- std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
+ std::transform(deps.begin(), deps.end(), result.begin(),
+ this->MapToNinjaPath());
// Add a dependency on the link definitions file, if any.
if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
@@ -376,7 +372,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
std::vector<std::string> linkDeps;
this->GeneratorTarget->GetLinkDepends(linkDeps, config, linkLanguage);
std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result),
- MapToNinjaPath());
+ this->MapToNinjaPath());
return result;
}
@@ -384,7 +380,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
std::string cmNinjaTargetGenerator::GetSourceFilePath(
cmSourceFile const* source) const
{
- return ConvertToNinjaPath(source->GetFullPath());
+ return this->ConvertToNinjaPath(source->GetFullPath());
}
std::string cmNinjaTargetGenerator::GetObjectFilePath(
@@ -465,7 +461,7 @@ std::string cmNinjaTargetGenerator::GetTargetOutputDir(
const std::string& config) const
{
std::string dir = this->GeneratorTarget->GetDirectory(config);
- return ConvertToNinjaPath(dir);
+ return this->ConvertToNinjaPath(dir);
}
std::string cmNinjaTargetGenerator::GetTargetFilePath(
@@ -502,13 +498,13 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(
}
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- ConvertToNinjaPath(pdbPath), cmOutputConverter::SHELL);
+ this->ConvertToNinjaPath(pdbPath), cmOutputConverter::SHELL);
vars["TARGET_COMPILE_PDB"] =
this->GetLocalGenerator()->ConvertToOutputFormat(
- ConvertToNinjaPath(compilePdbPath), cmOutputConverter::SHELL);
+ this->ConvertToNinjaPath(compilePdbPath), cmOutputConverter::SHELL);
- EnsureParentDirectoryExists(pdbPath);
- EnsureParentDirectoryExists(compilePdbPath);
+ this->EnsureParentDirectoryExists(pdbPath);
+ this->EnsureParentDirectoryExists(compilePdbPath);
return true;
}
return false;
@@ -527,82 +523,62 @@ namespace {
// Create the command to run the dependency scanner
std::string GetScanCommand(const std::string& cmakeCmd, const std::string& tdi,
const std::string& lang, const std::string& ppFile,
- bool needDyndep, const std::string& ddiFile)
+ const std::string& ddiFile)
{
- std::string ccmd =
- cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi, " --lang=", lang,
- " --pp=", ppFile, " --dep=$DEP_FILE");
- if (needDyndep) {
- ccmd = cmStrCat(ccmd, " --obj=$OBJ_FILE --ddi=", ddiFile);
- }
- return ccmd;
+ return cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi,
+ " --lang=", lang, " --src=$in", " --pp=", ppFile,
+ " --dep=$DEP_FILE --obj=$OBJ_FILE --ddi=", ddiFile);
}
-// Helper function to create dependency scanning rule, with optional
-// explicit preprocessing step if preprocessCommand is non-empty
-cmNinjaRule GetPreprocessScanRule(
- const std::string& ruleName, cmRulePlaceholderExpander::RuleVariables& vars,
+// Helper function to create dependency scanning rule that may or may
+// not perform explicit preprocessing too.
+cmNinjaRule GetScanRule(
+ const std::string& ruleName,
+ cmRulePlaceholderExpander::RuleVariables const& vars,
const std::string& responseFlag, const std::string& flags,
- const std::string& launcher,
cmRulePlaceholderExpander* const rulePlaceholderExpander,
- std::string scanCommand, cmLocalNinjaGenerator* generator,
- const std::string& preprocessCommand = "")
+ cmLocalNinjaGenerator* generator, std::vector<std::string> scanCmds)
{
cmNinjaRule rule(ruleName);
- // Explicit preprocessing always uses a depfile.
+ // Scanning always uses a depfile for preprocessor dependencies.
rule.DepType = ""; // no deps= for multiple outputs
rule.DepFile = "$DEP_FILE";
- cmRulePlaceholderExpander::RuleVariables ppVars;
- ppVars.CMTargetName = vars.CMTargetName;
- ppVars.CMTargetType = vars.CMTargetType;
- ppVars.Language = vars.Language;
- ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
- ppVars.PreprocessedSource = "$out";
- ppVars.DependencyFile = rule.DepFile.c_str();
-
- // Preprocessing uses the original source, compilation uses
- // preprocessed output or original source
- ppVars.Source = vars.Source;
- vars.Source = "$in";
-
- // Copy preprocessor definitions to the preprocessor rule.
- ppVars.Defines = vars.Defines;
+ cmRulePlaceholderExpander::RuleVariables scanVars;
+ scanVars.CMTargetName = vars.CMTargetName;
+ scanVars.CMTargetType = vars.CMTargetType;
+ scanVars.Language = vars.Language;
+ scanVars.Object = "$OBJ_FILE";
+ scanVars.PreprocessedSource = "$out";
+ scanVars.DynDepFile = "$DYNDEP_INTERMEDIATE_FILE";
+ scanVars.DependencyFile = rule.DepFile.c_str();
+ scanVars.DependencyTarget = "$out";
- // Copy include directories to the preprocessor rule. The Fortran
- // compilation rule still needs them for the INCLUDE directive.
- ppVars.Includes = vars.Includes;
+ // Scanning needs the same preprocessor settings as direct compilation would.
+ scanVars.Source = vars.Source;
+ scanVars.Defines = vars.Defines;
+ scanVars.Includes = vars.Includes;
- // Preprocessing and compilation use the same flags.
- std::string ppFlags = flags;
+ // Scanning needs the compilation flags too.
+ std::string scanFlags = flags;
// If using a response file, move defines, includes, and flags into it.
if (!responseFlag.empty()) {
rule.RspFile = "$RSP_FILE";
rule.RspContent =
- cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags);
- ppFlags = cmStrCat(responseFlag, rule.RspFile);
- ppVars.Defines = "";
- ppVars.Includes = "";
+ cmStrCat(' ', scanVars.Defines, ' ', scanVars.Includes, ' ', scanFlags);
+ scanFlags = cmStrCat(responseFlag, rule.RspFile);
+ scanVars.Defines = "";
+ scanVars.Includes = "";
}
- ppVars.Flags = ppFlags.c_str();
-
- // Rule for preprocessing source file.
- std::vector<std::string> ppCmds;
+ scanVars.Flags = scanFlags.c_str();
- if (!preprocessCommand.empty()) {
- // Lookup the explicit preprocessing rule.
- cmExpandList(preprocessCommand, ppCmds);
- for (std::string& i : ppCmds) {
- i = cmStrCat(launcher, i);
- rulePlaceholderExpander->ExpandRuleVariables(generator, i, ppVars);
- }
+ // Rule for scanning a source file.
+ for (std::string& scanCmd : scanCmds) {
+ rulePlaceholderExpander->ExpandRuleVariables(generator, scanCmd, scanVars);
}
-
- // Run CMake dependency scanner on either preprocessed output or source file
- ppCmds.emplace_back(std::move(scanCommand));
- rule.Command = generator->BuildCommandLine(ppCmds);
+ rule.Command = generator->BuildCommandLine(scanCmds);
return rule;
}
@@ -628,11 +604,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
cmMakefile* mf = this->GetMakefile();
- // For some cases we do an explicit preprocessor invocation.
- bool const explicitPP = this->NeedExplicitPreprocessing(lang);
- bool const compilePPWithDefines = this->UsePreprocessedSource(lang) &&
- this->CompilePreprocessedSourceWithDefines(lang);
- bool const needDyndep = this->NeedDyndep(lang);
+ // For some cases we scan to dynamically discover dependencies.
+ bool const needDyndep = this->NeedDyndep(lang, config);
+ bool const compilationPreprocesses = !this->NeedExplicitPreprocessing(lang);
std::string flags = "$FLAGS";
@@ -646,65 +620,97 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
responseFlag = "@";
}
}
+ std::string const modmapFormatVar =
+ cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_MODULE_MAP_FORMAT");
+ std::string const modmapFormat =
+ this->Makefile->GetSafeDefinition(modmapFormatVar);
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat(
- ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)),
+ this->ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)),
cmLocalGenerator::SHELL);
std::string launcher;
- const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+ cmProp val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE");
if (cmNonempty(val)) {
- launcher = cmStrCat(val, ' ');
+ launcher = cmStrCat(*val, ' ');
}
std::string const cmakeCmd =
this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- if (explicitPP) {
- // Combined preprocessing and dependency scanning
- const auto ppScanCommand = GetScanCommand(
- cmakeCmd, tdi, lang, "$out", needDyndep, "$DYNDEP_INTERMEDIATE_FILE");
- const auto ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE");
-
- auto ppRule = GetPreprocessScanRule(
- this->LanguagePreprocessRule(lang, config), vars, responseFlag, flags,
- launcher, rulePlaceholderExpander.get(), ppScanCommand,
- this->GetLocalGenerator(), mf->GetRequiredDefinition(ppVar));
-
- // Write the rule for preprocessing file of the given language.
- ppRule.Comment = cmStrCat("Rule for preprocessing ", lang, " files.");
- ppRule.Description = cmStrCat("Building ", lang, " preprocessed $out");
+ if (needDyndep) {
+ // Rule to scan dependencies of sources that need preprocessing.
+ {
+ std::vector<std::string> scanCommands;
+ std::string scanRuleName;
+ if (compilationPreprocesses) {
+ scanRuleName = this->LanguageScanRule(lang, config);
+ std::string const& scanCommand = mf->GetRequiredDefinition(
+ cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_SCANDEP_SOURCE"));
+ cmExpandList(scanCommand, scanCommands);
+ for (std::string& i : scanCommands) {
+ i = cmStrCat(launcher, i);
+ }
+ } else {
+ scanRuleName = this->LanguagePreprocessAndScanRule(lang, config);
+ std::string const& ppCommmand = mf->GetRequiredDefinition(
+ cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE"));
+ cmExpandList(ppCommmand, scanCommands);
+ for (std::string& i : scanCommands) {
+ i = cmStrCat(launcher, i);
+ }
+ scanCommands.emplace_back(GetScanCommand(cmakeCmd, tdi, lang, "$out",
+ "$DYNDEP_INTERMEDIATE_FILE"));
+ }
- this->GetGlobalGenerator()->AddRule(ppRule);
+ auto scanRule = GetScanRule(
+ scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(),
+ this->GetLocalGenerator(), std::move(scanCommands));
+
+ scanRule.Comment =
+ cmStrCat("Rule for generating ", lang, " dependencies.");
+ if (compilationPreprocesses) {
+ scanRule.Description =
+ cmStrCat("Scanning $in for ", lang, " dependencies");
+ } else {
+ scanRule.Description =
+ cmStrCat("Building ", lang, " preprocessed $out");
+ }
- if (!compilePPWithDefines) {
- // Remove preprocessor definitions from compilation step
- vars.Defines = "";
+ this->GetGlobalGenerator()->AddRule(scanRule);
}
- // Just dependency scanning for files that have preprocessing turned off
- const auto scanCommand =
- GetScanCommand(cmakeCmd, tdi, lang, "$in", needDyndep, "$out");
+ if (!compilationPreprocesses) {
+ // Compilation will not preprocess, so it does not need the defines
+ // unless the compiler wants them for some other purpose.
+ if (!this->CompileWithDefines(lang)) {
+ vars.Defines = "";
+ }
- auto scanRule = GetPreprocessScanRule(
- this->LanguageDependencyRule(lang, config), vars, "", flags, launcher,
- rulePlaceholderExpander.get(), scanCommand, this->GetLocalGenerator());
+ // Rule to scan dependencies of sources that do not need preprocessing.
+ std::string const& scanRuleName = this->LanguageScanRule(lang, config);
+ std::vector<std::string> scanCommands;
+ scanCommands.emplace_back(
+ GetScanCommand(cmakeCmd, tdi, lang, "$in", "$out"));
- // Write the rule for generating dependencies for the given language.
- scanRule.Comment = cmStrCat("Rule for generating ", lang,
- " dependencies on non-preprocessed files.");
- scanRule.Description =
- cmStrCat("Generating ", lang, " dependencies for $in");
+ auto scanRule = GetScanRule(
+ scanRuleName, vars, "", flags, rulePlaceholderExpander.get(),
+ this->GetLocalGenerator(), std::move(scanCommands));
- this->GetGlobalGenerator()->AddRule(scanRule);
- }
+ // Write the rule for generating dependencies for the given language.
+ scanRule.Comment = cmStrCat("Rule for generating ", lang,
+ " dependencies on non-preprocessed files.");
+ scanRule.Description =
+ cmStrCat("Generating ", lang, " dependencies for $in");
+
+ this->GetGlobalGenerator()->AddRule(scanRule);
+ }
- if (needDyndep) {
// Write the rule for ninja dyndep file generation.
cmNinjaRule rule(this->LanguageDyndepRule(lang, config));
// Command line length is almost always limited -> use response file for
@@ -714,12 +720,16 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
// Run CMake dependency scanner on the source file (using the preprocessed
// source if that was performed).
+ std::string ddModmapArg;
+ if (!modmapFormat.empty()) {
+ ddModmapArg += cmStrCat(" --modmapfmt=", modmapFormat);
+ }
{
std::vector<std::string> ddCmds;
{
- std::string ccmd =
- cmStrCat(cmakeCmd, " -E cmake_ninja_dyndep --tdi=", tdi,
- " --lang=", lang, " --dd=$out @", rule.RspFile);
+ std::string ccmd = cmStrCat(
+ cmakeCmd, " -E cmake_ninja_dyndep --tdi=", tdi, " --lang=", lang,
+ ddModmapArg, " --dd=$out @", rule.RspFile);
ddCmds.emplace_back(std::move(ccmd));
}
rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds);
@@ -743,12 +753,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
// Tell ninja dependency format so all deps can be loaded into a database
std::string cldeps;
- if (explicitPP) {
- // The explicit preprocessing step will handle dependency scanning.
- } else if (this->NeedDepTypeMSVC(lang)) {
- rule.DepType = "msvc";
- rule.DepFile.clear();
- flags += " /showIncludes";
+ if (!compilationPreprocesses) {
+ // The compiler will not do preprocessing, so it has no such dependencies.
} else if (mf->IsOn(cmStrCat("CMAKE_NINJA_CMCLDEPS_", lang))) {
// For the MS resource compiler we need cmcldeps, but skip dependencies
// for source-file try_compile cases because they are always fresh.
@@ -764,20 +770,35 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
"\" \"", cl, "\" ");
}
} else {
- rule.DepType = "gcc";
- rule.DepFile = "$DEP_FILE";
+ const auto& depType = this->GetMakefile()->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_DEPFILE_FORMAT"));
+ if (depType == "msvc"_s) {
+ rule.DepType = "msvc";
+ rule.DepFile.clear();
+ } else {
+ rule.DepType = "gcc";
+ rule.DepFile = "$DEP_FILE";
+ }
+ vars.DependencyFile = rule.DepFile.c_str();
+ vars.DependencyTarget = "$out";
+
const std::string flagsName = cmStrCat("CMAKE_DEPFILE_FLAGS_", lang);
std::string depfileFlags = mf->GetSafeDefinition(flagsName);
if (!depfileFlags.empty()) {
- cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE");
- cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out");
- cmSystemTools::ReplaceString(
- depfileFlags, "<CMAKE_C_COMPILER>",
- cmToCStr(mf->GetDefinition("CMAKE_C_COMPILER")));
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+ depfileFlags, vars);
flags += cmStrCat(' ', depfileFlags);
}
}
+ if (needDyndep && !modmapFormat.empty()) {
+ std::string modmapFlags = mf->GetRequiredDefinition(
+ cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_MODULE_MAP_FLAG"));
+ cmSystemTools::ReplaceString(modmapFlags, "<MODULE_MAP_FILE>",
+ "$DYNDEP_MODULE_MAP_FILE");
+ flags += cmStrCat(' ', modmapFlags);
+ }
+
vars.Flags = flags.c_str();
vars.DependencyFile = rule.DepFile.c_str();
@@ -815,15 +836,21 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
}
// Maybe insert an include-what-you-use runner.
- if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) {
- std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
- cmProp iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
+ if (!compileCmds.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) {
std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY");
cmProp tidy = this->GeneratorTarget->GetProperty(tidy_prop);
- std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT");
- cmProp cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
- std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
- cmProp cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
+ cmProp iwyu = nullptr;
+ cmProp cpplint = nullptr;
+ cmProp cppcheck = nullptr;
+ if (lang == "C" || lang == "CXX") {
+ std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
+ iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
+ std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT");
+ cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
+ std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
+ cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
+ }
if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
cmNonempty(cppcheck)) {
std::string run_iwyu = cmStrCat(cmakeCmd, " -E __run_co_compile");
@@ -887,6 +914,14 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
compileCmds.front().insert(0, cldeps);
}
+ const auto& extraCommands = this->GetMakefile()->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS"));
+ if (!extraCommands.empty()) {
+ auto commandList = cmExpandedList(extraCommands);
+ compileCmds.insert(compileCmds.end(), commandList.cbegin(),
+ commandList.cend());
+ }
+
for (std::string& i : compileCmds) {
i = cmStrCat(launcher, i);
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i,
@@ -939,7 +974,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
config);
}
if (firstForConfig) {
- cmProp pchExtension = GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
+ cmProp pchExtension =
+ this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
this->GeneratorTarget->GetExternalObjects(externalObjects, config);
@@ -973,9 +1009,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
const std::vector<std::string>& ccbyproducts = ccg.GetByproducts();
std::transform(ccoutputs.begin(), ccoutputs.end(),
- std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ std::back_inserter(orderOnlyDeps),
+ this->MapToNinjaPath());
std::transform(ccbyproducts.begin(), ccbyproducts.end(),
- std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ std::back_inserter(orderOnlyDeps),
+ this->MapToNinjaPath());
}
std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end());
@@ -1062,78 +1100,91 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
}
namespace {
-cmNinjaBuild GetPreprocessOrScanBuild(
- const std::string& ruleName, const std::string& ppFileName, bool compilePP,
- bool compilePPWithDefines, cmNinjaBuild& objBuild, cmNinjaVars& vars,
- const std::string& depFileName, bool needDyndep,
- const std::string& objectFileName)
+cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
+ const std::string& ppFileName,
+ bool compilePP, bool compilePPWithDefines,
+ cmNinjaBuild& objBuild, cmNinjaVars& vars,
+ std::string const& modmapFormat,
+ const std::string& objectFileName,
+ cmLocalGenerator* lg)
{
- // Explicit preprocessing and dependency
- cmNinjaBuild ppBuild(ruleName);
+ cmNinjaBuild scanBuild(ruleName);
if (!ppFileName.empty()) {
- ppBuild.Outputs.push_back(ppFileName);
- ppBuild.RspFile = cmStrCat(ppFileName, ".rsp");
+ scanBuild.RspFile = cmStrCat(ppFileName, ".rsp");
} else {
- ppBuild.RspFile = "$out.rsp";
+ scanBuild.RspFile = "$out.rsp";
}
if (compilePP) {
- // Move compilation dependencies to the preprocessing build statement.
- std::swap(ppBuild.ExplicitDeps, objBuild.ExplicitDeps);
- std::swap(ppBuild.ImplicitDeps, objBuild.ImplicitDeps);
- std::swap(ppBuild.OrderOnlyDeps, objBuild.OrderOnlyDeps);
- std::swap(ppBuild.Variables["IN_ABS"], vars["IN_ABS"]);
+ // Move compilation dependencies to the scan/preprocessing build statement.
+ std::swap(scanBuild.ExplicitDeps, objBuild.ExplicitDeps);
+ std::swap(scanBuild.ImplicitDeps, objBuild.ImplicitDeps);
+ std::swap(scanBuild.OrderOnlyDeps, objBuild.OrderOnlyDeps);
+ std::swap(scanBuild.Variables["IN_ABS"], vars["IN_ABS"]);
// The actual compilation will now use the preprocessed source.
objBuild.ExplicitDeps.push_back(ppFileName);
} else {
- // Copy compilation dependencies to the preprocessing build statement.
- ppBuild.ExplicitDeps = objBuild.ExplicitDeps;
- ppBuild.ImplicitDeps = objBuild.ImplicitDeps;
- ppBuild.OrderOnlyDeps = objBuild.OrderOnlyDeps;
- ppBuild.Variables["IN_ABS"] = vars["IN_ABS"];
+ // Copy compilation dependencies to the scan/preprocessing build statement.
+ scanBuild.ExplicitDeps = objBuild.ExplicitDeps;
+ scanBuild.ImplicitDeps = objBuild.ImplicitDeps;
+ scanBuild.OrderOnlyDeps = objBuild.OrderOnlyDeps;
+ scanBuild.Variables["IN_ABS"] = vars["IN_ABS"];
}
- // Preprocessing and compilation generally use the same flags.
- ppBuild.Variables["FLAGS"] = vars["FLAGS"];
+ // Scanning and compilation generally use the same flags.
+ scanBuild.Variables["FLAGS"] = vars["FLAGS"];
if (compilePP && !compilePPWithDefines) {
- // Move preprocessor definitions to the preprocessor build statement.
- std::swap(ppBuild.Variables["DEFINES"], vars["DEFINES"]);
+ // Move preprocessor definitions to the scan/preprocessor build statement.
+ std::swap(scanBuild.Variables["DEFINES"], vars["DEFINES"]);
} else {
- // Copy preprocessor definitions to the preprocessor build statement.
- ppBuild.Variables["DEFINES"] = vars["DEFINES"];
+ // Copy preprocessor definitions to the scan/preprocessor build statement.
+ scanBuild.Variables["DEFINES"] = vars["DEFINES"];
}
// Copy include directories to the preprocessor build statement. The
// Fortran compilation build statement still needs them for the INCLUDE
// directive.
- ppBuild.Variables["INCLUDES"] = vars["INCLUDES"];
+ scanBuild.Variables["INCLUDES"] = vars["INCLUDES"];
- // Explicit preprocessing always uses a depfile.
- ppBuild.Variables["DEP_FILE"] = depFileName;
+ // Tell dependency scanner the object file that will result from
+ // compiling the source.
+ scanBuild.Variables["OBJ_FILE"] = objectFileName;
+
+ // Tell dependency scanner where to store dyndep intermediate results.
+ std::string const& ddiFile = cmStrCat(objectFileName, ".ddi");
+ scanBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
+
+ // Outputs of the scan/preprocessor build statement.
+ if (!ppFileName.empty()) {
+ scanBuild.Outputs.push_back(ppFileName);
+ scanBuild.ImplicitOuts.push_back(ddiFile);
+ } else {
+ scanBuild.Outputs.push_back(ddiFile);
+ }
+
+ // Scanning always uses a depfile for preprocessor dependencies.
+ std::string const& depFileName = cmStrCat(scanBuild.Outputs.front(), ".d");
+ scanBuild.Variables["DEP_FILE"] =
+ lg->ConvertToOutputFormat(depFileName, cmOutputConverter::SHELL);
if (compilePP) {
// The actual compilation does not need a depfile because it
// depends on the already-preprocessed source.
vars.erase("DEP_FILE");
}
- if (needDyndep) {
- // Tell dependency scanner the object file that will result from
- // compiling the source.
- ppBuild.Variables["OBJ_FILE"] = objectFileName;
-
- // Tell dependency scanner where to store dyndep intermediate results.
- std::string const ddiFile = cmStrCat(objectFileName, ".ddi");
- if (ppFileName.empty()) {
- ppBuild.Outputs.push_back(ddiFile);
- } else {
- ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
- ppBuild.ImplicitOuts.push_back(ddiFile);
- }
+ if (!modmapFormat.empty()) {
+ // XXX(modmap): If changing this path construction, change
+ // `cmGlobalNinjaGenerator::WriteDyndep` to expect the corresponding
+ // file path.
+ std::string const ddModmapFile = cmStrCat(objectFileName, ".modmap");
+ scanBuild.Variables["DYNDEP_MODULE_MAP_FILE"] = ddModmapFile;
+ scanBuild.ImplicitOuts.push_back(ddModmapFile);
}
- return ppBuild;
+
+ return scanBuild;
}
}
@@ -1157,7 +1208,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
// build response file name
std::string cmakeLinkVar = cmStrCat(cmakeVarLang, "_RESPONSE_FILE_FLAG");
- cmProp flag = GetMakefile()->GetDefinition(cmakeLinkVar);
+ cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
bool const lang_supports_response =
!(language == "RC" || (language == "CUDA" && !flag));
@@ -1170,7 +1221,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["DEFINES"] = this->ComputeDefines(source, language, config);
vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
- if (!this->NeedDepTypeMSVC(language)) {
+ if (this->GetMakefile()->GetSafeDefinition(
+ cmStrCat("CMAKE_", language, "_DEPFILE_FORMAT")) != "msvc"_s) {
bool replaceExt(false);
if (!language.empty()) {
std::string repVar =
@@ -1253,7 +1305,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
std::transform(depList.begin(), depList.end(),
std::back_inserter(objBuild.ImplicitDeps),
- MapToNinjaPath());
+ this->MapToNinjaPath());
}
objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config));
@@ -1270,13 +1322,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
sourceFileName, objBuild.OrderOnlyDeps);
}
- // For some cases we need to generate a ninja dyndep file.
- bool const needDyndep = this->NeedDyndep(language);
+ // For some cases we scan to dynamically discover dependencies.
+ bool const needDyndep = this->NeedDyndep(language, config);
+ bool const compilationPreprocesses =
+ !this->NeedExplicitPreprocessing(language);
- // For some cases we do an explicit preprocessor invocation.
- bool const explicitPP = this->NeedExplicitPreprocessing(language);
- if (explicitPP) {
+ std::string modmapFormat;
+ if (needDyndep) {
+ std::string const modmapFormatVar =
+ cmStrCat("CMAKE_EXPERIMENTAL_", language, "_MODULE_MAP_FORMAT");
+ modmapFormat = this->Makefile->GetSafeDefinition(modmapFormatVar);
+ }
+ if (needDyndep) {
// If source/target has preprocessing turned off, we still need to
// generate an explicit dependency step
const auto srcpp = source->GetSafeProperty("Fortran_PREPROCESS");
@@ -1288,27 +1346,24 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
preprocess = cmOutputConverter::GetFortranPreprocess(tgtpp);
}
- bool const compilePP = this->UsePreprocessedSource(language) &&
+ bool const compilePP = !compilationPreprocesses &&
(preprocess != cmOutputConverter::FortranPreprocess::NotNeeded);
bool const compilePPWithDefines =
- compilePP && this->CompilePreprocessedSourceWithDefines(language);
-
- std::string const ppFileName = compilePP
- ? this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config))
- : "";
+ compilePP && this->CompileWithDefines(language);
- std::string const buildName = compilePP
- ? this->LanguagePreprocessRule(language, config)
- : this->LanguageDependencyRule(language, config);
-
- const auto depExtension = compilePP ? ".pp.d" : ".d";
- const std::string depFileName =
- this->GetLocalGenerator()->ConvertToOutputFormat(
- cmStrCat(objectFileName, depExtension), cmOutputConverter::SHELL);
+ std::string scanRuleName;
+ std::string ppFileName;
+ if (compilePP) {
+ scanRuleName = this->LanguagePreprocessAndScanRule(language, config);
+ ppFileName = this->ConvertToNinjaPath(
+ this->GetPreprocessedFilePath(source, config));
+ } else {
+ scanRuleName = this->LanguageScanRule(language, config);
+ }
- cmNinjaBuild ppBuild = GetPreprocessOrScanBuild(
- buildName, ppFileName, compilePP, compilePPWithDefines, objBuild, vars,
- depFileName, needDyndep, objectFileName);
+ cmNinjaBuild ppBuild = GetScanBuildStatement(
+ scanRuleName, ppFileName, compilePP, compilePPWithDefines, objBuild,
+ vars, modmapFormat, objectFileName, this->LocalGenerator);
if (compilePP) {
// In case compilation requires flags that are incompatible with
@@ -1330,7 +1385,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]);
}
- if (firstForConfig && needDyndep) {
+ if (firstForConfig) {
std::string const ddiFile = cmStrCat(objectFileName, ".ddi");
this->Configs[config].DDIFiles[language].push_back(ddiFile);
}
@@ -1340,14 +1395,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
ppBuild, commandLineLengthLimit);
- }
- if (needDyndep) {
+
std::string const dyndep = this->GetDyndepFilePath(language, config);
objBuild.OrderOnlyDeps.push_back(dyndep);
vars["dyndep"] = dyndep;
+
+ if (!modmapFormat.empty()) {
+ std::string const ddModmapFile = cmStrCat(objectFileName, ".modmap");
+ vars["DYNDEP_MODULE_MAP_FILE"] = ddModmapFile;
+ objBuild.OrderOnlyDeps.push_back(ddModmapFile);
+ }
}
- EnsureParentDirectoryExists(objectFileName);
+ this->EnsureParentDirectoryExists(objectFileName);
vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
objectDir, cmOutputConverter::SHELL);
@@ -1420,7 +1480,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
auto headers = this->GeneratorTarget->GetGeneratedISPCHeaders(config);
if (!headers.empty()) {
std::transform(headers.begin(), headers.end(), headers.begin(),
- MapToNinjaPath());
+ this->MapToNinjaPath());
objBuild.OrderOnlyDeps.insert(objBuild.OrderOnlyDeps.end(),
headers.begin(), headers.end());
}
@@ -1442,7 +1502,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
build.Comment = "Additional output files.";
build.Outputs = cmExpandedList(evaluatedObjectOutputs);
std::transform(build.Outputs.begin(), build.Outputs.end(),
- build.Outputs.begin(), MapToNinjaPath());
+ build.Outputs.begin(), this->MapToNinjaPath());
build.ExplicitDeps = objBuild.Outputs;
this->GetGlobalGenerator()->WriteBuild(
this->GetImplFileStream(fileConfig), build);
@@ -1458,17 +1518,26 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
tdi["compiler-id"] = this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_", lang, "_COMPILER_ID"));
+ std::string mod_dir;
if (lang == "Fortran") {
- std::string mod_dir = this->GeneratorTarget->GetFortranModuleDirectory(
+ mod_dir = this->GeneratorTarget->GetFortranModuleDirectory(
this->Makefile->GetHomeOutputDirectory());
- if (mod_dir.empty()) {
- mod_dir = this->Makefile->GetCurrentBinaryDirectory();
- }
- tdi["module-dir"] = mod_dir;
+ } else if (lang == "CXX") {
+ mod_dir =
+ cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory);
+ }
+ if (mod_dir.empty()) {
+ mod_dir = this->Makefile->GetCurrentBinaryDirectory();
+ }
+ tdi["module-dir"] = mod_dir;
+
+ if (lang == "Fortran") {
tdi["submodule-sep"] =
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
tdi["submodule-ext"] =
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
+ } else if (lang == "CXX") {
+ // No extra information necessary.
}
tdi["dir-cur-bld"] = this->Makefile->GetCurrentBinaryDirectory();
@@ -1550,7 +1619,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string const& objectFileDir, std::string const& flags,
std::string const& defines, std::string const& includes)
{
- if (!this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) {
+ if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) {
return;
}
@@ -1662,7 +1731,7 @@ void cmNinjaTargetGenerator::EnsureDirectoryExists(
void cmNinjaTargetGenerator::EnsureParentDirectoryExists(
const std::string& path) const
{
- EnsureDirectoryExists(cmSystemTools::GetParentDirectory(path));
+ this->EnsureDirectoryExists(cmSystemTools::GetParentDirectory(path));
}
void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index a27c9b4b7..79dc6227e 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -42,8 +42,6 @@ public:
std::string GetTargetName() const;
- bool NeedDepTypeMSVC(const std::string& lang) const;
-
protected:
bool SetMsvcTargetPdbVariable(cmNinjaVars&, const std::string& config) const;
@@ -67,16 +65,17 @@ protected:
std::string LanguageCompilerRule(const std::string& lang,
const std::string& config) const;
- std::string LanguagePreprocessRule(std::string const& lang,
- const std::string& config) const;
- std::string LanguageDependencyRule(std::string const& lang,
- const std::string& config) const;
- bool NeedExplicitPreprocessing(std::string const& lang) const;
+ std::string LanguagePreprocessAndScanRule(std::string const& lang,
+ const std::string& config) const;
+ std::string LanguageScanRule(std::string const& lang,
+ const std::string& config) const;
std::string LanguageDyndepRule(std::string const& lang,
const std::string& config) const;
- bool NeedDyndep(std::string const& lang) const;
- bool UsePreprocessedSource(std::string const& lang) const;
- bool CompilePreprocessedSourceWithDefines(std::string const& lang) const;
+ bool NeedDyndep(std::string const& lang, std::string const& config) const;
+ bool NeedExplicitPreprocessing(std::string const& lang) const;
+ bool CompileWithDefines(std::string const& lang) const;
+ bool NeedCxxModuleSupport(std::string const& lang,
+ std::string const& config) const;
std::string OrderDependsTargetForTarget(const std::string& config);
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index ad1d5f1cd..a18ca20d5 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -5,6 +5,7 @@
#include <algorithm>
#include <array>
#include <iterator>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -34,13 +35,35 @@ cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default;
void cmNinjaUtilityTargetGenerator::Generate(const std::string& config)
{
+ if (!this->GetGeneratorTarget()->Target->IsPerConfig()) {
+ this->WriteUtilBuildStatements(config, config);
+ return;
+ }
+
+ for (auto const& fileConfig : this->GetConfigNames()) {
+ if (!this->GetGlobalGenerator()
+ ->GetCrossConfigs(fileConfig)
+ .count(config)) {
+ continue;
+ }
+ if (fileConfig != config &&
+ this->GetGeneratorTarget()->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ continue;
+ }
+ this->WriteUtilBuildStatements(config, fileConfig);
+ }
+}
+
+void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
+ std::string const& config, std::string const& fileConfig)
+{
cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator();
cmLocalNinjaGenerator* lg = this->GetLocalGenerator();
cmGeneratorTarget* genTarget = this->GetGeneratorTarget();
std::string configDir;
if (genTarget->Target->IsPerConfig()) {
- configDir = gg->ConfigDirectory(config);
+ configDir = gg->ConfigDirectory(fileConfig);
}
std::string utilCommandName =
cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles", configDir, "/",
@@ -60,12 +83,13 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config)
for (std::vector<cmCustomCommand> const* cmdList : cmdLists) {
for (cmCustomCommand const& ci : *cmdList) {
- cmCustomCommandGenerator ccg(ci, config, lg);
- lg->AppendCustomCommandDeps(ccg, deps, config);
+ 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), MapToNinjaPath());
+ std::back_inserter(util_outputs),
+ this->MapToNinjaPath());
if (ci.GetUsesTerminal()) {
uses_terminal = true;
}
@@ -85,9 +109,9 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config)
const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
const std::vector<std::string>& ccByproducts = ccg.GetByproducts();
std::transform(ccOutputs.begin(), ccOutputs.end(),
- std::back_inserter(deps), MapToNinjaPath());
+ std::back_inserter(deps), this->MapToNinjaPath());
std::transform(ccByproducts.begin(), ccByproducts.end(),
- std::back_inserter(deps), MapToNinjaPath());
+ std::back_inserter(deps), this->MapToNinjaPath());
}
}
}
@@ -103,13 +127,17 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config)
std::copy(util_outputs.begin(), util_outputs.end(),
std::back_inserter(gg->GetByproductsForCleanTarget()));
}
- lg->AppendTargetDepends(genTarget, deps, config, config,
+ lg->AppendTargetDepends(genTarget, deps, config, fileConfig,
DependOnTargetArtifact);
if (commands.empty()) {
phonyBuild.Comment = "Utility command for " + this->GetTargetName();
phonyBuild.ExplicitDeps = std::move(deps);
- gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
+ if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
+ gg->WriteBuild(this->GetImplFileStream(fileConfig), phonyBuild);
+ } else {
+ gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
+ }
} else {
std::string command =
lg->BuildCommandLine(commands, "utility", this->GeneratorTarget);
@@ -145,15 +173,22 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config)
std::string ccConfig;
if (genTarget->Target->IsPerConfig() &&
genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
- ccConfig = config;
+ ccConfig = fileConfig;
+ }
+ if (config == fileConfig ||
+ gg->GetPerConfigUtilityTargets().count(genTarget->GetName())) {
+ gg->WriteCustomCommandBuild(
+ command, desc, "Utility command for " + this->GetTargetName(),
+ /*depfile*/ "", /*job_pool*/ "", uses_terminal,
+ /*restat*/ true, util_outputs, ccConfig, deps);
}
- gg->WriteCustomCommandBuild(command, desc,
- "Utility command for " + this->GetTargetName(),
- /*depfile*/ "", /*job_pool*/ "", uses_terminal,
- /*restat*/ true, util_outputs, ccConfig, deps);
phonyBuild.ExplicitDeps.push_back(utilCommandName);
- gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
+ if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
+ gg->WriteBuild(this->GetImplFileStream(fileConfig), phonyBuild);
+ } else {
+ gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
+ }
}
// Find ADDITIONAL_CLEAN_FILES
diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h
index 24b47f806..dbd37975c 100644
--- a/Source/cmNinjaUtilityTargetGenerator.h
+++ b/Source/cmNinjaUtilityTargetGenerator.h
@@ -17,4 +17,8 @@ public:
~cmNinjaUtilityTargetGenerator() override;
void Generate(const std::string& config) override;
+
+private:
+ void WriteUtilBuildStatements(std::string const& config,
+ std::string const& fileConfig);
};
diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h
index 4c33fcc95..a3b6f9883 100644
--- a/Source/cmOSXBundleGenerator.h
+++ b/Source/cmOSXBundleGenerator.h
@@ -62,7 +62,6 @@ public:
private:
bool MustSkip();
-private:
cmGeneratorTarget* GT;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 359e9f5a9..ec5453716 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -121,7 +121,7 @@ std::string cmOutputConverter::EscapeForShell(
flags |= Shell_Flag_IsUnix;
}
- return Shell__GetArgument(str, flags);
+ return Shell_GetArgument(str, flags);
}
std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
@@ -150,7 +150,7 @@ std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
std::string cmOutputConverter::EscapeWindowsShellArgument(cm::string_view arg,
int shell_flags)
{
- return Shell__GetArgument(arg, shell_flags);
+ return Shell_GetArgument(arg, shell_flags);
}
cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
@@ -226,12 +226,12 @@ use the caret character itself (^), use two in a row (^^).
*/
/* Some helpers to identify character classes */
-static bool Shell__CharIsWhitespace(char c)
+static bool Shell_CharIsWhitespace(char c)
{
return ((c == ' ') || (c == '\t'));
}
-static bool Shell__CharNeedsQuotesOnUnix(char c)
+static bool Shell_CharNeedsQuotesOnUnix(char c)
{
return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
(c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -239,18 +239,18 @@ static bool Shell__CharNeedsQuotesOnUnix(char c)
(c == '\\'));
}
-static bool Shell__CharNeedsQuotesOnWindows(char c)
+static bool Shell_CharNeedsQuotesOnWindows(char c)
{
return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
(c == '>') || (c == '|') || (c == '^'));
}
-static bool Shell__CharIsMakeVariableName(char c)
+static bool Shell_CharIsMakeVariableName(char c)
{
return c && (c == '_' || isalpha((static_cast<int>(c))));
}
-bool cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
+bool cmOutputConverter::Shell_CharNeedsQuotes(char c, int flags)
{
/* On Windows the built-in command shell echo never needs quotes. */
if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) {
@@ -258,30 +258,30 @@ bool cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
}
/* On all platforms quotes are needed to preserve whitespace. */
- if (Shell__CharIsWhitespace(c)) {
+ if (Shell_CharIsWhitespace(c)) {
return true;
}
if (flags & Shell_Flag_IsUnix) {
/* On UNIX several special characters need quotes to preserve them. */
- if (Shell__CharNeedsQuotesOnUnix(c)) {
+ if (Shell_CharNeedsQuotesOnUnix(c)) {
return true;
}
} else {
/* On Windows several special characters need quotes to preserve them. */
- if (Shell__CharNeedsQuotesOnWindows(c)) {
+ if (Shell_CharNeedsQuotesOnWindows(c)) {
return true;
}
}
return false;
}
-cm::string_view::iterator cmOutputConverter::Shell__SkipMakeVariables(
+cm::string_view::iterator cmOutputConverter::Shell_SkipMakeVariables(
cm::string_view::iterator c, cm::string_view::iterator end)
{
while ((c != end && (c + 1) != end) && (*c == '$' && *(c + 1) == '(')) {
cm::string_view::iterator skip = c + 2;
- while ((skip != end) && Shell__CharIsMakeVariableName(*skip)) {
+ while ((skip != end) && Shell_CharIsMakeVariableName(*skip)) {
++skip;
}
if ((skip != end) && *skip == ')') {
@@ -316,8 +316,8 @@ flag later when we understand applications of this better.
*/
#define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0
-bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
- int flags)
+bool cmOutputConverter::Shell_ArgumentNeedsQuotes(cm::string_view in,
+ int flags)
{
/* The empty string needs quotes. */
if (in.empty()) {
@@ -330,7 +330,7 @@ bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
/* Look for $(MAKEVAR) syntax if requested. */
if (flags & Shell_Flag_AllowMakeVariables) {
#if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES
- cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+ cm::string_view::iterator skip = Shell_SkipMakeVariables(cit, cend);
if (skip != cit) {
/* We need to quote make variable references to preserve the
string with contents substituted in its place. */
@@ -338,7 +338,7 @@ bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
}
#else
/* Skip over the make variable references if any are present. */
- cit = Shell__SkipMakeVariables(cit, cend);
+ cit = Shell_SkipMakeVariables(cit, cend);
/* Stop if we have reached the end of the string. */
if (cit == cend) {
@@ -348,7 +348,7 @@ bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
}
/* Check whether this character needs quotes. */
- if (Shell__CharNeedsQuotes(*cit, flags)) {
+ if (Shell_CharNeedsQuotes(*cit, flags)) {
return true;
}
}
@@ -364,8 +364,7 @@ bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
return false;
}
-std::string cmOutputConverter::Shell__GetArgument(cm::string_view in,
- int flags)
+std::string cmOutputConverter::Shell_GetArgument(cm::string_view in, int flags)
{
/* Output will be at least as long as input string. */
std::string out;
@@ -375,7 +374,7 @@ std::string cmOutputConverter::Shell__GetArgument(cm::string_view in,
int windows_backslashes = 0;
/* Whether the argument must be quoted. */
- int needQuotes = Shell__ArgumentNeedsQuotes(in, flags);
+ int needQuotes = Shell_ArgumentNeedsQuotes(in, flags);
if (needQuotes) {
/* Add the opening quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
@@ -393,7 +392,7 @@ std::string cmOutputConverter::Shell__GetArgument(cm::string_view in,
cit != cend; ++cit) {
/* Look for $(MAKEVAR) syntax if requested. */
if (flags & Shell_Flag_AllowMakeVariables) {
- cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+ cm::string_view::iterator skip = Shell_SkipMakeVariables(cit, cend);
if (skip != cit) {
/* Copy to the end of the make variable references. */
while (cit != skip) {
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index 655bc8703..f1a8041ba 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -105,13 +105,12 @@ public:
private:
cmState* GetState() const;
- static bool Shell__CharNeedsQuotes(char c, int flags);
- static cm::string_view::iterator Shell__SkipMakeVariables(
+ static bool Shell_CharNeedsQuotes(char c, int flags);
+ static cm::string_view::iterator Shell_SkipMakeVariables(
cm::string_view::iterator begin, cm::string_view::iterator end);
- static bool Shell__ArgumentNeedsQuotes(cm::string_view in, int flags);
- static std::string Shell__GetArgument(cm::string_view in, int flags);
+ static bool Shell_ArgumentNeedsQuotes(cm::string_view in, int flags);
+ static std::string Shell_GetArgument(cm::string_view in, int flags);
-private:
cmStateSnapshot StateSnapshot;
bool LinkScriptShell;
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index aa5abcb7a..d589614d7 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -376,7 +376,7 @@ protected:
}
// Didn't find an instance. Create a new one and save it.
auto info = cm::make_unique<cmDependInformation>();
- auto ptr = info.get();
+ auto* ptr = info.get();
info->FullPath = fullPath;
info->PathOnly = cmSystemTools::GetFilenamePath(fullPath);
info->IncludeName = file;
diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx
deleted file mode 100644
index 1eede13e0..000000000
--- a/Source/cmPipeConnection.cxx
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmPipeConnection.h"
-
-#include <utility>
-
-#include "cmServer.h"
-
-cmPipeConnection::cmPipeConnection(std::string name,
- cmConnectionBufferStrategy* bufferStrategy)
- : cmEventBasedConnection(bufferStrategy)
- , PipeName(std::move(name))
-{
-}
-
-void cmPipeConnection::Connect(uv_stream_t* server)
-{
- if (this->WriteStream.get()) {
- // Accept and close all pipes but the first:
- cm::uv_pipe_ptr rejectPipe;
-
- rejectPipe.init(*this->Server->GetLoop(), 0);
- uv_accept(server, rejectPipe);
-
- return;
- }
-
- cm::uv_pipe_ptr ClientPipe;
- ClientPipe.init(*this->Server->GetLoop(), 0,
- static_cast<cmEventBasedConnection*>(this));
-
- if (uv_accept(server, ClientPipe) != 0) {
- return;
- }
-
- uv_read_start(ClientPipe, on_alloc_buffer, on_read);
- WriteStream = std::move(ClientPipe);
- Server->OnConnected(this);
-}
-
-bool cmPipeConnection::OnServeStart(std::string* errorMessage)
-{
- this->ServerPipe.init(*this->Server->GetLoop(), 0,
- static_cast<cmEventBasedConnection*>(this));
-
- int r;
- if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
- *errorMessage = std::string("Internal Error with ") + this->PipeName +
- ": " + uv_err_name(r);
- return false;
- }
-
- if ((r = uv_listen(this->ServerPipe, 1, on_new_connection)) != 0) {
- *errorMessage = std::string("Internal Error listening on ") +
- this->PipeName + ": " + uv_err_name(r);
- return false;
- }
-
- return cmConnection::OnServeStart(errorMessage);
-}
-
-bool cmPipeConnection::OnConnectionShuttingDown()
-{
- if (this->WriteStream.get()) {
- this->WriteStream->data = nullptr;
- }
-
- this->ServerPipe.reset();
-
- return cmEventBasedConnection::OnConnectionShuttingDown();
-}
diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h
deleted file mode 100644
index 121571603..000000000
--- a/Source/cmPipeConnection.h
+++ /dev/null
@@ -1,29 +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>
-
-#include <cm3p/uv.h>
-
-#include "cmConnection.h"
-#include "cmUVHandlePtr.h"
-
-class cmPipeConnection : public cmEventBasedConnection
-{
-public:
- cmPipeConnection(std::string name,
- cmConnectionBufferStrategy* bufferStrategy = nullptr);
-
- bool OnServeStart(std::string* pString) override;
-
- bool OnConnectionShuttingDown() override;
-
- void Connect(uv_stream_t* server) override;
-
-private:
- const std::string PipeName;
- cm::uv_pipe_ptr ServerPipe;
-};
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 18ce9c3f2..2194b0f29 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -340,6 +340,25 @@ class cmMakefile;
3, 19, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0114, \
"ExternalProject step targets fully adopt their steps.", 3, 19, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0115, "Source file extensions must be explicit.", 3, 20, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0116, \
+ "Ninja generators transform DEPFILEs from add_custom_command().", 3, \
+ 20, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0117, \
+ "MSVC RTTI flag /GR is not added to CMAKE_CXX_FLAGS by default.", 3, \
+ 20, 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0118, \
+ "The GENERATED source file property is now visible in all directories.", \
+ 3, 20, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0119, \
+ "LANGUAGE source file property explicitly compiles as specified " \
+ "language.", \
+ 3, 20, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0120, \
+ "The WriteCompilerDetectionHeader module is removed.", 3, 20, 0, \
cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
@@ -375,7 +394,8 @@ class cmMakefile;
F(CMP0105) \
F(CMP0108) \
F(CMP0112) \
- F(CMP0113)
+ F(CMP0113) \
+ F(CMP0119)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx
index 0fb4ff71c..10c421542 100644
--- a/Source/cmProcessOutput.cxx
+++ b/Source/cmProcessOutput.cxx
@@ -51,8 +51,6 @@ cmProcessOutput::cmProcessOutput(Encoding encoding, unsigned int maxSize)
#endif
}
-cmProcessOutput::~cmProcessOutput() = default;
-
bool cmProcessOutput::DecodeText(std::string raw, std::string& decoded,
size_t id)
{
@@ -126,7 +124,7 @@ bool cmProcessOutput::DecodeText(std::string raw, std::string& decoded,
bool cmProcessOutput::DecodeText(const char* data, size_t length,
std::string& decoded, size_t id)
{
- return DecodeText(std::string(data, length), decoded, id);
+ return this->DecodeText(std::string(data, length), decoded, id);
}
bool cmProcessOutput::DecodeText(std::vector<char> raw,
@@ -134,7 +132,7 @@ bool cmProcessOutput::DecodeText(std::vector<char> raw,
{
std::string str;
const bool success =
- DecodeText(std::string(raw.begin(), raw.end()), str, id);
+ this->DecodeText(std::string(raw.begin(), raw.end()), str, id);
decoded.assign(str.begin(), str.end());
return success;
}
diff --git a/Source/cmProcessOutput.h b/Source/cmProcessOutput.h
index a1f73bd0e..8cee987a2 100644
--- a/Source/cmProcessOutput.h
+++ b/Source/cmProcessOutput.h
@@ -47,7 +47,7 @@ public:
* 0 as \a maxSize.
*/
cmProcessOutput(Encoding encoding = Auto, unsigned int maxSize = 1024);
- ~cmProcessOutput();
+ ~cmProcessOutput() = default;
/**
* Decode \a raw string using external encoding to internal
* encoding in \a decoded.
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 0cfba6353..ed32de9f3 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -358,6 +358,17 @@ static bool IncludeByVariable(cmExecutionStatus& status,
return true;
}
+ std::string includeFile =
+ cmSystemTools::CollapseFullPath(*include, mf.GetCurrentSourceDirectory());
+ if (!cmSystemTools::FileExists(includeFile)) {
+ status.SetError(cmStrCat("could not find requested file:\n ", *include));
+ return false;
+ }
+ if (cmSystemTools::FileIsDirectory(includeFile)) {
+ status.SetError(cmStrCat("requested file is a directory:\n ", *include));
+ return false;
+ }
+
const bool readit = mf.ReadDependentFile(*include);
if (readit) {
return true;
@@ -367,7 +378,7 @@ static bool IncludeByVariable(cmExecutionStatus& status,
return true;
}
- status.SetError(cmStrCat("could not find file:\n ", *include));
+ status.SetError(cmStrCat("could not load requested file:\n ", *include));
return false;
}
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index f22f36dd4..06e151ab6 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -7,17 +7,17 @@
void cmPropertyMap::Clear()
{
- Map_.clear();
+ this->Map_.clear();
}
void cmPropertyMap::SetProperty(const std::string& name, const char* value)
{
if (!value) {
- Map_.erase(name);
+ this->Map_.erase(name);
return;
}
- Map_[name] = value;
+ this->Map_[name] = value;
}
void cmPropertyMap::AppendProperty(const std::string& name,
@@ -29,7 +29,7 @@ void cmPropertyMap::AppendProperty(const std::string& name,
}
{
- std::string& pVal = Map_[name];
+ std::string& pVal = this->Map_[name];
if (!pVal.empty() && !asString) {
pVal += ';';
}
@@ -39,13 +39,13 @@ void cmPropertyMap::AppendProperty(const std::string& name,
void cmPropertyMap::RemoveProperty(const std::string& name)
{
- Map_.erase(name);
+ this->Map_.erase(name);
}
cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const
{
- auto it = Map_.find(name);
- if (it != Map_.end()) {
+ auto it = this->Map_.find(name);
+ if (it != this->Map_.end()) {
return &it->second;
}
return nullptr;
@@ -54,8 +54,8 @@ cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const
std::vector<std::string> cmPropertyMap::GetKeys() const
{
std::vector<std::string> keyList;
- keyList.reserve(Map_.size());
- for (auto const& item : Map_) {
+ keyList.reserve(this->Map_.size());
+ for (auto const& item : this->Map_) {
keyList.push_back(item.first);
}
std::sort(keyList.begin(), keyList.end());
@@ -66,8 +66,8 @@ std::vector<std::pair<std::string, std::string>> cmPropertyMap::GetList() const
{
using StringPair = std::pair<std::string, std::string>;
std::vector<StringPair> kvList;
- kvList.reserve(Map_.size());
- for (auto const& item : Map_) {
+ kvList.reserve(this->Map_.size());
+ for (auto const& item : this->Map_) {
kvList.emplace_back(item.first, item.second);
}
std::sort(kvList.begin(), kvList.end(),
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index de462db35..e9670f9c3 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -5,6 +5,7 @@
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
@@ -40,8 +41,7 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args,
cmStrCat(mf.GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx");
cmSourceFile* sf = mf.GetOrCreateSource(newName, true);
if (curr) {
- cmProp p = curr->GetProperty("ABSTRACT");
- sf->SetProperty("ABSTRACT", cmToCStr(p));
+ sf->SetProperty("ABSTRACT", cmToCStr(curr->GetProperty("ABSTRACT")));
}
// Compute the name of the header from which to generate the file.
@@ -74,9 +74,9 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args,
std::string no_main_dependency;
const char* no_working_dir = nullptr;
- mf.AddCustomCommandToOutput(newName, depends, no_main_dependency,
- commandLines, "Qt Wrapped File",
- no_working_dir);
+ mf.AddCustomCommandToOutput(
+ newName, depends, no_main_dependency, commandLines, "Qt Wrapped File",
+ no_working_dir, mf.GetPolicyStatus(cmPolicies::CMP0116));
}
}
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index 66c0228fc..f98f0b321 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -5,6 +5,7 @@
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
@@ -87,16 +88,19 @@ bool cmQTWrapUICommand(std::vector<std::string> const& args,
const char* no_comment = nullptr;
const char* no_working_dir = nullptr;
mf.AddCustomCommandToOutput(hName, depends, no_main_dependency,
- hCommandLines, no_comment, no_working_dir);
+ hCommandLines, no_comment, no_working_dir,
+ mf.GetPolicyStatus(cmPolicies::CMP0116));
depends.push_back(hName);
mf.AddCustomCommandToOutput(cxxName, depends, no_main_dependency,
- cxxCommandLines, no_comment, no_working_dir);
+ cxxCommandLines, no_comment, no_working_dir,
+ mf.GetPolicyStatus(cmPolicies::CMP0116));
depends.clear();
depends.push_back(hName);
mf.AddCustomCommandToOutput(mocName, depends, no_main_dependency,
- mocCommandLines, no_comment, no_working_dir);
+ mocCommandLines, no_comment, no_working_dir,
+ mf.GetPolicyStatus(cmPolicies::CMP0116));
}
}
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index cf90417f2..466a954a9 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -29,13 +29,13 @@ public:
{
}
- bool operator>(IntegerVersion const version)
+ bool operator>(IntegerVersion const version) const
{
return (this->Major > version.Major) ||
((this->Major == version.Major) && (this->Minor > version.Minor));
}
- bool operator>=(IntegerVersion const version)
+ bool operator>=(IntegerVersion const version) const
{
return (this->Major > version.Major) ||
((this->Major == version.Major) && (this->Minor >= version.Minor));
@@ -64,7 +64,6 @@ public:
/// @brief Maximum number of parallel threads/processes in a generator
static unsigned int const ParallelMax;
-public:
/// @brief Returns the generator name
static cm::string_view GeneratorName(GenT genType);
/// @brief Returns the generator name in upper case
@@ -111,20 +110,20 @@ public:
RccLister(std::string rccExecutable, std::vector<std::string> listOptions);
//! The rcc executable
- std::string const& RccExcutable() const { return RccExcutable_; }
+ std::string const& RccExcutable() const { return this->RccExcutable_; }
void SetRccExecutable(std::string const& rccExecutable)
{
- RccExcutable_ = rccExecutable;
+ this->RccExcutable_ = rccExecutable;
}
//! The rcc executable list options
std::vector<std::string> const& ListOptions() const
{
- return ListOptions_;
+ return this->ListOptions_;
}
void SetListOptions(std::vector<std::string> const& listOptions)
{
- ListOptions_ = listOptions;
+ this->ListOptions_ = listOptions;
}
/**
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index fac2bbf2d..f79ffd4a0 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoGenGlobalInitializer.h"
+#include <set>
#include <utility>
#include <cm/memory>
@@ -12,6 +13,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmProcessOutput.h"
#include "cmProperty.h"
#include "cmQtAutoGen.h"
@@ -56,7 +58,8 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
if (targetName.empty()) {
targetName = "autogen";
}
- GlobalAutoGenTargets_.emplace(localGen.get(), std::move(targetName));
+ this->GlobalAutoGenTargets_.emplace(localGen.get(),
+ std::move(targetName));
globalAutoGenTarget = true;
}
@@ -67,7 +70,8 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
if (targetName.empty()) {
targetName = "autorcc";
}
- GlobalAutoRccTargets_.emplace(localGen.get(), std::move(targetName));
+ this->GlobalAutoRccTargets_.emplace(localGen.get(),
+ std::move(targetName));
globalAutoRccTarget = true;
}
}
@@ -91,17 +95,23 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
// Don't process target
continue;
}
+ std::set<std::string> const& languages =
+ target->GetAllConfigCompileLanguages();
+ if (languages.count("CSharp")) {
+ // Don't process target if it's a CSharp target
+ continue;
+ }
- bool const moc = target->GetPropertyAsBool(kw().AUTOMOC);
- bool const uic = target->GetPropertyAsBool(kw().AUTOUIC);
- bool const rcc = target->GetPropertyAsBool(kw().AUTORCC);
+ bool const moc = target->GetPropertyAsBool(this->kw().AUTOMOC);
+ bool const uic = target->GetPropertyAsBool(this->kw().AUTOUIC);
+ bool const rcc = target->GetPropertyAsBool(this->kw().AUTORCC);
if (moc || uic || rcc) {
std::string const& mocExec =
- target->GetSafeProperty(kw().AUTOMOC_EXECUTABLE);
+ target->GetSafeProperty(this->kw().AUTOMOC_EXECUTABLE);
std::string const& uicExec =
- target->GetSafeProperty(kw().AUTOUIC_EXECUTABLE);
+ target->GetSafeProperty(this->kw().AUTOUIC_EXECUTABLE);
std::string const& rccExec =
- target->GetSafeProperty(kw().AUTORCC_EXECUTABLE);
+ target->GetSafeProperty(this->kw().AUTORCC_EXECUTABLE);
// We support Qt4, Qt5 and Qt6
auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target.get());
@@ -134,9 +144,10 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
}
if (mocIsValid || uicIsValid || rccIsValid) {
// Create autogen target initializer
- Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>(
- this, target.get(), qtVersion.first, mocIsValid, uicIsValid,
- rccIsValid, globalAutoGenTarget, globalAutoRccTarget));
+ this->Initializers_.emplace_back(
+ cm::make_unique<cmQtAutoGenInitializer>(
+ this, target.get(), qtVersion.first, mocIsValid, uicIsValid,
+ rccIsValid, globalAutoGenTarget, globalAutoRccTarget));
}
}
}
@@ -157,9 +168,10 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
cmCustomCommandLines no_commands;
+ const cmPolicies::PolicyStatus cmp0116_new = cmPolicies::NEW;
cmTarget* target = localGen->AddUtilityCommand(
name, true, makefile->GetHomeOutputDirectory().c_str(), no_byproducts,
- no_depends, no_commands, false, comment.c_str());
+ no_depends, no_commands, cmp0116_new, false, comment.c_str());
localGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(target, localGen));
@@ -177,8 +189,8 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen(
cmLocalGenerator* localGen, std::string const& targetName)
{
- auto it = GlobalAutoGenTargets_.find(localGen);
- if (it != GlobalAutoGenTargets_.end()) {
+ auto it = this->GlobalAutoGenTargets_.find(localGen);
+ if (it != this->GlobalAutoGenTargets_.end()) {
cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
if (target != nullptr) {
target->Target->AddUtility(targetName, false, localGen->GetMakefile());
@@ -189,8 +201,8 @@ void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen(
void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc(
cmLocalGenerator* localGen, std::string const& targetName)
{
- auto it = GlobalAutoRccTargets_.find(localGen);
- if (it != GlobalAutoRccTargets_.end()) {
+ auto it = this->GlobalAutoRccTargets_.find(localGen);
+ if (it != this->GlobalAutoRccTargets_.end()) {
cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
if (target != nullptr) {
target->Target->AddUtility(targetName, false, localGen->GetMakefile());
@@ -251,7 +263,7 @@ cmQtAutoGenGlobalInitializer::GetCompilerFeatures(
bool cmQtAutoGenGlobalInitializer::generate()
{
- return (InitializeCustomTargets() && SetupCustomTargets());
+ return (this->InitializeCustomTargets() && this->SetupCustomTargets());
}
bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets()
@@ -259,19 +271,19 @@ bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets()
// Initialize global autogen targets
{
std::string const comment = "Global AUTOGEN target";
- for (auto const& pair : GlobalAutoGenTargets_) {
- GetOrCreateGlobalTarget(pair.first, pair.second, comment);
+ for (auto const& pair : this->GlobalAutoGenTargets_) {
+ this->GetOrCreateGlobalTarget(pair.first, pair.second, comment);
}
}
// Initialize global autorcc targets
{
std::string const comment = "Global AUTORCC target";
- for (auto const& pair : GlobalAutoRccTargets_) {
- GetOrCreateGlobalTarget(pair.first, pair.second, comment);
+ for (auto const& pair : this->GlobalAutoRccTargets_) {
+ this->GetOrCreateGlobalTarget(pair.first, pair.second, comment);
}
}
// Initialize per target autogen targets
- for (auto& initializer : Initializers_) {
+ for (auto& initializer : this->Initializers_) {
if (!initializer->InitCustomTargets()) {
return false;
}
@@ -281,7 +293,7 @@ bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets()
bool cmQtAutoGenGlobalInitializer::SetupCustomTargets()
{
- for (auto& initializer : Initializers_) {
+ for (auto& initializer : this->Initializers_) {
if (!initializer->SetupCustomTargets()) {
return false;
}
diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h
index cdae13751..afcb4a2a9 100644
--- a/Source/cmQtAutoGenGlobalInitializer.h
+++ b/Source/cmQtAutoGenGlobalInitializer.h
@@ -45,12 +45,11 @@ public:
std::string ui;
};
-public:
cmQtAutoGenGlobalInitializer(
std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators);
~cmQtAutoGenGlobalInitializer();
- Keywords const& kw() const { return Keywords_; };
+ Keywords const& kw() const { return this->Keywords_; };
bool generate();
@@ -73,7 +72,6 @@ private:
std::string const& generator, std::string const& executable,
std::string& error);
-private:
std::vector<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_;
std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_;
std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_;
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 3b62e9cf8..d4138d93f 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -17,6 +17,7 @@
#include <cm/iterator>
#include <cm/memory>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include <cm3p/json/value.h>
#include <cm3p/json/writer.h>
@@ -150,7 +151,8 @@ std::vector<std::string> SearchPathSanitizer::operator()(
res.reserve(paths.size());
for (std::string const& srcPath : paths) {
// Collapse relative paths
- std::string path = cmSystemTools::CollapseFullPath(srcPath, SourcePath_);
+ std::string path =
+ cmSystemTools::CollapseFullPath(srcPath, this->SourcePath_);
// Remove suffix slashes
while (cmHasSuffix(path, '/')) {
path.pop_back();
@@ -170,14 +172,17 @@ public:
// -- Single value
void Set(std::string const& key, std::string const& value)
{
- Value_[key] = value;
+ this->Value_[key] = value;
}
void SetConfig(std::string const& key,
cmQtAutoGenInitializer::ConfigString const& cfgStr);
- void SetBool(std::string const& key, bool value) { Value_[key] = value; }
+ void SetBool(std::string const& key, bool value)
+ {
+ this->Value_[key] = value;
+ }
void SetUInt(std::string const& key, unsigned int value)
{
- Value_[key] = value;
+ this->Value_[key] = value;
}
// -- Array utility
@@ -209,9 +214,9 @@ private:
void InfoWriter::SetConfig(std::string const& key,
cmQtAutoGenInitializer::ConfigString const& cfgStr)
{
- Set(key, cfgStr.Default);
+ this->Set(key, cfgStr.Default);
for (auto const& item : cfgStr.Config) {
- Set(cmStrCat(key, '_', item.first), item.second);
+ this->Set(cmStrCat(key, '_', item.first), item.second);
}
}
@@ -241,14 +246,14 @@ void InfoWriter::MakeStringArray(Json::Value& jval, CONT const& container)
template <typename CONT>
void InfoWriter::SetArray(std::string const& key, CONT const& container)
{
- MakeStringArray(Value_[key], container);
+ MakeStringArray(this->Value_[key], container);
}
template <typename CONT, typename FUNC>
void InfoWriter::SetArrayArray(std::string const& key, CONT const& container,
FUNC func)
{
- Json::Value& jval = Value_[key];
+ Json::Value& jval = this->Value_[key];
if (MakeArray(jval, container)) {
Json::ArrayIndex ii = 0;
for (auto const& citem : container) {
@@ -264,9 +269,9 @@ void InfoWriter::SetConfigArray(
std::string const& key,
cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr)
{
- SetArray(key, cfgStr.Default);
+ this->SetArray(key, cfgStr.Default);
for (auto const& item : cfgStr.Config) {
- SetArray(cmStrCat(key, '_', item.first), item.second);
+ this->SetArray(cmStrCat(key, '_', item.first), item.second);
}
}
@@ -281,7 +286,7 @@ bool InfoWriter::Save(std::string const& filename)
Json::StyledStreamWriter jsonWriter;
try {
- jsonWriter.write(fileStream, Value_);
+ jsonWriter.write(fileStream, this->Value_);
} catch (...) {
return false;
}
@@ -304,11 +309,11 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer(
, PathCheckSum(genTarget->Makefile)
, QtVersion(qtVersion)
{
- AutogenTarget.GlobalTarget = globalAutogenTarget;
- Moc.Enabled = mocEnabled;
- Uic.Enabled = uicEnabled;
- Rcc.Enabled = rccEnabled;
- Rcc.GlobalTarget = globalAutoRccTarget;
+ this->AutogenTarget.GlobalTarget = globalAutogenTarget;
+ this->Moc.Enabled = mocEnabled;
+ this->Uic.Enabled = uicEnabled;
+ this->Rcc.Enabled = rccEnabled;
+ this->Rcc.GlobalTarget = globalAutoRccTarget;
}
bool cmQtAutoGenInitializer::InitCustomTargets()
@@ -414,8 +419,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
// Include directory
- ConfigFileNames(this->Dir.Include, cmStrCat(this->Dir.Build, "/include"),
- "");
+ this->ConfigFileNames(this->Dir.Include,
+ cmStrCat(this->Dir.Build, "/include"), "");
this->Dir.IncludeGenExp = this->Dir.Include.Default;
if (this->MultiConfig) {
this->Dir.IncludeGenExp += "_$<CONFIG>";
@@ -425,12 +430,12 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
// Moc, Uic and _autogen target settings
if (this->MocOrUicEnabled()) {
// Init moc specific settings
- if (this->Moc.Enabled && !InitMoc()) {
+ if (this->Moc.Enabled && !this->InitMoc()) {
return false;
}
// Init uic specific settings
- if (this->Uic.Enabled && !InitUic()) {
+ if (this->Uic.Enabled && !this->InitUic()) {
return false;
}
@@ -457,14 +462,14 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmStrCat(this->Dir.Info, "/AutogenInfo.json");
// Used settings file
- ConfigFileNames(this->AutogenTarget.SettingsFile,
- cmStrCat(this->Dir.Info, "/AutogenUsed"), ".txt");
- ConfigFileClean(this->AutogenTarget.SettingsFile);
+ this->ConfigFileNames(this->AutogenTarget.SettingsFile,
+ cmStrCat(this->Dir.Info, "/AutogenUsed"), ".txt");
+ this->ConfigFileClean(this->AutogenTarget.SettingsFile);
// Parse cache file
- ConfigFileNames(this->AutogenTarget.ParseCacheFile,
- cmStrCat(this->Dir.Info, "/ParseCache"), ".txt");
- ConfigFileClean(this->AutogenTarget.ParseCacheFile);
+ this->ConfigFileNames(this->AutogenTarget.ParseCacheFile,
+ cmStrCat(this->Dir.Info, "/ParseCache"), ".txt");
+ this->ConfigFileClean(this->AutogenTarget.ParseCacheFile);
}
// Autogen target: Compute user defined dependencies
@@ -533,7 +538,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
// Init rcc specific settings
- if (this->Rcc.Enabled && !InitRcc()) {
+ if (this->Rcc.Enabled && !this->InitRcc()) {
return false;
}
@@ -563,8 +568,23 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
bool cmQtAutoGenInitializer::InitMoc()
{
// Mocs compilation file
- this->Moc.CompilationFile =
- cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
+ if (this->GlobalGen->IsXcode()) {
+ // XXX(xcode-per-cfg-src): Drop this Xcode-specific code path
+ // when the Xcode generator supports per-config sources.
+ this->Moc.CompilationFile.Default =
+ 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;
+ }
+ }
// Moc predefs
if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
@@ -574,8 +594,8 @@ bool cmQtAutoGenInitializer::InitMoc()
this->Moc.PredefsCmd);
// Header
if (!this->Moc.PredefsCmd.empty()) {
- ConfigFileNames(this->Moc.PredefsFile,
- cmStrCat(this->Dir.Build, "/moc_predefs"), ".h");
+ this->ConfigFileNames(this->Moc.PredefsFile,
+ cmStrCat(this->Dir.Build, "/moc_predefs"), ".h");
}
}
@@ -730,10 +750,14 @@ bool cmQtAutoGenInitializer::InitScanFiles()
auto const& kw = this->GlobalInitializer->kw();
auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,
+ std::vector<size_t> const& configs,
bool muIt) -> MUFileHandle {
MUFileHandle muf = cm::make_unique<MUFile>();
muf->FullPath = fullPath;
muf->SF = sf;
+ if (!configs.empty() && configs.size() != this->ConfigsList.size()) {
+ muf->Configs = configs;
+ }
muf->Generated = sf->GetIsGenerated();
bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
muf->SkipMoc = this->Moc.Enabled &&
@@ -772,42 +796,37 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Scan through target files
{
// Scan through target files
- std::vector<cmSourceFile*> srcFiles;
- this->GenTarget->GetConfigCommonSourceFiles(srcFiles);
- for (cmSourceFile* sf : srcFiles) {
- // sf->GetExtension() is only valid after sf->ResolveFullPath() ...
- // Since we're iterating over source files that might be not in the
- // target we need to check for path errors (not existing files).
- std::string pathError;
- std::string const& fullPath = sf->ResolveFullPath(&pathError);
- if (!pathError.empty() || fullPath.empty()) {
- continue;
- }
+ for (cmGeneratorTarget::AllConfigSource const& acs :
+ this->GenTarget->GetAllConfigSources()) {
+ std::string const& fullPath = acs.Source->GetFullPath();
std::string const& extLower =
- cmSystemTools::LowerCase(sf->GetExtension());
+ cmSystemTools::LowerCase(acs.Source->GetExtension());
// Register files that will be scanned by moc or uic
if (this->MocOrUicEnabled()) {
if (cm->IsAHeaderExtension(extLower)) {
- addMUHeader(makeMUFile(sf, fullPath, true), extLower);
+ addMUHeader(makeMUFile(acs.Source, fullPath, acs.Configs, true),
+ extLower);
} else if (cm->IsACLikeSourceExtension(extLower)) {
- addMUSource(makeMUFile(sf, fullPath, true));
+ addMUSource(makeMUFile(acs.Source, fullPath, acs.Configs, true));
}
}
// Register rcc enabled files
if (this->Rcc.Enabled) {
- if ((extLower == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
- !sf->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
+ if ((extLower == kw.qrc) &&
+ !acs.Source->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
+ !acs.Source->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
// Register qrc file
Qrc qrc;
qrc.QrcFile = fullPath;
qrc.QrcName =
cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
- qrc.Generated = sf->GetIsGenerated();
+ qrc.Generated = acs.Source->GetIsGenerated();
// RCC options
{
- std::string const opts = sf->GetSafeProperty(kw.AUTORCC_OPTIONS);
+ std::string const& opts =
+ acs.Source->GetSafeProperty(kw.AUTORCC_OPTIONS);
if (!opts.empty()) {
cmExpandList(opts, qrc.Options);
}
@@ -817,7 +836,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
}
}
}
- // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
+ // cmGeneratorTarget::GetAllConfigSources computes the target's
// sources meta data cache. Clear it so that OBJECT library targets that
// are AUTOGEN initialized after this target get their added
// mocs_compilation.cpp source acknowledged by this target.
@@ -861,7 +880,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
}
if (sf != nullptr) {
- auto eMuf = makeMUFile(sf, fullPath, true);
+ auto eMuf = makeMUFile(sf, fullPath, muf.Configs, true);
// Only process moc/uic when the parent is processed as well
if (!muf.MocIt) {
eMuf->MocIt = false;
@@ -896,14 +915,14 @@ bool cmQtAutoGenInitializer::InitScanFiles()
if (cm->IsAHeaderExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Headers, sf.get())) {
- auto muf = makeMUFile(sf.get(), fullPath, false);
+ auto muf = makeMUFile(sf.get(), fullPath, {}, false);
if (muf->SkipMoc || muf->SkipUic) {
addMUHeader(std::move(muf), extLower);
}
}
} else if (cm->IsACLikeSourceExtension(extLower)) {
if (!cm::contains(this->AutogenTarget.Sources, sf.get())) {
- auto muf = makeMUFile(sf.get(), fullPath, false);
+ auto muf = makeMUFile(sf.get(), fullPath, {}, false);
if (muf->SkipMoc || muf->SkipUic) {
addMUSource(std::move(muf));
}
@@ -1020,7 +1039,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
qrc.QrcName, '_', qrc.QrcPathChecksum);
qrc.LockFile = cmStrCat(base, "_Lock.lock");
qrc.InfoFile = cmStrCat(base, "_Info.json");
- ConfigFileNames(qrc.SettingsFile, cmStrCat(base, "_Used"), ".txt");
+ this->ConfigFileNames(qrc.SettingsFile, cmStrCat(base, "_Used"), ".txt");
}
// rcc options
for (Qrc& qrc : this->Rcc.Qrcs) {
@@ -1066,10 +1085,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);
// Files provided by the autogen target
- std::vector<std::string> autogenProvides;
+ std::vector<std::string> autogenByproducts;
if (this->Moc.Enabled) {
this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true);
- autogenProvides.push_back(this->Moc.CompilationFile);
+ autogenByproducts.push_back(this->Moc.CompilationFileGenex);
}
// Compose target comment
@@ -1090,8 +1109,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
// Compose command lines
- // TODO: Refactor autogen to output a per-config mocs_compilation.cpp instead
- // of fiddling with the include directories
+ // FIXME: Take advantage of our per-config mocs_compilation_$<CONFIG>.cpp
+ // instead of fiddling with the include directories
std::vector<std::string> configs;
this->GlobalGen->GetQtAutoGenConfigs(configs);
bool stdPipesUTF8 = true;
@@ -1118,7 +1137,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
usePRE_BUILD = false;
}
// Cannot use PRE_BUILD when a global autogen target is in place
- if (AutogenTarget.GlobalTarget) {
+ if (this->AutogenTarget.GlobalTarget) {
usePRE_BUILD = false;
}
}
@@ -1137,7 +1156,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// PRE_BUILD does not support file dependencies!
const std::vector<std::string> no_output;
const std::vector<std::string> no_deps;
- cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines,
+ cmCustomCommand cc(no_output, autogenByproducts, no_deps, commandLines,
this->Makefile->GetBacktrace(), autogenComment.c_str(),
this->Dir.Work.c_str(), stdPipesUTF8);
cc.SetEscapeOldStyle(false);
@@ -1206,7 +1225,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
cmTarget* timestampTarget = this->LocalGen->AddUtilityCommand(
timestampTargetName, true, this->Dir.Work.c_str(),
/*byproducts=*/timestampTargetProvides,
- /*depends=*/dependencies, timestampTargetCommandLines, false, nullptr);
+ /*depends=*/dependencies, timestampTargetCommandLines, cmPolicies::NEW,
+ false, nullptr);
this->LocalGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(timestampTarget, this->LocalGen));
@@ -1237,15 +1257,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
const std::string outputFile =
cmStrCat(this->Dir.Build, "/", timestampFileName);
this->AutogenTarget.DepFile = cmStrCat(this->Dir.Build, "/deps");
- auto relativeBinaryDir = cmSystemTools::RelativePath(
- this->LocalGen->GetBinaryDirectory(),
- this->LocalGen->GetCurrentBinaryDirectory());
- if (!relativeBinaryDir.empty()) {
- relativeBinaryDir = cmStrCat(relativeBinaryDir, "/");
- }
this->AutogenTarget.DepFileRuleName =
- cmStrCat(relativeBinaryDir, this->GenTarget->GetName(), "_autogen/",
- timestampFileName);
+ cmStrCat(this->GenTarget->GetName(), "_autogen/", timestampFileName);
commandLines.push_back(cmMakeCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));
@@ -1253,7 +1266,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
const std::string no_main_dependency;
this->LocalGen->AddCustomCommandToOutput(
outputFile, dependencies, no_main_dependency, commandLines,
- autogenComment.c_str(), this->Dir.Work.c_str(), /*replace=*/false,
+ autogenComment.c_str(), this->Dir.Work.c_str(),
+ /*cmp0116=*/cmPolicies::NEW, /*replace=*/false,
/*escapeOldStyle=*/false,
/*uses_terminal=*/false,
/*command_expand_lists=*/false, this->AutogenTarget.DepFile, "",
@@ -1270,8 +1284,9 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// Create autogen target
cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(
this->AutogenTarget.Name, true, this->Dir.Work.c_str(),
- /*byproducts=*/autogenProvides,
- /*depends=*/dependencies, commandLines, false, autogenComment.c_str());
+ /*byproducts=*/autogenByproducts,
+ /*depends=*/dependencies, commandLines, cmPolicies::NEW, false,
+ autogenComment.c_str());
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen));
@@ -1357,8 +1372,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand(
ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends,
- commandLines, false, ccComment.c_str(), false, false, "",
- stdPipesUTF8);
+ commandLines, cmPolicies::NEW, false, ccComment.c_str(), false,
+ false, "", stdPipesUTF8);
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
@@ -1398,8 +1413,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
this->LocalGen->AddCustomCommandToOutput(
ccOutput, ccByproducts, ccDepends, no_main_dependency,
no_implicit_depends, commandLines, ccComment.c_str(),
- this->Dir.Work.c_str(), false, true, false, false, "", "",
- stdPipesUTF8);
+ this->Dir.Work.c_str(), cmPolicies::NEW, false, true, false, false,
+ "", "", stdPipesUTF8);
}
// Reconfigure when .qrc file changes
this->Makefile->AddCMakeDependFile(qrc.QrcFile);
@@ -1520,18 +1535,31 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
info.SetArray("CMAKE_LIST_FILES", this->Makefile->GetListFiles());
info.SetArray("HEADER_EXTENSIONS",
this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
+ auto cfgArray = [this](std::vector<size_t> const& configs) -> Json::Value {
+ Json::Value value;
+ if (!configs.empty()) {
+ value = Json::arrayValue;
+ for (size_t ci : configs) {
+ value.append(this->ConfigsList[ci]);
+ }
+ }
+ return value;
+ };
+ info.SetArrayArray("HEADERS", headers,
+ [this, &cfgArray](Json::Value& jval, MUFile const* muf) {
+ jval.resize(4u);
+ jval[0u] = muf->FullPath;
+ jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm',
+ muf->UicIt ? 'U' : 'u');
+ jval[2u] = this->GetMocBuildPath(*muf);
+ jval[3u] = cfgArray(muf->Configs);
+ });
info.SetArrayArray(
- "HEADERS", headers, [this](Json::Value& jval, MUFile const* muf) {
+ "SOURCES", sources, [&cfgArray](Json::Value& jval, MUFile const* muf) {
jval.resize(3u);
jval[0u] = muf->FullPath;
jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
- jval[2u] = this->GetMocBuildPath(*muf);
- });
- info.SetArrayArray(
- "SOURCES", sources, [](Json::Value& jval, MUFile const* muf) {
- jval.resize(2u);
- jval[0u] = muf->FullPath;
- jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
+ jval[2u] = cfgArray(muf->Configs);
});
// Write moc settings
@@ -1550,7 +1578,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
jval[0u] = pair.first;
jval[1u] = pair.second;
});
- info.Set("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
+ info.SetConfig("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);
}
@@ -1624,7 +1652,7 @@ cmSourceFile* cmQtAutoGenInitializer::RegisterGeneratedSource(
std::string const& filename)
{
cmSourceFile* gFile = this->Makefile->GetOrCreateSource(filename, true);
- gFile->SetProperty("GENERATED", "1");
+ gFile->MarkAsGenerated();
gFile->SetProperty("SKIP_AUTOGEN", "1");
return gFile;
}
@@ -1643,6 +1671,28 @@ cmSourceFile* cmQtAutoGenInitializer::AddGeneratedSource(
return gFile;
}
+void cmQtAutoGenInitializer::AddGeneratedSource(ConfigString const& filename,
+ GenVarsT const& genVars,
+ bool prepend)
+{
+ // XXX(xcode-per-cfg-src): Drop the Xcode-specific part of the condition
+ // when the Xcode generator supports per-config sources.
+ if (!this->MultiConfig || this->GlobalGen->IsXcode()) {
+ this->AddGeneratedSource(filename.Default, genVars, prepend);
+ return;
+ }
+ for (auto const& cfg : this->ConfigsList) {
+ std::string const& filenameCfg = filename.Config.at(cfg);
+ // Register source at makefile
+ this->RegisterGeneratedSource(filenameCfg);
+ // Add source file to target for this configuration.
+ this->GenTarget->AddSource(
+ cmStrCat("$<$<CONFIG:"_s, cfg, ">:"_s, filenameCfg, ">"_s), prepend);
+ // Add source file to source group
+ this->AddToSourceGroup(filenameCfg, genVars.GenNameUpper);
+ }
+}
+
void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
cm::string_view genNameUpper)
{
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 3ab303ac1..f7e126d10 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <memory>
#include <set>
#include <string>
@@ -70,6 +71,7 @@ public:
{
std::string FullPath;
cmSourceFile* SF = nullptr;
+ std::vector<size_t> Configs;
bool Generated = false;
bool SkipMoc = false;
bool SkipUic = false;
@@ -96,7 +98,6 @@ public:
, GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
};
-public:
/** @return The detected Qt version and the required Qt major version. */
static std::pair<IntegerVersion, unsigned int> GetQtVersion(
cmGeneratorTarget const* genTarget);
@@ -132,6 +133,8 @@ private:
cmSourceFile* AddGeneratedSource(std::string const& filename,
GenVarsT const& genVars,
bool prepend = false);
+ void AddGeneratedSource(ConfigString const& filename,
+ GenVarsT const& genVars, bool prepend = false);
void AddToSourceGroup(std::string const& fileName,
cm::string_view genNameUpper);
void AddCleanFile(std::string const& fileName);
@@ -145,7 +148,6 @@ private:
bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
bool ignoreMissingTarget) const;
-private:
cmQtAutoGenGlobalInitializer* GlobalInitializer = nullptr;
cmGeneratorTarget* GenTarget = nullptr;
cmGlobalGenerator* GlobalGen = nullptr;
@@ -207,7 +209,8 @@ private:
bool RelaxedMode = false;
bool PathPrefix = false;
- std::string CompilationFile;
+ ConfigString CompilationFile;
+ std::string CompilationFileGenex;
// Compiler implicit pre defines
std::vector<std::string> PredefsCmd;
ConfigString PredefsFile;
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index ee2bc0937..6e88e266f 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -18,10 +18,10 @@ cmQtAutoGenerator::Logger::Logger()
if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
unsigned long iVerbose = 0;
if (cmStrToULong(verbose, &iVerbose)) {
- SetVerbosity(static_cast<unsigned int>(iVerbose));
+ this->SetVerbosity(static_cast<unsigned int>(iVerbose));
} else {
// Non numeric verbosity
- SetVerbose(cmIsOn(verbose));
+ this->SetVerbose(cmIsOn(verbose));
}
}
}
@@ -29,15 +29,13 @@ cmQtAutoGenerator::Logger::Logger()
std::string colorEnv;
cmSystemTools::GetEnv("COLOR", colorEnv);
if (!colorEnv.empty()) {
- SetColorOutput(cmIsOn(colorEnv));
+ this->SetColorOutput(cmIsOn(colorEnv));
} else {
- SetColorOutput(true);
+ this->SetColorOutput(true);
}
}
}
-cmQtAutoGenerator::Logger::~Logger() = default;
-
void cmQtAutoGenerator::Logger::RaiseVerbosity(unsigned int value)
{
if (this->Verbosity_ < value) {
@@ -47,7 +45,7 @@ void cmQtAutoGenerator::Logger::RaiseVerbosity(unsigned int value)
void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
{
- ColorOutput_ = value;
+ this->ColorOutput_ = value;
}
std::string cmQtAutoGenerator::Logger::HeadLine(cm::string_view title)
@@ -61,7 +59,7 @@ void cmQtAutoGenerator::Logger::Info(GenT genType,
std::string msg = cmStrCat(GeneratorName(genType), ": ", message,
cmHasSuffix(message, '\n') ? "" : "\n");
{
- std::lock_guard<std::mutex> lock(Mutex_);
+ std::lock_guard<std::mutex> lock(this->Mutex_);
cmSystemTools::Stdout(msg);
}
}
@@ -80,7 +78,7 @@ void cmQtAutoGenerator::Logger::Warning(GenT genType,
message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
}
{
- std::lock_guard<std::mutex> lock(Mutex_);
+ std::lock_guard<std::mutex> lock(this->Mutex_);
cmSystemTools::Stdout(msg);
}
}
@@ -92,7 +90,7 @@ void cmQtAutoGenerator::Logger::Error(GenT genType,
cmStrCat('\n', HeadLine(cmStrCat(GeneratorName(genType), " error")),
message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
{
- std::lock_guard<std::mutex> lock(Mutex_);
+ std::lock_guard<std::mutex> lock(this->Mutex_);
cmSystemTools::Stderr(msg);
}
}
@@ -108,7 +106,7 @@ void cmQtAutoGenerator::Logger::ErrorCommand(
msg += cmStrCat(HeadLine("Output"), output,
cmHasSuffix(output, '\n') ? "\n" : "\n\n");
{
- std::lock_guard<std::mutex> lock(Mutex_);
+ std::lock_guard<std::mutex> lock(this->Mutex_);
cmSystemTools::Stderr(msg);
}
}
@@ -215,7 +213,7 @@ cmQtAutoGenerator::~cmQtAutoGenerator() = default;
bool cmQtAutoGenerator::InfoT::Read(std::istream& istr)
{
try {
- istr >> Json_;
+ istr >> this->Json_;
} catch (...) {
return false;
}
@@ -264,22 +262,22 @@ bool cmQtAutoGenerator::InfoT::GetJsonArray(
std::string cmQtAutoGenerator::InfoT::ConfigKey(cm::string_view key) const
{
- return cmStrCat(key, '_', Gen_.InfoConfig());
+ return cmStrCat(key, '_', this->Gen_.InfoConfig());
}
bool cmQtAutoGenerator::InfoT::GetString(std::string const& key,
std::string& value,
bool required) const
{
- Json::Value const& jval = Json_[key];
+ Json::Value const& jval = this->Json_[key];
if (!jval.isString()) {
if (!jval.isNull() || required) {
- return LogError(cmStrCat(key, " is not a string."));
+ return this->LogError(cmStrCat(key, " is not a string."));
}
} else {
value = jval.asString();
if (value.empty() && required) {
- return LogError(cmStrCat(key, " is empty."));
+ return this->LogError(cmStrCat(key, " is empty."));
}
}
return true;
@@ -290,32 +288,32 @@ bool cmQtAutoGenerator::InfoT::GetStringConfig(std::string const& key,
bool required) const
{
{ // Try config
- std::string const configKey = ConfigKey(key);
- Json::Value const& jval = Json_[configKey];
+ std::string const configKey = this->ConfigKey(key);
+ Json::Value const& jval = this->Json_[configKey];
if (!jval.isNull()) {
if (!jval.isString()) {
- return LogError(cmStrCat(configKey, " is not a string."));
+ return this->LogError(cmStrCat(configKey, " is not a string."));
}
value = jval.asString();
if (required && value.empty()) {
- return LogError(cmStrCat(configKey, " is empty."));
+ return this->LogError(cmStrCat(configKey, " is empty."));
}
return true;
}
}
// Try plain
- return GetString(key, value, required);
+ return this->GetString(key, value, required);
}
bool cmQtAutoGenerator::InfoT::GetBool(std::string const& key, bool& value,
bool required) const
{
- Json::Value const& jval = Json_[key];
+ Json::Value const& jval = this->Json_[key];
if (jval.isBool()) {
value = jval.asBool();
} else {
if (!jval.isNull() || required) {
- return LogError(cmStrCat(key, " is not a boolean."));
+ return this->LogError(cmStrCat(key, " is not a boolean."));
}
}
return true;
@@ -325,12 +323,12 @@ bool cmQtAutoGenerator::InfoT::GetUInt(std::string const& key,
unsigned int& value,
bool required) const
{
- Json::Value const& jval = Json_[key];
+ Json::Value const& jval = this->Json_[key];
if (jval.isUInt()) {
value = jval.asUInt();
} else {
if (!jval.isNull() || required) {
- return LogError(cmStrCat(key, " is not an unsigned integer."));
+ return this->LogError(cmStrCat(key, " is not an unsigned integer."));
}
}
return true;
@@ -340,10 +338,10 @@ bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
std::vector<std::string>& list,
bool required) const
{
- Json::Value const& jval = Json_[key];
+ Json::Value const& jval = this->Json_[key];
if (!jval.isArray()) {
if (!jval.isNull() || required) {
- return LogError(cmStrCat(key, " is not an array."));
+ return this->LogError(cmStrCat(key, " is not an array."));
}
}
return GetJsonArray(list, jval) || !required;
@@ -353,10 +351,10 @@ bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
std::unordered_set<std::string>& list,
bool required) const
{
- Json::Value const& jval = Json_[key];
+ Json::Value const& jval = this->Json_[key];
if (!jval.isArray()) {
if (!jval.isNull() || required) {
- return LogError(cmStrCat(key, " is not an array."));
+ return this->LogError(cmStrCat(key, " is not an array."));
}
}
return GetJsonArray(list, jval) || !required;
@@ -367,34 +365,35 @@ bool cmQtAutoGenerator::InfoT::GetArrayConfig(std::string const& key,
bool required) const
{
{ // Try config
- std::string const configKey = ConfigKey(key);
- Json::Value const& jval = Json_[configKey];
+ std::string const configKey = this->ConfigKey(key);
+ Json::Value const& jval = this->Json_[configKey];
if (!jval.isNull()) {
if (!jval.isArray()) {
- return LogError(cmStrCat(configKey, " is not an array string."));
+ return this->LogError(cmStrCat(configKey, " is not an array string."));
}
if (!GetJsonArray(list, jval) && required) {
- return LogError(cmStrCat(configKey, " is empty."));
+ return this->LogError(cmStrCat(configKey, " is empty."));
}
return true;
}
}
// Try plain
- return GetArray(key, list, required);
+ return this->GetArray(key, list, required);
}
bool cmQtAutoGenerator::InfoT::LogError(GenT genType,
cm::string_view message) const
{
- Gen_.Log().Error(genType,
- cmStrCat("Info error in info file\n",
- Quoted(Gen_.InfoFile()), ":\n", message));
+ this->Gen_.Log().Error(genType,
+ cmStrCat("Info error in info file\n",
+ Quoted(this->Gen_.InfoFile()), ":\n",
+ message));
return false;
}
bool cmQtAutoGenerator::InfoT::LogError(cm::string_view message) const
{
- return LogError(Gen_.GenType_, message);
+ return this->LogError(this->Gen_.GenType_, message);
}
std::string cmQtAutoGenerator::SettingsFind(cm::string_view content,
@@ -418,10 +417,10 @@ std::string cmQtAutoGenerator::SettingsFind(cm::string_view content,
std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
{
std::string res;
- if (cmHasPrefix(path, ProjectDirs().Source)) {
- res = cmStrCat("SRC:", path.substr(ProjectDirs().Source.size()));
- } else if (cmHasPrefix(path, ProjectDirs().Binary)) {
- res = cmStrCat("BIN:", path.substr(ProjectDirs().Binary.size()));
+ if (cmHasPrefix(path, this->ProjectDirs().Source)) {
+ res = cmStrCat("SRC:", path.substr(this->ProjectDirs().Source.size()));
+ } else if (cmHasPrefix(path, this->ProjectDirs().Binary)) {
+ res = cmStrCat("BIN:", path.substr(this->ProjectDirs().Binary.size()));
} else {
res = std::string(path);
}
@@ -431,17 +430,18 @@ std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config)
{
// Info config
- InfoConfig_ = std::string(config);
+ this->InfoConfig_ = std::string(config);
// Info file
- InfoFile_ = std::string(infoFile);
- cmSystemTools::CollapseFullPath(InfoFile_);
- InfoDir_ = cmSystemTools::GetFilenamePath(InfoFile_);
+ this->InfoFile_ = std::string(infoFile);
+ cmSystemTools::CollapseFullPath(this->InfoFile_);
+ this->InfoDir_ = cmSystemTools::GetFilenamePath(this->InfoFile_);
// Load info file time
- if (!InfoFileTime_.Load(InfoFile_)) {
+ if (!this->InfoFileTime_.Load(this->InfoFile_)) {
cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
- Quoted(InfoFile_), " is not readable\n"));
+ Quoted(this->InfoFile_),
+ " is not readable\n"));
return false;
}
@@ -450,17 +450,18 @@ bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config)
// Read info file
{
- cmsys::ifstream ifs(InfoFile_.c_str(),
+ cmsys::ifstream ifs(this->InfoFile_.c_str(),
(std::ios::in | std::ios::binary));
if (!ifs) {
- Log().Error(
- GenType_,
- cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
+ this->Log().Error(
+ this->GenType_,
+ cmStrCat("Could not to open info file ", Quoted(this->InfoFile_)));
return false;
}
if (!info.Read(ifs)) {
- Log().Error(GenType_,
- cmStrCat("Could not read info file ", Quoted(InfoFile_)));
+ this->Log().Error(
+ this->GenType_,
+ cmStrCat("Could not read info file ", Quoted(this->InfoFile_)));
return false;
}
}
@@ -470,15 +471,17 @@ bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config)
unsigned int verbosity = 0;
// Info: setup project directories
if (!info.GetUInt("VERBOSITY", verbosity, false) ||
- !info.GetString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
- !info.GetString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
+ !info.GetString("CMAKE_SOURCE_DIR", this->ProjectDirs_.Source,
+ true) ||
+ !info.GetString("CMAKE_BINARY_DIR", this->ProjectDirs_.Binary,
+ true) ||
!info.GetString("CMAKE_CURRENT_SOURCE_DIR",
- ProjectDirs_.CurrentSource, true) ||
+ this->ProjectDirs_.CurrentSource, true) ||
!info.GetString("CMAKE_CURRENT_BINARY_DIR",
- ProjectDirs_.CurrentBinary, true)) {
+ this->ProjectDirs_.CurrentBinary, true)) {
return false;
}
- Logger_.RaiseVerbosity(verbosity);
+ this->Logger_.RaiseVerbosity(verbosity);
}
// -- Call virtual init from info method.
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index b4f057d06..5c3a8adcc 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -31,7 +31,7 @@ public:
public:
// -- Construction
Logger();
- ~Logger();
+ ~Logger() = default;
// -- Verbosity
unsigned int Verbosity() const { return this->Verbosity_; }
void SetVerbosity(unsigned int value) { this->Verbosity_ = value; }
@@ -54,7 +54,6 @@ public:
private:
static std::string HeadLine(cm::string_view title);
- private:
mutable std::mutex Mutex_;
unsigned int Verbosity_ = 0;
bool ColorOutput_ = false;
@@ -79,7 +78,6 @@ public:
static bool FileDiffers(std::string const& filename,
std::string const& content);
-public:
// -- Constructors
cmQtAutoGenerator(GenT genType);
virtual ~cmQtAutoGenerator();
@@ -88,10 +86,10 @@ public:
cmQtAutoGenerator& operator=(cmQtAutoGenerator const&) = delete;
// -- Info options
- std::string const& InfoFile() const { return InfoFile_; }
- std::string const& InfoDir() const { return InfoDir_; }
- cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
- std::string const& InfoConfig() const { return InfoConfig_; }
+ std::string const& InfoFile() const { return this->InfoFile_; }
+ std::string const& InfoDir() const { return this->InfoDir_; }
+ cmFileTime const& InfoFileTime() const { return this->InfoFileTime_; }
+ std::string const& InfoConfig() const { return this->InfoConfig_; }
// -- Info file parsing
/** Info file reader class. */
@@ -124,7 +122,7 @@ public:
Json::Value const& GetValue(std::string const& key) const
{
- return Json_[key];
+ return this->Json_[key];
}
/** Returns true if strings were appended to the list. */
@@ -140,7 +138,6 @@ public:
private:
std::string ConfigKey(cm::string_view key) const;
- private:
Json::Value Json_;
cmQtAutoGenerator& Gen_;
};
@@ -150,7 +147,7 @@ public:
cm::string_view key);
// -- Directories
- ProjectDirsT const& ProjectDirs() const { return ProjectDirs_; }
+ ProjectDirsT const& ProjectDirs() const { return this->ProjectDirs_; }
std::string MessagePath(cm::string_view path) const;
// -- Run
@@ -161,7 +158,7 @@ protected:
virtual bool InitFromInfo(InfoT const& info) = 0;
virtual bool Process() = 0;
// - Utility classes
- Logger const& Log() const { return Logger_; }
+ Logger const& Log() const { return this->Logger_; }
private:
// -- Generator type
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 9cb172bd3..1e3bf06c0 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -15,6 +15,7 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
@@ -26,7 +27,6 @@
#include "cmCryptoHash.h"
#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
-#include "cmGccDepfileReaderTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
@@ -55,7 +55,6 @@ public:
cmQtAutoMocUicT(cmQtAutoMocUicT const&) = delete;
cmQtAutoMocUicT& operator=(cmQtAutoMocUicT const&) = delete;
-public:
// -- Types
/** Include string with sub parts. */
@@ -112,7 +111,6 @@ public:
using FileHandleT = std::shared_ptr<FileT>;
using GetOrInsertT = std::pair<FileHandleT, bool>;
- public:
ParseCacheT();
~ParseCacheT();
@@ -135,7 +133,6 @@ public:
{
}
- public:
std::string FileName;
cmFileTime FileTime;
ParseCacheT::FileHandleT ParseData;
@@ -266,7 +263,6 @@ public:
std::vector<std::string> Options;
};
- public:
UicSettingsT();
~UicSettingsT();
@@ -313,22 +309,22 @@ public:
//! Get the generator. Only valid during Process() call!
cmQtAutoMocUicT* Gen() const
{
- return static_cast<cmQtAutoMocUicT*>(UserData());
+ return static_cast<cmQtAutoMocUicT*>(this->UserData());
};
// -- Accessors. Only valid during Process() call!
- Logger const& Log() const { return Gen()->Log(); }
- BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
- BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
- MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
- MocEvalT& MocEval() const { return Gen()->MocEval(); }
- UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
- UicEvalT& UicEval() const { return Gen()->UicEval(); }
+ Logger const& Log() const { return this->Gen()->Log(); }
+ BaseSettingsT const& BaseConst() const { return this->Gen()->BaseConst(); }
+ BaseEvalT& BaseEval() const { return this->Gen()->BaseEval(); }
+ MocSettingsT const& MocConst() const { return this->Gen()->MocConst(); }
+ MocEvalT& MocEval() const { return this->Gen()->MocEval(); }
+ UicSettingsT const& UicConst() const { return this->Gen()->UicConst(); }
+ UicEvalT& UicEval() const { return this->Gen()->UicEval(); }
// -- Logging
std::string MessagePath(cm::string_view path) const
{
- return Gen()->MessagePath(path);
+ return this->Gen()->MessagePath(path);
}
// - Error logging with automatic abort
void LogError(GenT genType, cm::string_view message) const;
@@ -379,7 +375,6 @@ public:
void MocIncludes();
void UicIncludes();
- protected:
SourceFileHandleT FileHandle;
std::string Content;
};
@@ -522,6 +517,7 @@ public:
class JobDepFilesMergeT : public JobFenceT
{
private:
+ std::vector<std::string> initialDependencies() const;
void Process() override;
};
@@ -541,9 +537,9 @@ public:
UicEvalT& UicEval() { return this->UicEval_; }
// -- Parallel job processing interface
- cmWorkerPool& WorkerPool() { return WorkerPool_; }
- void AbortError() { Abort(true); }
- void AbortSuccess() { Abort(false); }
+ cmWorkerPool& WorkerPool() { return this->WorkerPool_; }
+ void AbortError() { this->Abort(true); }
+ void AbortSuccess() { this->Abort(false); }
// -- Utility
std::string AbsoluteBuildPath(cm::string_view relativePath) const;
@@ -571,7 +567,6 @@ private:
static std::vector<std::string> dependenciesFromDepFile(
const char* filePath);
-private:
// -- Settings
BaseSettingsT BaseConst_;
BaseEvalT BaseEval_;
@@ -597,19 +592,19 @@ cmQtAutoMocUicT::IncludeKeyT::IncludeKeyT(std::string const& key,
, Base(cmSystemTools::GetFilenameWithoutLastExtension(key))
{
if (basePrefixLength != 0) {
- Base = Base.substr(basePrefixLength);
+ this->Base = this->Base.substr(basePrefixLength);
}
}
void cmQtAutoMocUicT::ParseCacheT::FileT::Clear()
{
- Moc.Macro.clear();
- Moc.Include.Underscore.clear();
- Moc.Include.Dot.clear();
- Moc.Depends.clear();
+ this->Moc.Macro.clear();
+ this->Moc.Include.Underscore.clear();
+ this->Moc.Include.Dot.clear();
+ this->Moc.Depends.clear();
- Uic.Include.clear();
- Uic.Depends.clear();
+ this->Uic.Include.clear();
+ this->Uic.Depends.clear();
}
cmQtAutoMocUicT::ParseCacheT::GetOrInsertT
@@ -617,15 +612,15 @@ cmQtAutoMocUicT::ParseCacheT::GetOrInsert(std::string const& fileName)
{
// Find existing entry
{
- auto it = Map_.find(fileName);
- if (it != Map_.end()) {
+ auto it = this->Map_.find(fileName);
+ if (it != this->Map_.end()) {
return GetOrInsertT{ it->second, false };
}
}
// Insert new entry
return GetOrInsertT{
- Map_.emplace(fileName, std::make_shared<FileT>()).first->second, true
+ this->Map_.emplace(fileName, std::make_shared<FileT>()).first->second, true
};
}
@@ -655,7 +650,7 @@ bool cmQtAutoMocUicT::ParseCacheT::ReadFromFile(std::string const& fileName)
}
// Check if this a file name line
if (line.front() != ' ') {
- fileHandle = GetOrInsert(line).first;
+ fileHandle = this->GetOrInsert(line).first;
continue;
}
@@ -702,7 +697,7 @@ bool cmQtAutoMocUicT::ParseCacheT::WriteToFile(std::string const& fileName)
return false;
}
ofs << "# Generated by CMake. Changes will be overwritten.\n";
- for (auto const& pair : Map_) {
+ for (auto const& pair : this->Map_) {
ofs << pair.first << '\n';
FileT const& file = *pair.second;
if (!file.Moc.Macro.empty()) {
@@ -732,7 +727,7 @@ cmQtAutoMocUicT::BaseSettingsT::~BaseSettingsT() = default;
cmQtAutoMocUicT::MocSettingsT::MocSettingsT()
{
- RegExpInclude.compile(
+ this->RegExpInclude.compile(
"(^|\n)[ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
}
@@ -741,14 +736,15 @@ cmQtAutoMocUicT::MocSettingsT::~MocSettingsT() = default;
bool cmQtAutoMocUicT::MocSettingsT::skipped(std::string const& fileName) const
{
- return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
+ return (!this->Enabled ||
+ (this->SkipList.find(fileName) != this->SkipList.end()));
}
std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const
{
std::string res;
- const auto itB = MacroFilters.cbegin();
- const auto itE = MacroFilters.cend();
+ const auto itB = this->MacroFilters.cbegin();
+ const auto itE = this->MacroFilters.cend();
const auto itL = itE - 1;
auto itC = itB;
for (; itC != itE; ++itC) {
@@ -768,30 +764,31 @@ std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const
cmQtAutoMocUicT::UicSettingsT::UicSettingsT()
{
- RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
+ this->RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
+ "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
}
cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default;
bool cmQtAutoMocUicT::UicSettingsT::skipped(std::string const& fileName) const
{
- return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
+ return (!this->Enabled ||
+ (this->SkipList.find(fileName) != this->SkipList.end()));
}
void cmQtAutoMocUicT::JobT::LogError(GenT genType,
cm::string_view message) const
{
- Gen()->AbortError();
- Gen()->Log().Error(genType, message);
+ this->Gen()->AbortError();
+ this->Gen()->Log().Error(genType, message);
}
void cmQtAutoMocUicT::JobT::LogCommandError(
GenT genType, cm::string_view message,
std::vector<std::string> const& command, std::string const& output) const
{
- Gen()->AbortError();
- Gen()->Log().ErrorCommand(genType, message, command, output);
+ this->Gen()->AbortError();
+ this->Gen()->Log().ErrorCommand(genType, message, command, output);
}
bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
@@ -800,48 +797,48 @@ bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
std::string* infoMessage)
{
// Log command
- if (Log().Verbose()) {
+ if (this->Log().Verbose()) {
cm::string_view info;
if (infoMessage != nullptr) {
info = *infoMessage;
}
- Log().Info(genType,
- cmStrCat(info,
- info.empty() || cmHasSuffix(info, '\n') ? "" : "\n",
- QuotedCommand(command), '\n'));
+ this->Log().Info(
+ genType,
+ cmStrCat(info, info.empty() || cmHasSuffix(info, '\n') ? "" : "\n",
+ QuotedCommand(command), '\n'));
}
// Run command
- return cmWorkerPool::JobT::RunProcess(result, command,
- BaseConst().AutogenBuildDir);
+ return this->cmWorkerPool::JobT::RunProcess(
+ result, command, this->BaseConst().AutogenBuildDir);
}
void cmQtAutoMocUicT::JobMocPredefsT::Process()
{
// (Re)generate moc_predefs.h on demand
std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
+ if (this->Log().Verbose()) {
reason = cm::make_unique<std::string>();
}
- if (!Update(reason.get())) {
+ if (!this->Update(reason.get())) {
return;
}
- std::string const& predefsFileAbs = MocConst().PredefsFileAbs;
+ std::string const& predefsFileAbs = this->MocConst().PredefsFileAbs;
{
cmWorkerPool::ProcessResultT result;
{
// Compose command
- std::vector<std::string> cmd = MocConst().PredefsCmd;
+ std::vector<std::string> cmd = this->MocConst().PredefsCmd;
// Add definitions
- cm::append(cmd, MocConst().OptionsDefinitions);
+ cm::append(cmd, this->MocConst().OptionsDefinitions);
// Add includes
- cm::append(cmd, MocConst().OptionsIncludes);
+ cm::append(cmd, this->MocConst().OptionsIncludes);
// Execute command
- if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
- LogCommandError(GenT::MOC,
- cmStrCat("The content generation command for ",
- MessagePath(predefsFileAbs), " failed.\n",
- result.ErrorMessage),
- cmd, result.StdOut);
+ if (!this->RunProcess(GenT::MOC, result, cmd, reason.get())) {
+ this->LogCommandError(GenT::MOC,
+ cmStrCat("The content generation command for ",
+ this->MessagePath(predefsFileAbs),
+ " failed.\n", result.ErrorMessage),
+ cmd, result.StdOut);
return;
}
}
@@ -849,30 +846,31 @@ void cmQtAutoMocUicT::JobMocPredefsT::Process()
// (Re)write predefs file only on demand
if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
- LogError(
+ this->LogError(
GenT::MOC,
- cmStrCat("Writing ", MessagePath(predefsFileAbs), " failed."));
+ cmStrCat("Writing ", this->MessagePath(predefsFileAbs), " failed."));
return;
}
} else {
// Touch to update the time stamp
- if (Log().Verbose()) {
- Log().Info(GenT::MOC, "Touching " + MessagePath(predefsFileAbs));
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::MOC,
+ "Touching " + this->MessagePath(predefsFileAbs));
}
if (!cmSystemTools::Touch(predefsFileAbs, false)) {
- LogError(
- GenT::MOC,
- cmStrCat("Touching ", MessagePath(predefsFileAbs), " failed."));
+ this->LogError(GenT::MOC,
+ cmStrCat("Touching ", this->MessagePath(predefsFileAbs),
+ " failed."));
return;
}
}
}
// Read file time afterwards
- if (!MocEval().PredefsTime.Load(predefsFileAbs)) {
- LogError(GenT::MOC,
- cmStrCat("Reading the file time of ", MessagePath(predefsFileAbs),
- " failed."));
+ if (!this->MocEval().PredefsTime.Load(predefsFileAbs)) {
+ this->LogError(GenT::MOC,
+ cmStrCat("Reading the file time of ",
+ this->MessagePath(predefsFileAbs), " failed."));
return;
}
}
@@ -880,18 +878,20 @@ void cmQtAutoMocUicT::JobMocPredefsT::Process()
bool cmQtAutoMocUicT::JobMocPredefsT::Update(std::string* reason) const
{
// Test if the file exists
- if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
+ if (!this->MocEval().PredefsTime.Load(this->MocConst().PredefsFileAbs)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
+ *reason = cmStrCat("Generating ",
+ this->MessagePath(this->MocConst().PredefsFileAbs),
", because it doesn't exist.");
}
return true;
}
// Test if the settings changed
- if (MocConst().SettingsChanged) {
+ if (this->MocConst().SettingsChanged) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
+ *reason = cmStrCat("Generating ",
+ this->MessagePath(this->MocConst().PredefsFileAbs),
", because the moc settings changed.");
}
return true;
@@ -899,14 +899,14 @@ bool cmQtAutoMocUicT::JobMocPredefsT::Update(std::string* reason) const
// Test if the executable is newer
{
- std::string const& exec = MocConst().PredefsCmd.at(0);
+ std::string const& exec = this->MocConst().PredefsCmd.at(0);
cmFileTime execTime;
if (execTime.Load(exec)) {
- if (MocEval().PredefsTime.Older(execTime)) {
+ if (this->MocEval().PredefsTime.Older(execTime)) {
if (reason != nullptr) {
- *reason =
- cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
- " because it is older than ", MessagePath(exec), '.');
+ *reason = cmStrCat(
+ "Generating ", this->MessagePath(this->MocConst().PredefsFileAbs),
+ " because it is older than ", this->MessagePath(exec), '.');
}
return true;
}
@@ -919,25 +919,27 @@ bool cmQtAutoMocUicT::JobMocPredefsT::Update(std::string* reason) const
bool cmQtAutoMocUicT::JobParseT::ReadFile()
{
// Clear old parse information
- FileHandle->ParseData->Clear();
- std::string const& fileName = FileHandle->FileName;
+ this->FileHandle->ParseData->Clear();
+ std::string const& fileName = this->FileHandle->FileName;
// Write info
- if (Log().Verbose()) {
- Log().Info(GenT::GEN, cmStrCat("Parsing ", MessagePath(fileName)));
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::GEN,
+ cmStrCat("Parsing ", this->MessagePath(fileName)));
}
// Read file content
{
std::string error;
- if (!cmQtAutoGenerator::FileRead(Content, fileName, &error)) {
- LogError(
- GenT::GEN,
- cmStrCat("Could not read ", MessagePath(fileName), ".\n", error));
+ if (!cmQtAutoGenerator::FileRead(this->Content, fileName, &error)) {
+ this->LogError(GenT::GEN,
+ cmStrCat("Could not read ", this->MessagePath(fileName),
+ ".\n", error));
return false;
}
}
// Warn if empty
- if (Content.empty()) {
- Log().Warning(GenT::GEN, cmStrCat(MessagePath(fileName), " is empty."));
+ if (this->Content.empty()) {
+ this->Log().Warning(GenT::GEN,
+ cmStrCat(this->MessagePath(fileName), " is empty."));
return false;
}
return true;
@@ -958,16 +960,16 @@ void cmQtAutoMocUicT::JobParseT::CreateKeys(
void cmQtAutoMocUicT::JobParseT::MocMacro()
{
- for (KeyExpT const& filter : MocConst().MacroFilters) {
+ for (KeyExpT const& filter : this->MocConst().MacroFilters) {
// Run a simple find string check
- if (Content.find(filter.Key) == std::string::npos) {
+ if (this->Content.find(filter.Key) == std::string::npos) {
continue;
}
// Run the expensive regular expression check loop
cmsys::RegularExpressionMatch match;
- if (filter.Exp.find(Content.c_str(), match)) {
+ if (filter.Exp.find(this->Content.c_str(), match)) {
// Keep detected macro name
- FileHandle->ParseData->Moc.Macro = filter.Key;
+ this->FileHandle->ParseData->Moc.Macro = filter.Key;
return;
}
}
@@ -975,19 +977,20 @@ void cmQtAutoMocUicT::JobParseT::MocMacro()
void cmQtAutoMocUicT::JobParseT::MocDependecies()
{
- if (MocConst().DependFilters.empty() || MocConst().CanOutputDependencies) {
+ if (this->MocConst().DependFilters.empty() ||
+ this->MocConst().CanOutputDependencies) {
return;
}
// Find dependency strings
std::set<std::string> parseDepends;
- for (KeyExpT const& filter : MocConst().DependFilters) {
+ for (KeyExpT const& filter : this->MocConst().DependFilters) {
// Run a simple find string check
- if (Content.find(filter.Key) == std::string::npos) {
+ if (this->Content.find(filter.Key) == std::string::npos) {
continue;
}
// Run the expensive regular expression check loop
- const char* contentChars = Content.c_str();
+ const char* contentChars = this->Content.c_str();
cmsys::RegularExpressionMatch match;
while (filter.Exp.find(contentChars, match)) {
{
@@ -1002,7 +1005,7 @@ void cmQtAutoMocUicT::JobParseT::MocDependecies()
// Store dependency strings
{
- auto& Depends = FileHandle->ParseData->Moc.Depends;
+ auto& Depends = this->FileHandle->ParseData->Moc.Depends;
Depends.reserve(parseDepends.size());
for (std::string const& item : parseDepends) {
Depends.emplace_back(item);
@@ -1016,15 +1019,15 @@ void cmQtAutoMocUicT::JobParseT::MocDependecies()
void cmQtAutoMocUicT::JobParseT::MocIncludes()
{
- if (Content.find("moc") == std::string::npos) {
+ if (this->Content.find("moc") == std::string::npos) {
return;
}
std::set<std::string> underscore;
std::set<std::string> dot;
{
- const char* contentChars = Content.c_str();
- cmsys::RegularExpression const& regExp = MocConst().RegExpInclude;
+ const char* contentChars = this->Content.c_str();
+ cmsys::RegularExpression const& regExp = this->MocConst().RegExpInclude;
cmsys::RegularExpressionMatch match;
while (regExp.find(contentChars, match)) {
std::string incString = match.match(2);
@@ -1042,21 +1045,21 @@ void cmQtAutoMocUicT::JobParseT::MocIncludes()
contentChars += match.end();
}
}
- auto& Include = FileHandle->ParseData->Moc.Include;
- CreateKeys(Include.Underscore, underscore, MocUnderscoreLength);
- CreateKeys(Include.Dot, dot, 0);
+ auto& Include = this->FileHandle->ParseData->Moc.Include;
+ this->CreateKeys(Include.Underscore, underscore, MocUnderscoreLength);
+ this->CreateKeys(Include.Dot, dot, 0);
}
void cmQtAutoMocUicT::JobParseT::UicIncludes()
{
- if (Content.find("ui_") == std::string::npos) {
+ if (this->Content.find("ui_") == std::string::npos) {
return;
}
std::set<std::string> includes;
{
- const char* contentChars = Content.c_str();
- cmsys::RegularExpression const& regExp = UicConst().RegExpInclude;
+ const char* contentChars = this->Content.c_str();
+ cmsys::RegularExpression const& regExp = this->UicConst().RegExpInclude;
cmsys::RegularExpressionMatch match;
while (regExp.find(contentChars, match)) {
includes.emplace(match.match(2));
@@ -1064,39 +1067,40 @@ void cmQtAutoMocUicT::JobParseT::UicIncludes()
contentChars += match.end();
}
}
- CreateKeys(FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength);
+ this->CreateKeys(this->FileHandle->ParseData->Uic.Include, includes,
+ UiUnderscoreLength);
}
void cmQtAutoMocUicT::JobParseHeaderT::Process()
{
- if (!ReadFile()) {
+ if (!this->ReadFile()) {
return;
}
// Moc parsing
- if (FileHandle->Moc) {
- MocMacro();
- MocDependecies();
+ if (this->FileHandle->Moc) {
+ this->MocMacro();
+ this->MocDependecies();
}
// Uic parsing
- if (FileHandle->Uic) {
- UicIncludes();
+ if (this->FileHandle->Uic) {
+ this->UicIncludes();
}
}
void cmQtAutoMocUicT::JobParseSourceT::Process()
{
- if (!ReadFile()) {
+ if (!this->ReadFile()) {
return;
}
// Moc parsing
- if (FileHandle->Moc) {
- MocMacro();
- MocDependecies();
- MocIncludes();
+ if (this->FileHandle->Moc) {
+ this->MocMacro();
+ this->MocDependecies();
+ this->MocIncludes();
}
// Uic parsing
- if (FileHandle->Uic) {
- UicIncludes();
+ if (this->FileHandle->Uic) {
+ this->UicIncludes();
}
}
@@ -1104,9 +1108,9 @@ std::string cmQtAutoMocUicT::JobEvalCacheT::MessageSearchLocations() const
{
std::string res;
res.reserve(512);
- for (std::string const& path : SearchLocations) {
+ for (std::string const& path : this->SearchLocations) {
res += " ";
- res += MessagePath(path);
+ res += this->MessagePath(path);
res += '\n';
}
return res;
@@ -1115,14 +1119,14 @@ std::string cmQtAutoMocUicT::JobEvalCacheT::MessageSearchLocations() const
void cmQtAutoMocUicT::JobEvalCacheMocT::Process()
{
// Evaluate headers
- for (auto const& pair : BaseEval().Headers) {
- if (!EvalHeader(pair.second)) {
+ for (auto const& pair : this->BaseEval().Headers) {
+ if (!this->EvalHeader(pair.second)) {
return;
}
}
// Evaluate sources
- for (auto const& pair : BaseEval().Sources) {
- if (!EvalSource(pair.second)) {
+ for (auto const& pair : this->BaseEval().Sources) {
+ if (!this->EvalSource(pair.second)) {
return;
}
}
@@ -1142,14 +1146,16 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
handle->SourceFile = std::move(source);
// Absolute build path
- if (BaseConst().MultiConfig) {
- handle->OutputFile = Gen()->AbsoluteIncludePath(sourceFile.BuildPath);
+ if (this->BaseConst().MultiConfig) {
+ handle->OutputFile =
+ this->Gen()->AbsoluteIncludePath(sourceFile.BuildPath);
} else {
- handle->OutputFile = Gen()->AbsoluteBuildPath(sourceFile.BuildPath);
+ handle->OutputFile =
+ this->Gen()->AbsoluteBuildPath(sourceFile.BuildPath);
}
// Register mapping in headers map
- RegisterMapping(handle);
+ this->RegisterMapping(handle);
}
return true;
@@ -1171,7 +1177,7 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
cmSystemTools::GetFilenameWithoutLastExtension(sourceFile.FileName);
// For relaxed mode check if the own "moc_" or ".moc" file is included
- bool const relaxedMode = MocConst().RelaxedMode;
+ bool const relaxedMode = this->MocConst().RelaxedMode;
bool sourceIncludesMocUnderscore = false;
bool sourceIncludesDotMoc = false;
// Check if the sources own "moc_" or ".moc" file is included
@@ -1193,12 +1199,13 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
// Check if this source needs to be moc processed but doesn't.
if (!sourceIncludesDotMoc && !parseData.Macro.empty() &&
!(relaxedMode && sourceIncludesMocUnderscore)) {
- LogError(GenT::MOC,
- cmStrCat(MessagePath(sourceFile.FileName), "\ncontains a ",
- Quoted(parseData.Macro), " macro, but does not include ",
- MessagePath(sourceBase + ".moc"),
- "!\nConsider to\n - add #include \"", sourceBase,
- ".moc\"\n - enable SKIP_AUTOMOC for this file"));
+ this->LogError(GenT::MOC,
+ cmStrCat(this->MessagePath(sourceFile.FileName),
+ "\ncontains a ", Quoted(parseData.Macro),
+ " macro, but does not include ",
+ this->MessagePath(sourceBase + ".moc"),
+ "!\nConsider to\n - add #include \"", sourceBase,
+ ".moc\"\n - enable SKIP_AUTOMOC for this file"));
return false;
}
@@ -1207,14 +1214,16 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
SourceFileHandleT headerHandle;
{
std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
- if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
- LogError(GenT::MOC,
- cmStrCat(MessagePath(sourceFile.FileName),
- "\nincludes the moc file ", MessagePath(incKey.Key),
- ",\nbut a header ", MessageHeader(headerBase),
- "\ncould not be found "
- "in the following directories\n",
- MessageSearchLocations()));
+ if (!this->FindIncludedHeader(headerHandle, sourceDirPrefix,
+ headerBase)) {
+ this->LogError(
+ GenT::MOC,
+ cmStrCat(this->MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", this->MessagePath(incKey.Key),
+ ",\nbut a header ", this->MessageHeader(headerBase),
+ "\ncould not be found "
+ "in the following directories\n",
+ this->MessageSearchLocations()));
return false;
}
}
@@ -1228,30 +1237,31 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
// used. This is for KDE4 compatibility.
// Issue a warning
- Log().Warning(
+ this->Log().Warning(
GenT::MOC,
- cmStrCat(MessagePath(sourceFile.FileName), "\ncontains a ",
+ cmStrCat(this->MessagePath(sourceFile.FileName), "\ncontains a ",
Quoted(parseData.Macro), " macro, but does not include ",
- MessagePath(sourceBase + ".moc"), ".\nInstead it includes ",
- MessagePath(incKey.Key), ".\nRunning moc on the source\n ",
- MessagePath(sourceFile.FileName), "!\nBetter include ",
- MessagePath(sourceBase + ".moc"),
+ this->MessagePath(sourceBase + ".moc"),
+ ".\nInstead it includes ", this->MessagePath(incKey.Key),
+ ".\nRunning moc on the source\n ",
+ this->MessagePath(sourceFile.FileName), "!\nBetter include ",
+ this->MessagePath(sourceBase + ".moc"),
" for compatibility with regular mode.\n",
"This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
// Create mapping
- if (!RegisterIncluded(incKey.Key, source, source)) {
+ if (!this->RegisterIncluded(incKey.Key, source, source)) {
return false;
}
continue;
}
// Check if header is skipped
- if (MocConst().skipped(headerHandle->FileName)) {
+ if (this->MocConst().skipped(headerHandle->FileName)) {
continue;
}
// Create mapping
- if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle))) {
+ if (!this->RegisterIncluded(incKey.Key, source, std::move(headerHandle))) {
return false;
}
}
@@ -1264,7 +1274,7 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
bool const ownMoc = (incKey.Base == sourceBase);
if (ownMoc && !parseData.Macro.empty()) {
// Create mapping for the regular use case
- if (!RegisterIncluded(incKey.Key, source, source)) {
+ if (!this->RegisterIncluded(incKey.Key, source, source)) {
return false;
}
continue;
@@ -1274,50 +1284,54 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
SourceFileHandleT headerHandle;
{
std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
- if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
- LogError(
+ if (!this->FindIncludedHeader(headerHandle, sourceDirPrefix,
+ headerBase)) {
+ this->LogError(
GenT::MOC,
cmStrCat(
- MessagePath(sourceFile.FileName), "\nincludes the moc file ",
- MessagePath(incKey.Key),
+ this->MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", this->MessagePath(incKey.Key),
",\nwhich seems to be the moc file from a different source "
"file.\nCMAKE_AUTOMOC_RELAXED_MODE:\nAlso a matching header ",
- MessageHeader(headerBase),
+ this->MessageHeader(headerBase),
"\ncould not be found in the following directories\n",
- MessageSearchLocations()));
+ this->MessageSearchLocations()));
return false;
}
}
// Check if header is skipped
- if (MocConst().skipped(headerHandle->FileName)) {
+ if (this->MocConst().skipped(headerHandle->FileName)) {
continue;
}
// Issue a warning
if (ownMoc && parseData.Macro.empty()) {
- Log().Warning(
+ this->Log().Warning(
GenT::MOC,
- cmStrCat(MessagePath(sourceFile.FileName),
- "\nincludes the moc file ", MessagePath(incKey.Key),
- ", but does not contain a\n", MocConst().MacrosString(),
- " macro.\nRunning moc on the header\n ",
- MessagePath(headerHandle->FileName), "!\nBetter include ",
- MessagePath("moc_" + incKey.Base + ".cpp"),
- " for a compatibility with regular mode.\n",
- "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
+ cmStrCat(
+ this->MessagePath(sourceFile.FileName), "\nincludes the moc file ",
+ this->MessagePath(incKey.Key), ", but does not contain a\n",
+ this->MocConst().MacrosString(),
+ " macro.\nRunning moc on the header\n ",
+ this->MessagePath(headerHandle->FileName), "!\nBetter include ",
+ this->MessagePath("moc_" + incKey.Base + ".cpp"),
+ " for a compatibility with regular mode.\n",
+ "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
} else {
- Log().Warning(
+ this->Log().Warning(
GenT::MOC,
- cmStrCat(MessagePath(sourceFile.FileName),
- "\nincludes the moc file ", MessagePath(incKey.Key),
- " instead of ", MessagePath("moc_" + incKey.Base + ".cpp"),
- ".\nRunning moc on the header\n ",
- MessagePath(headerHandle->FileName), "!\nBetter include ",
- MessagePath("moc_" + incKey.Base + ".cpp"),
- " for compatibility with regular mode.\n",
- "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
+ cmStrCat(
+ this->MessagePath(sourceFile.FileName), "\nincludes the moc file ",
+ this->MessagePath(incKey.Key), " instead of ",
+ this->MessagePath("moc_" + incKey.Base + ".cpp"),
+ ".\nRunning moc on the header\n ",
+ this->MessagePath(headerHandle->FileName), "!\nBetter include ",
+ this->MessagePath("moc_" + incKey.Base + ".cpp"),
+ " for compatibility with regular mode.\n",
+ "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
}
// Create mapping
- if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle))) {
+ if (!this->RegisterIncluded(incKey.Key, source,
+ std::move(headerHandle))) {
return false;
}
}
@@ -1328,26 +1342,27 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
bool const ownMoc = (incKey.Base == sourceBase);
if (!ownMoc) {
// Don't allow <BASE>.moc include other than own in regular mode
- LogError(GenT::MOC,
- cmStrCat(MessagePath(sourceFile.FileName),
- "\nincludes the moc file ", MessagePath(incKey.Key),
- ",\nwhich seems to be the moc file from a different "
- "source file.\nThis is not supported. Include ",
- MessagePath(sourceBase + ".moc"),
- " to run moc on this source file."));
+ this->LogError(
+ GenT::MOC,
+ cmStrCat(this->MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", this->MessagePath(incKey.Key),
+ ",\nwhich seems to be the moc file from a different "
+ "source file.\nThis is not supported. Include ",
+ this->MessagePath(sourceBase + ".moc"),
+ " to run moc on this source file."));
return false;
}
// Accept but issue a warning if moc isn't required
if (parseData.Macro.empty()) {
- Log().Warning(GenT::MOC,
- cmStrCat(MessagePath(sourceFile.FileName),
- "\nincludes the moc file ",
- MessagePath(incKey.Key),
- ", but does not contain a ",
- MocConst().MacrosString(), " macro."));
+ this->Log().Warning(
+ GenT::MOC,
+ cmStrCat(this->MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", this->MessagePath(incKey.Key),
+ ", but does not contain a ",
+ this->MocConst().MacrosString(), " macro."));
}
// Create mapping
- if (!RegisterIncluded(incKey.Key, source, source)) {
+ if (!this->RegisterIncluded(incKey.Key, source, source)) {
return false;
}
}
@@ -1361,7 +1376,7 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
cm::string_view includeBase)
{
// Clear search locations
- SearchLocations.clear();
+ this->SearchLocations.clear();
auto findHeader = [this,
&headerHandle](std::string const& basePath) -> bool {
@@ -1377,8 +1392,8 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
// Return a known file if it exists already
{
- auto it = BaseEval().Headers.find(testPath);
- if (it != BaseEval().Headers.end()) {
+ auto it = this->BaseEval().Headers.find(testPath);
+ if (it != this->BaseEval().Headers.end()) {
headerHandle = it->second;
found = true;
break;
@@ -1387,7 +1402,8 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
// Created and return discovered file entry
{
- SourceFileHandleT& handle = MocEval().HeadersDiscovered[testPath];
+ SourceFileHandleT& handle =
+ this->MocEval().HeadersDiscovered[testPath];
if (!handle) {
handle = std::make_shared<SourceFileT>(testPath);
handle->FileTime = fileTime;
@@ -1410,13 +1426,12 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
return true;
}
// Search in include directories
- for (std::string const& path : MocConst().IncludePaths) {
- if (findHeader(cmStrCat(path, '/', includeBase))) {
- return true;
- }
- }
- // Return without success
- return false;
+ auto const& includePaths = this->MocConst().IncludePaths;
+ return std::any_of(
+ includePaths.begin(), includePaths.end(),
+ [&findHeader, &includeBase](std::string const& path) -> bool {
+ return findHeader(cmStrCat(path, '/', includeBase));
+ });
}
bool cmQtAutoMocUicT::JobEvalCacheMocT::RegisterIncluded(
@@ -1424,24 +1439,24 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::RegisterIncluded(
SourceFileHandleT sourceFileHandle) const
{
// Check if this file is already included
- MappingHandleT& handle = MocEval().Includes[includeString];
+ MappingHandleT& handle = this->MocEval().Includes[includeString];
if (handle) {
// Check if the output file would be generated from different source files
if (handle->SourceFile != sourceFileHandle) {
std::string files =
- cmStrCat(" ", MessagePath(includerFileHandle->FileName), '\n');
+ cmStrCat(" ", this->MessagePath(includerFileHandle->FileName), '\n');
for (auto const& item : handle->IncluderFiles) {
- files += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ files += cmStrCat(" ", this->MessagePath(item->FileName), '\n');
}
- LogError(
+ this->LogError(
GenT::MOC,
cmStrCat("The source files\n", files,
"contain the same include string ",
- MessagePath(includeString),
+ this->MessagePath(includeString),
", but\nthe moc file would be generated from different "
"source files\n ",
- MessagePath(sourceFileHandle->FileName), " and\n ",
- MessagePath(handle->SourceFile->FileName),
+ this->MessagePath(sourceFileHandle->FileName), " and\n ",
+ this->MessagePath(handle->SourceFile->FileName),
".\nConsider to\n"
" - not include the \"moc_<NAME>.cpp\" file\n"
" - add a directory prefix to a \"<NAME>.moc\" include "
@@ -1460,10 +1475,10 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::RegisterIncluded(
handle->IncludeString = includeString;
handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
handle->SourceFile = std::move(sourceFileHandle);
- handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
+ handle->OutputFile = this->Gen()->AbsoluteIncludePath(includeString);
// Register mapping in sources/headers map
- RegisterMapping(handle);
+ this->RegisterMapping(handle);
return true;
}
@@ -1471,8 +1486,8 @@ void cmQtAutoMocUicT::JobEvalCacheMocT::RegisterMapping(
MappingHandleT mappingHandle) const
{
auto& regMap = mappingHandle->SourceFile->IsHeader
- ? MocEval().HeaderMappings
- : MocEval().SourceMappings;
+ ? this->MocEval().HeaderMappings
+ : this->MocEval().SourceMappings;
// Check if source file already gets mapped
auto& regHandle = regMap[mappingHandle->SourceFile->FileName];
if (!regHandle) {
@@ -1489,24 +1504,24 @@ void cmQtAutoMocUicT::JobEvalCacheMocT::RegisterMapping(
std::string cmQtAutoMocUicT::JobEvalCacheMocT::MessageHeader(
cm::string_view headerBase) const
{
- return MessagePath(cmStrCat(
+ return this->MessagePath(cmStrCat(
headerBase, ".{", cmJoin(this->BaseConst().HeaderExtensions, ","), '}'));
}
void cmQtAutoMocUicT::JobEvalCacheUicT::Process()
{
// Prepare buffers
- SearchLocations.reserve((UicConst().SearchPaths.size() + 1) * 2);
+ this->SearchLocations.reserve((this->UicConst().SearchPaths.size() + 1) * 2);
// Evaluate headers
- for (auto const& pair : BaseEval().Headers) {
- if (!EvalFile(pair.second)) {
+ for (auto const& pair : this->BaseEval().Headers) {
+ if (!this->EvalFile(pair.second)) {
return;
}
}
// Evaluate sources
- for (auto const& pair : BaseEval().Sources) {
- if (!EvalFile(pair.second)) {
+ for (auto const& pair : this->BaseEval().Sources) {
+ if (!this->EvalFile(pair.second)) {
return;
}
}
@@ -1522,36 +1537,37 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::EvalFile(
}
std::string const sourceDirPrefix = SubDirPrefix(sourceFile.FileName);
- for (IncludeKeyT const& incKey : Include) {
- // Find .ui file
- UiName = cmStrCat(incKey.Base, ".ui");
- if (!FindIncludedUi(sourceDirPrefix, incKey.Dir)) {
- LogError(GenT::UIC,
- cmStrCat(MessagePath(sourceFile.FileName),
- "\nincludes the uic file ", MessagePath(incKey.Key),
- ",\nbut the user interface file ", MessagePath(UiName),
- "\ncould not be found in the following directories\n",
- MessageSearchLocations()));
- return false;
- }
- // Check if the file is skipped
- if (UicConst().skipped(UiFileHandle->FileName)) {
- continue;
- }
- // Register mapping
- if (!RegisterMapping(incKey.Key, sourceFileHandle)) {
- return false;
- }
- }
-
- return true;
+ return std::all_of(
+ Include.begin(), Include.end(),
+ [this, &sourceDirPrefix, &sourceFile,
+ &sourceFileHandle](IncludeKeyT const& incKey) -> bool {
+ // Find .ui file
+ this->UiName = cmStrCat(incKey.Base, ".ui");
+ if (!this->FindIncludedUi(sourceDirPrefix, incKey.Dir)) {
+ this->LogError(
+ GenT::UIC,
+ cmStrCat(this->MessagePath(sourceFile.FileName),
+ "\nincludes the uic file ", this->MessagePath(incKey.Key),
+ ",\nbut the user interface file ",
+ this->MessagePath(this->UiName),
+ "\ncould not be found in the following directories\n",
+ this->MessageSearchLocations()));
+ return false;
+ }
+ // Check if the file is skipped
+ if (this->UicConst().skipped(this->UiFileHandle->FileName)) {
+ return true;
+ }
+ // Register mapping
+ return this->RegisterMapping(incKey.Key, sourceFileHandle);
+ });
}
bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
cm::string_view sourceDirPrefix, cm::string_view includePrefix)
{
// Clear locations buffer
- SearchLocations.clear();
+ this->SearchLocations.clear();
auto findUi = [this](std::string const& testPath) -> bool {
std::string const fullPath = this->Gen()->CollapseFullPathTS(testPath);
@@ -1573,25 +1589,25 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
};
// Vicinity of the source
- if (findUi(cmStrCat(sourceDirPrefix, UiName))) {
+ if (findUi(cmStrCat(sourceDirPrefix, this->UiName))) {
return true;
}
if (!includePrefix.empty()) {
- if (findUi(cmStrCat(sourceDirPrefix, includePrefix, UiName))) {
+ if (findUi(cmStrCat(sourceDirPrefix, includePrefix, this->UiName))) {
return true;
}
}
// Additional AUTOUIC search paths
- auto const& searchPaths = UicConst().SearchPaths;
+ auto const& searchPaths = this->UicConst().SearchPaths;
if (!searchPaths.empty()) {
for (std::string const& sPath : searchPaths) {
- if (findUi(cmStrCat(sPath, '/', UiName))) {
+ if (findUi(cmStrCat(sPath, '/', this->UiName))) {
return true;
}
}
if (!includePrefix.empty()) {
for (std::string const& sPath : searchPaths) {
- if (findUi(cmStrCat(sPath, '/', includePrefix, UiName))) {
+ if (findUi(cmStrCat(sPath, '/', includePrefix, this->UiName))) {
return true;
}
}
@@ -1604,26 +1620,26 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
bool cmQtAutoMocUicT::JobEvalCacheUicT::RegisterMapping(
std::string const& includeString, SourceFileHandleT includerFileHandle)
{
- auto& Includes = Gen()->UicEval().Includes;
+ auto& Includes = this->Gen()->UicEval().Includes;
auto it = Includes.find(includeString);
if (it != Includes.end()) {
MappingHandleT const& handle = it->second;
- if (handle->SourceFile != UiFileHandle) {
+ if (handle->SourceFile != this->UiFileHandle) {
// The output file already gets generated - from a different .ui file!
std::string files =
- cmStrCat(" ", MessagePath(includerFileHandle->FileName), '\n');
+ cmStrCat(" ", this->MessagePath(includerFileHandle->FileName), '\n');
for (auto const& item : handle->IncluderFiles) {
- files += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ files += cmStrCat(" ", this->MessagePath(item->FileName), '\n');
}
- LogError(
+ this->LogError(
GenT::UIC,
cmStrCat(
"The source files\n", files, "contain the same include string ",
Quoted(includeString),
", but\nthe uic file would be generated from different "
"user interface files\n ",
- MessagePath(UiFileHandle->FileName), " and\n ",
- MessagePath(handle->SourceFile->FileName),
+ this->MessagePath(this->UiFileHandle->FileName), " and\n ",
+ this->MessagePath(handle->SourceFile->FileName),
".\nConsider to\n"
" - add a directory prefix to a \"ui_<NAME>.h\" include "
"(e.g \"sub/ui_<NAME>.h\")\n"
@@ -1638,8 +1654,8 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::RegisterMapping(
MappingHandleT handle = std::make_shared<MappingT>();
handle->IncludeString = includeString;
handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
- handle->SourceFile = UiFileHandle;
- handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
+ handle->SourceFile = this->UiFileHandle;
+ handle->OutputFile = this->Gen()->AbsoluteIncludePath(includeString);
// Register mapping
Includes.emplace(includeString, std::move(handle));
}
@@ -1649,40 +1665,42 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::RegisterMapping(
void cmQtAutoMocUicT::JobEvalCacheFinishT::Process()
{
// Add discovered header parse jobs
- Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
+ this->Gen()->CreateParseJobs<JobParseHeaderT>(
+ this->MocEval().HeadersDiscovered);
// Add dependency probing jobs
{
// Add fence job to ensure all parsing has finished
- Gen()->WorkerPool().EmplaceJob<JobFenceT>();
- if (MocConst().Enabled) {
- Gen()->WorkerPool().EmplaceJob<JobProbeDepsMocT>();
+ this->Gen()->WorkerPool().EmplaceJob<JobFenceT>();
+ if (this->MocConst().Enabled) {
+ this->Gen()->WorkerPool().EmplaceJob<JobProbeDepsMocT>();
}
- if (UicConst().Enabled) {
- Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
+ if (this->UicConst().Enabled) {
+ this->Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
}
// Add probe finish job
- Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
+ this->Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
}
}
void cmQtAutoMocUicT::JobProbeDepsMocT::Process()
{
// Create moc header jobs
- for (auto const& pair : MocEval().HeaderMappings) {
+ for (auto const& pair : this->MocEval().HeaderMappings) {
// Register if this mapping is a candidate for mocs_compilation.cpp
bool const compFile = pair.second->IncludeString.empty();
if (compFile) {
- MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
+ this->MocEval().CompFiles.emplace_back(
+ pair.second->SourceFile->BuildPath);
}
- if (!Generate(pair.second, compFile)) {
+ if (!this->Generate(pair.second, compFile)) {
return;
}
}
// Create moc source jobs
- for (auto const& pair : MocEval().SourceMappings) {
- if (!Generate(pair.second, false)) {
+ for (auto const& pair : this->MocEval().SourceMappings) {
+ if (!this->Generate(pair.second, false)) {
return;
}
}
@@ -1692,22 +1710,23 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
bool compFile) const
{
std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
+ if (this->Log().Verbose()) {
reason = cm::make_unique<std::string>();
}
- if (Probe(*mapping, reason.get())) {
+ if (this->Probe(*mapping, reason.get())) {
// Register the parent directory for creation
- MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
+ this->MocEval().OutputDirs.emplace(
+ cmQtAutoGen::ParentDir(mapping->OutputFile));
// Fetch the cache entry for the source file
std::string const& sourceFile = mapping->SourceFile->FileName;
ParseCacheT::GetOrInsertT cacheEntry =
- BaseEval().ParseCache.GetOrInsert(sourceFile);
+ this->BaseEval().ParseCache.GetOrInsert(sourceFile);
// Add moc job
- Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(
+ this->Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(
mapping, std::move(reason), std::move(cacheEntry.first));
// Check if a moc job for a mocs_compilation.cpp entry was generated
if (compFile) {
- MocEval().CompUpdated = true;
+ this->MocEval().CompUpdated = true;
}
}
return true;
@@ -1723,19 +1742,19 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
cmFileTime outputFileTime;
if (!outputFileTime.Load(outputFile)) {
if (reason != nullptr) {
- *reason =
- cmStrCat("Generating ", MessagePath(outputFile),
- ", because it doesn't exist, from ", MessagePath(sourceFile));
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
+ ", because it doesn't exist, from ",
+ this->MessagePath(sourceFile));
}
return true;
}
// Test if any setting changed
- if (MocConst().SettingsChanged) {
+ if (this->MocConst().SettingsChanged) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
", because the uic settings changed, from ",
- MessagePath(sourceFile));
+ this->MessagePath(sourceFile));
}
return true;
}
@@ -1743,32 +1762,32 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
// Test if the source file is newer
if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
", because it's older than its source file, from ",
- MessagePath(sourceFile));
+ this->MessagePath(sourceFile));
}
return true;
}
// Test if the moc_predefs file is newer
- if (!MocConst().PredefsFileAbs.empty()) {
- if (outputFileTime.Older(MocEval().PredefsTime)) {
+ if (!this->MocConst().PredefsFileAbs.empty()) {
+ if (outputFileTime.Older(this->MocEval().PredefsTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
", because it's older than ",
- MessagePath(MocConst().PredefsFileAbs), ", from ",
- MessagePath(sourceFile));
+ this->MessagePath(this->MocConst().PredefsFileAbs),
+ ", from ", this->MessagePath(sourceFile));
}
return true;
}
}
// Test if the moc executable is newer
- if (outputFileTime.Older(MocConst().ExecutableTime)) {
+ if (outputFileTime.Older(this->MocConst().ExecutableTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
", because it's older than the moc executable, from ",
- MessagePath(sourceFile));
+ this->MessagePath(sourceFile));
}
return true;
}
@@ -1782,26 +1801,26 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
auto& dep = *it;
// Find dependency file
- auto const depMatch = FindDependency(sourceDir, dep);
+ auto const depMatch = this->FindDependency(sourceDir, dep);
if (depMatch.first.empty()) {
if (reason != nullptr) {
- *reason =
- cmStrCat("Generating ", MessagePath(outputFile), " from ",
- MessagePath(sourceFile), ", because its dependency ",
- MessagePath(dep), " vanished.");
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
+ " from ", this->MessagePath(sourceFile),
+ ", because its dependency ",
+ this->MessagePath(dep), " vanished.");
}
dependencies.erase(it);
- BaseEval().ParseCacheChanged = true;
+ this->BaseEval().ParseCacheChanged = true;
return true;
}
// Test if dependency file is older
if (outputFileTime.Older(depMatch.second)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
", because it's older than its dependency file ",
- MessagePath(depMatch.first), ", from ",
- MessagePath(sourceFile));
+ this->MessagePath(depMatch.first), ", from ",
+ this->MessagePath(sourceFile));
}
return true;
}
@@ -1817,7 +1836,7 @@ cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
{
using ResPair = std::pair<std::string, cmFileTime>;
// moc's dependency file contains absolute paths
- if (MocConst().CanOutputDependencies) {
+ if (this->MocConst().CanOutputDependencies) {
ResPair res{ includeString, {} };
if (res.second.Load(res.first)) {
return res;
@@ -1832,7 +1851,7 @@ cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
}
}
// Search in include directories
- for (std::string const& includePath : MocConst().IncludePaths) {
+ for (std::string const& includePath : this->MocConst().IncludePaths) {
ResPair res{ cmStrCat(includePath, '/', includeString), {} };
if (res.second.Load(res.first)) {
return res;
@@ -1844,20 +1863,22 @@ cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
void cmQtAutoMocUicT::JobProbeDepsUicT::Process()
{
- for (auto const& pair : Gen()->UicEval().Includes) {
+ for (auto const& pair : this->Gen()->UicEval().Includes) {
MappingHandleT const& mapping = pair.second;
std::unique_ptr<std::string> reason;
- if (Log().Verbose()) {
+ if (this->Log().Verbose()) {
reason = cm::make_unique<std::string>();
}
- if (!Probe(*mapping, reason.get())) {
+ if (!this->Probe(*mapping, reason.get())) {
continue;
}
// Register the parent directory for creation
- UicEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
+ this->UicEval().OutputDirs.emplace(
+ cmQtAutoGen::ParentDir(mapping->OutputFile));
// Add uic job
- Gen()->WorkerPool().EmplaceJob<JobCompileUicT>(mapping, std::move(reason));
+ this->Gen()->WorkerPool().EmplaceJob<JobCompileUicT>(mapping,
+ std::move(reason));
}
}
@@ -1871,19 +1892,19 @@ bool cmQtAutoMocUicT::JobProbeDepsUicT::Probe(MappingT const& mapping,
cmFileTime outputFileTime;
if (!outputFileTime.Load(outputFile)) {
if (reason != nullptr) {
- *reason =
- cmStrCat("Generating ", MessagePath(outputFile),
- ", because it doesn't exist, from ", MessagePath(sourceFile));
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
+ ", because it doesn't exist, from ",
+ this->MessagePath(sourceFile));
}
return true;
}
// Test if the uic settings changed
- if (UicConst().SettingsChanged) {
+ if (this->UicConst().SettingsChanged) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
", because the uic settings changed, from ",
- MessagePath(sourceFile));
+ this->MessagePath(sourceFile));
}
return true;
}
@@ -1891,19 +1912,19 @@ bool cmQtAutoMocUicT::JobProbeDepsUicT::Probe(MappingT const& mapping,
// Test if the source file is newer
if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
" because it's older than the source file ",
- MessagePath(sourceFile));
+ this->MessagePath(sourceFile));
}
return true;
}
// Test if the uic executable is newer
- if (outputFileTime.Older(UicConst().ExecutableTime)) {
+ if (outputFileTime.Older(this->UicConst().ExecutableTime)) {
if (reason != nullptr) {
- *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ *reason = cmStrCat("Generating ", this->MessagePath(outputFile),
", because it's older than the uic executable, from ",
- MessagePath(sourceFile));
+ this->MessagePath(sourceFile));
}
return true;
}
@@ -1919,64 +1940,64 @@ void cmQtAutoMocUicT::JobProbeDepsFinishT::Process()
auto createDirs = [this](GenT genType, StringSet const& dirSet) {
for (std::string const& dirName : dirSet) {
if (!cmSystemTools::MakeDirectory(dirName)) {
- this->LogError(
- genType,
- cmStrCat("Creating directory ", MessagePath(dirName), " failed."));
+ this->LogError(genType,
+ cmStrCat("Creating directory ",
+ this->MessagePath(dirName), " failed."));
return;
}
}
};
- if (MocConst().Enabled && UicConst().Enabled) {
- StringSet outputDirs = MocEval().OutputDirs;
- outputDirs.insert(UicEval().OutputDirs.begin(),
- UicEval().OutputDirs.end());
+ if (this->MocConst().Enabled && this->UicConst().Enabled) {
+ StringSet outputDirs = this->MocEval().OutputDirs;
+ outputDirs.insert(this->UicEval().OutputDirs.begin(),
+ this->UicEval().OutputDirs.end());
createDirs(GenT::GEN, outputDirs);
- } else if (MocConst().Enabled) {
- createDirs(GenT::MOC, MocEval().OutputDirs);
- } else if (UicConst().Enabled) {
- createDirs(GenT::UIC, UicEval().OutputDirs);
+ } else if (this->MocConst().Enabled) {
+ createDirs(GenT::MOC, this->MocEval().OutputDirs);
+ } else if (this->UicConst().Enabled) {
+ createDirs(GenT::UIC, this->UicEval().OutputDirs);
}
}
- if (MocConst().Enabled) {
+ if (this->MocConst().Enabled) {
// Add mocs compilations job
- Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
+ this->Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
}
- if (!BaseConst().DepFile.empty()) {
+ if (!this->BaseConst().DepFile.empty()) {
// Add job to merge dep files
- Gen()->WorkerPool().EmplaceJob<JobDepFilesMergeT>();
+ this->Gen()->WorkerPool().EmplaceJob<JobDepFilesMergeT>();
}
// Add finish job
- Gen()->WorkerPool().EmplaceJob<JobFinishT>();
+ this->Gen()->WorkerPool().EmplaceJob<JobFinishT>();
}
void cmQtAutoMocUicT::JobCompileMocT::Process()
{
- std::string const& sourceFile = Mapping->SourceFile->FileName;
- std::string const& outputFile = Mapping->OutputFile;
+ std::string const& sourceFile = this->Mapping->SourceFile->FileName;
+ std::string const& outputFile = this->Mapping->OutputFile;
// Compose moc command
std::vector<std::string> cmd;
{
// Reserve large enough
- cmd.reserve(MocConst().OptionsDefinitions.size() +
- MocConst().OptionsIncludes.size() +
- MocConst().OptionsExtra.size() + 16);
- cmd.push_back(MocConst().Executable);
+ cmd.reserve(this->MocConst().OptionsDefinitions.size() +
+ this->MocConst().OptionsIncludes.size() +
+ this->MocConst().OptionsExtra.size() + 16);
+ cmd.push_back(this->MocConst().Executable);
// Add definitions
- cm::append(cmd, MocConst().OptionsDefinitions);
+ cm::append(cmd, this->MocConst().OptionsDefinitions);
// Add includes
- cm::append(cmd, MocConst().OptionsIncludes);
+ cm::append(cmd, this->MocConst().OptionsIncludes);
// Add predefs include
- if (!MocConst().PredefsFileAbs.empty()) {
+ if (!this->MocConst().PredefsFileAbs.empty()) {
cmd.emplace_back("--include");
- cmd.push_back(MocConst().PredefsFileAbs);
+ cmd.push_back(this->MocConst().PredefsFileAbs);
}
// Add path prefix on demand
- if (MocConst().PathPrefix && Mapping->SourceFile->IsHeader) {
- for (std::string const& dir : MocConst().IncludePaths) {
+ if (this->MocConst().PathPrefix && this->Mapping->SourceFile->IsHeader) {
+ for (std::string const& dir : this->MocConst().IncludePaths) {
cm::string_view prefix = sourceFile;
if (cmHasPrefix(prefix, dir)) {
prefix.remove_prefix(dir.size());
@@ -1996,8 +2017,8 @@ void cmQtAutoMocUicT::JobCompileMocT::Process()
}
}
// Add extra options
- cm::append(cmd, MocConst().OptionsExtra);
- if (MocConst().CanOutputDependencies) {
+ cm::append(cmd, this->MocConst().OptionsExtra);
+ if (this->MocConst().CanOutputDependencies) {
cmd.emplace_back("--output-dep-file");
}
// Add output file
@@ -2009,60 +2030,60 @@ void cmQtAutoMocUicT::JobCompileMocT::Process()
// Execute moc command
cmWorkerPool::ProcessResultT result;
- if (!RunProcess(GenT::MOC, result, cmd, Reason.get())) {
+ if (!this->RunProcess(GenT::MOC, result, cmd, this->Reason.get())) {
// Moc command failed
std::string includers;
- if (!Mapping->IncluderFiles.empty()) {
+ if (!this->Mapping->IncluderFiles.empty()) {
includers = "included by\n";
- for (auto const& item : Mapping->IncluderFiles) {
- includers += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ for (auto const& item : this->Mapping->IncluderFiles) {
+ includers += cmStrCat(" ", this->MessagePath(item->FileName), '\n');
}
}
- LogCommandError(GenT::MOC,
- cmStrCat("The moc process failed to compile\n ",
- MessagePath(sourceFile), "\ninto\n ",
- MessagePath(outputFile), '\n', includers,
- result.ErrorMessage),
- cmd, result.StdOut);
+ this->LogCommandError(GenT::MOC,
+ cmStrCat("The moc process failed to compile\n ",
+ this->MessagePath(sourceFile), "\ninto\n ",
+ this->MessagePath(outputFile), '\n',
+ includers, result.ErrorMessage),
+ cmd, result.StdOut);
return;
}
// Moc command success. Print moc output.
if (!result.StdOut.empty()) {
- Log().Info(GenT::MOC, result.StdOut);
+ this->Log().Info(GenT::MOC, result.StdOut);
}
// Extract dependencies from the dep file moc generated for us
- if (MocConst().CanOutputDependencies) {
+ if (this->MocConst().CanOutputDependencies) {
const std::string depfile = outputFile + ".d";
- if (Log().Verbose()) {
- Log().Info(GenT::MOC,
- "Reading dependencies from " + MessagePath(depfile));
+ if (this->Log().Verbose()) {
+ this->Log().Info(
+ GenT::MOC, "Reading dependencies from " + this->MessagePath(depfile));
}
if (!cmSystemTools::FileExists(depfile)) {
- Log().Warning(GenT::MOC,
- "Dependency file " + MessagePath(depfile) +
- " does not exist.");
+ this->Log().Warning(GenT::MOC,
+ "Dependency file " + this->MessagePath(depfile) +
+ " does not exist.");
return;
}
- CacheEntry->Moc.Depends = dependenciesFromDepFile(depfile.c_str());
+ this->CacheEntry->Moc.Depends = dependenciesFromDepFile(depfile.c_str());
}
}
void cmQtAutoMocUicT::JobCompileUicT::Process()
{
- std::string const& sourceFile = Mapping->SourceFile->FileName;
- std::string const& outputFile = Mapping->OutputFile;
+ std::string const& sourceFile = this->Mapping->SourceFile->FileName;
+ std::string const& outputFile = this->Mapping->OutputFile;
// Compose uic command
std::vector<std::string> cmd;
- cmd.push_back(UicConst().Executable);
+ cmd.push_back(this->UicConst().Executable);
{
- std::vector<std::string> allOpts = UicConst().Options;
- auto optionIt = UicConst().UiFiles.find(sourceFile);
- if (optionIt != UicConst().UiFiles.end()) {
+ std::vector<std::string> allOpts = this->UicConst().Options;
+ auto optionIt = this->UicConst().UiFiles.find(sourceFile);
+ if (optionIt != this->UicConst().UiFiles.end()) {
UicMergeOptions(allOpts, optionIt->second.Options,
- (BaseConst().QtVersion.Major == 5));
+ (this->BaseConst().QtVersion.Major == 5));
}
cm::append(cmd, allOpts);
}
@@ -2071,24 +2092,25 @@ void cmQtAutoMocUicT::JobCompileUicT::Process()
cmd.emplace_back(sourceFile);
cmWorkerPool::ProcessResultT result;
- if (RunProcess(GenT::UIC, result, cmd, Reason.get())) {
+ if (this->RunProcess(GenT::UIC, result, cmd, this->Reason.get())) {
// Uic command success
// Print uic output
if (!result.StdOut.empty()) {
- Log().Info(GenT::UIC, result.StdOut);
+ this->Log().Info(GenT::UIC, result.StdOut);
}
} else {
// Uic command failed
std::string includers;
- for (auto const& item : Mapping->IncluderFiles) {
- includers += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ for (auto const& item : this->Mapping->IncluderFiles) {
+ includers += cmStrCat(" ", this->MessagePath(item->FileName), '\n');
}
- LogCommandError(GenT::UIC,
- cmStrCat("The uic process failed to compile\n ",
- MessagePath(sourceFile), "\ninto\n ",
- MessagePath(outputFile), "\nincluded by\n",
- includers, result.ErrorMessage),
- cmd, result.StdOut);
+ this->LogCommandError(GenT::UIC,
+ cmStrCat("The uic process failed to compile\n ",
+ this->MessagePath(sourceFile), "\ninto\n ",
+ this->MessagePath(outputFile),
+ "\nincluded by\n", includers,
+ result.ErrorMessage),
+ cmd, result.StdOut);
}
}
@@ -2098,41 +2120,41 @@ void cmQtAutoMocUicT::JobMocsCompilationT::Process()
std::string content =
"// This file is autogenerated. Changes will be overwritten.\n";
- if (MocEval().CompFiles.empty()) {
+ if (this->MocEval().CompFiles.empty()) {
// Placeholder content
content += "// No files found that require moc or the moc files are "
"included\n"
"enum some_compilers { need_more_than_nothing };\n";
} else {
// Valid content
- const bool mc = BaseConst().MultiConfig;
+ const bool mc = this->BaseConst().MultiConfig;
cm::string_view const wrapFront = mc ? "#include <" : "#include \"";
cm::string_view const wrapBack = mc ? ">\n" : "\"\n";
- content += cmWrap(wrapFront, MocEval().CompFiles, wrapBack, "");
+ content += cmWrap(wrapFront, this->MocEval().CompFiles, wrapBack, "");
}
- std::string const& compAbs = MocConst().CompFileAbs;
+ std::string const& compAbs = this->MocConst().CompFileAbs;
if (cmQtAutoGenerator::FileDiffers(compAbs, content)) {
// Actually write mocs compilation file
- if (Log().Verbose()) {
- Log().Info(GenT::MOC,
- "Generating MOC compilation " + MessagePath(compAbs));
+ if (this->Log().Verbose()) {
+ this->Log().Info(
+ GenT::MOC, "Generating MOC compilation " + this->MessagePath(compAbs));
}
if (!FileWrite(compAbs, content)) {
- LogError(GenT::MOC,
- cmStrCat("Writing MOC compilation ", MessagePath(compAbs),
- " failed."));
+ this->LogError(GenT::MOC,
+ cmStrCat("Writing MOC compilation ",
+ this->MessagePath(compAbs), " failed."));
}
- } else if (MocEval().CompUpdated) {
+ } else if (this->MocEval().CompUpdated) {
// Only touch mocs compilation file
- if (Log().Verbose()) {
- Log().Info(GenT::MOC,
- "Touching MOC compilation " + MessagePath(compAbs));
+ if (this->Log().Verbose()) {
+ this->Log().Info(
+ GenT::MOC, "Touching MOC compilation " + this->MessagePath(compAbs));
}
if (!cmSystemTools::Touch(compAbs, false)) {
- LogError(GenT::MOC,
- cmStrCat("Touching MOC compilation ", MessagePath(compAbs),
- " failed."));
+ this->LogError(GenT::MOC,
+ cmStrCat("Touching MOC compilation ",
+ this->MessagePath(compAbs), " failed."));
}
}
}
@@ -2169,12 +2191,36 @@ std::string escapeDependencyPath(cm::string_view path)
return escapedPath;
}
+/*
+ * Return the initial dependencies of the merged depfile.
+ * Those are dependencies from the project files, not from moc runs.
+ */
+std::vector<std::string>
+cmQtAutoMocUicT::JobDepFilesMergeT::initialDependencies() const
+{
+ std::vector<std::string> dependencies;
+ dependencies.reserve(this->BaseConst().ListFiles.size() +
+ this->BaseEval().Headers.size() +
+ this->BaseEval().Sources.size());
+ cm::append(dependencies, this->BaseConst().ListFiles);
+ auto append_file_path =
+ [&dependencies](const SourceFileMapT::value_type& p) {
+ dependencies.push_back(p.first);
+ };
+ std::for_each(this->BaseEval().Headers.begin(),
+ this->BaseEval().Headers.end(), append_file_path);
+ std::for_each(this->BaseEval().Sources.begin(),
+ this->BaseEval().Sources.end(), append_file_path);
+ return dependencies;
+}
+
void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
{
- if (Log().Verbose()) {
- Log().Info(GenT::MOC,
- cmStrCat("Merging MOC dependencies into ",
- MessagePath(BaseConst().DepFile.c_str())));
+ if (this->Log().Verbose()) {
+ this->Log().Info(
+ GenT::MOC,
+ cmStrCat("Merging MOC dependencies into ",
+ this->MessagePath(this->BaseConst().DepFile.c_str())));
}
auto processDepFile =
[](const std::string& mocOutputFile) -> std::vector<std::string> {
@@ -2185,8 +2231,8 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
return dependenciesFromDepFile(f.c_str());
};
- std::vector<std::string> dependencies = BaseConst().ListFiles;
- ParseCacheT& parseCache = BaseEval().ParseCache;
+ std::vector<std::string> dependencies = this->initialDependencies();
+ ParseCacheT& parseCache = this->BaseEval().ParseCache;
auto processMappingEntry = [&](const MappingMapT::value_type& m) {
auto cacheEntry = parseCache.GetOrInsert(m.first);
if (cacheEntry.first->Moc.Depends.empty()) {
@@ -2197,10 +2243,10 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
cacheEntry.first->Moc.Depends.end());
};
- std::for_each(MocEval().HeaderMappings.begin(),
- MocEval().HeaderMappings.end(), processMappingEntry);
- std::for_each(MocEval().SourceMappings.begin(),
- MocEval().SourceMappings.end(), processMappingEntry);
+ std::for_each(this->MocEval().HeaderMappings.begin(),
+ this->MocEval().HeaderMappings.end(), processMappingEntry);
+ std::for_each(this->MocEval().SourceMappings.begin(),
+ this->MocEval().SourceMappings.end(), processMappingEntry);
// Remove duplicates to make the depfile smaller
std::sort(dependencies.begin(), dependencies.end());
@@ -2208,39 +2254,42 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
dependencies.end());
// Add form files
- for (const auto& uif : UicEval().UiFiles) {
+ for (const auto& uif : this->UicEval().UiFiles) {
dependencies.push_back(uif.first);
}
// Write the file
cmsys::ofstream ofs;
- ofs.open(BaseConst().DepFile.c_str(),
+ ofs.open(this->BaseConst().DepFile.c_str(),
(std::ios::out | std::ios::binary | std::ios::trunc));
if (!ofs) {
- LogError(GenT::GEN,
- cmStrCat("Cannot open ", MessagePath(BaseConst().DepFile),
- " for writing."));
+ this->LogError(GenT::GEN,
+ cmStrCat("Cannot open ",
+ this->MessagePath(this->BaseConst().DepFile),
+ " for writing."));
return;
}
- ofs << BaseConst().DepFileRuleName << ": \\\n";
+ ofs << this->BaseConst().DepFileRuleName << ": \\\n";
for (const std::string& file : dependencies) {
ofs << '\t' << escapeDependencyPath(file) << " \\\n";
if (!ofs.good()) {
- LogError(GenT::GEN,
- cmStrCat("Writing depfile", MessagePath(BaseConst().DepFile),
- " failed."));
+ this->LogError(GenT::GEN,
+ cmStrCat("Writing depfile",
+ this->MessagePath(this->BaseConst().DepFile),
+ " failed."));
return;
}
}
// Add the CMake executable to re-new cache data if necessary.
// Also, this is the last entry, so don't add a backslash.
- ofs << '\t' << escapeDependencyPath(BaseConst().CMakeExecutable) << '\n';
+ ofs << '\t' << escapeDependencyPath(this->BaseConst().CMakeExecutable)
+ << '\n';
}
void cmQtAutoMocUicT::JobFinishT::Process()
{
- Gen()->AbortSuccess();
+ this->Gen()->AbortSuccess();
}
cmQtAutoMocUicT::cmQtAutoMocUicT()
@@ -2252,42 +2301,51 @@ cmQtAutoMocUicT::~cmQtAutoMocUicT() = default;
bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
{
// -- Required settings
- if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
- !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersion.Major, true) ||
- !info.GetUInt("QT_VERSION_MINOR", BaseConst_.QtVersion.Minor, true) ||
- !info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
- !info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
- !info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir,
+ if (!info.GetBool("MULTI_CONFIG", this->BaseConst_.MultiConfig, true) ||
+ !info.GetUInt("QT_VERSION_MAJOR", this->BaseConst_.QtVersion.Major,
+ true) ||
+ !info.GetUInt("QT_VERSION_MINOR", this->BaseConst_.QtVersion.Minor,
+ true) ||
+ !info.GetUInt("PARALLEL", this->BaseConst_.ThreadCount, false) ||
+ !info.GetString("BUILD_DIR", this->BaseConst_.AutogenBuildDir, true) ||
+ !info.GetStringConfig("INCLUDE_DIR", this->BaseConst_.AutogenIncludeDir,
true) ||
- !info.GetString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
- !info.GetStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile,
- true) ||
- !info.GetString("DEP_FILE", BaseConst_.DepFile, false) ||
- !info.GetString("DEP_FILE_RULE_NAME", BaseConst_.DepFileRuleName,
+ !info.GetString("CMAKE_EXECUTABLE", this->BaseConst_.CMakeExecutable,
+ true) ||
+ !info.GetStringConfig("PARSE_CACHE_FILE",
+ this->BaseConst_.ParseCacheFile, true) ||
+ !info.GetString("DEP_FILE", this->BaseConst_.DepFile, false) ||
+ !info.GetString("DEP_FILE_RULE_NAME", this->BaseConst_.DepFileRuleName,
+ false) ||
+ !info.GetStringConfig("SETTINGS_FILE", this->SettingsFile_, true) ||
+ !info.GetArray("CMAKE_LIST_FILES", this->BaseConst_.ListFiles, true) ||
+ !info.GetArray("HEADER_EXTENSIONS", this->BaseConst_.HeaderExtensions,
+ true) ||
+ !info.GetString("QT_MOC_EXECUTABLE", this->MocConst_.Executable,
false) ||
- !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
- !info.GetArray("CMAKE_LIST_FILES", BaseConst_.ListFiles, true) ||
- !info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
- !info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
- !info.GetString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
+ !info.GetString("QT_UIC_EXECUTABLE", this->UicConst_.Executable,
+ false)) {
return false;
}
// -- Checks
- if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
- return info.LogError(cmStrCat("The CMake executable ",
- MessagePath(BaseConst_.CMakeExecutable),
- " does not exist."));
+ if (!this->BaseConst_.CMakeExecutableTime.Load(
+ this->BaseConst_.CMakeExecutable)) {
+ return info.LogError(
+ cmStrCat("The CMake executable ",
+ this->MessagePath(this->BaseConst_.CMakeExecutable),
+ " does not exist."));
}
// -- Evaluate values
- BaseConst_.ThreadCount = std::min(BaseConst_.ThreadCount, ParallelMax);
- WorkerPool_.SetThreadCount(BaseConst_.ThreadCount);
+ this->BaseConst_.ThreadCount =
+ std::min(this->BaseConst_.ThreadCount, ParallelMax);
+ this->WorkerPool_.SetThreadCount(this->BaseConst_.ThreadCount);
// -- Moc
- if (!MocConst_.Executable.empty()) {
+ if (!this->MocConst_.Executable.empty()) {
// -- Moc is enabled
- MocConst_.Enabled = true;
+ this->MocConst_.Enabled = true;
// -- Temporary buffers
struct
@@ -2297,18 +2355,21 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
} tmp;
// -- Required settings
- if (!info.GetBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
- !info.GetBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
- !info.GetArray("MOC_SKIP", MocConst_.SkipList, false) ||
- !info.GetArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions,
+ if (!info.GetBool("MOC_RELAXED_MODE", this->MocConst_.RelaxedMode,
+ false) ||
+ !info.GetBool("MOC_PATH_PREFIX", this->MocConst_.PathPrefix, true) ||
+ !info.GetArray("MOC_SKIP", this->MocConst_.SkipList, false) ||
+ !info.GetArrayConfig("MOC_DEFINITIONS", this->MocConst_.Definitions,
+ false) ||
+ !info.GetArrayConfig("MOC_INCLUDES", this->MocConst_.IncludePaths,
false) ||
- !info.GetArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
- !info.GetArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
- !info.GetStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
- true) ||
- !info.GetArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
- !info.GetStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
- !MocConst_.PredefsCmd.empty()) ||
+ !info.GetArray("MOC_OPTIONS", this->MocConst_.OptionsExtra, false) ||
+ !info.GetStringConfig("MOC_COMPILATION_FILE",
+ this->MocConst_.CompFileAbs, true) ||
+ !info.GetArray("MOC_PREDEFS_CMD", this->MocConst_.PredefsCmd, false) ||
+ !info.GetStringConfig("MOC_PREDEFS_FILE",
+ this->MocConst_.PredefsFileAbs,
+ !this->MocConst_.PredefsCmd.empty()) ||
!info.GetArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
!info.GetArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
return false;
@@ -2316,12 +2377,12 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
// -- Evaluate settings
for (std::string const& item : tmp.MacroNames) {
- MocConst_.MacroFilters.emplace_back(
+ this->MocConst_.MacroFilters.emplace_back(
item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
}
// Can moc output dependencies or do we need to setup dependency filters?
- if (BaseConst_.QtVersion >= IntegerVersion(5, 15)) {
- MocConst_.CanOutputDependencies = true;
+ if (this->BaseConst_.QtVersion >= IntegerVersion(5, 15)) {
+ this->MocConst_.CanOutputDependencies = true;
} else {
Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS");
if (!val.isArray()) {
@@ -2371,22 +2432,23 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
}
}
// Check if moc executable exists (by reading the file time)
- if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
- return info.LogError(cmStrCat("The moc executable ",
- MessagePath(MocConst_.Executable),
- " does not exist."));
+ if (!this->MocConst_.ExecutableTime.Load(this->MocConst_.Executable)) {
+ return info.LogError(cmStrCat(
+ "The moc executable ", this->MessagePath(this->MocConst_.Executable),
+ " does not exist."));
}
}
// -- Uic
- if (!UicConst_.Executable.empty()) {
+ if (!this->UicConst_.Executable.empty()) {
// Uic is enabled
- UicConst_.Enabled = true;
+ this->UicConst_.Enabled = true;
// -- Required settings
- if (!info.GetArray("UIC_SKIP", UicConst_.SkipList, false) ||
- !info.GetArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
- !info.GetArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
+ if (!info.GetArray("UIC_SKIP", this->UicConst_.SkipList, false) ||
+ !info.GetArray("UIC_SEARCH_PATHS", this->UicConst_.SearchPaths,
+ false) ||
+ !info.GetArrayConfig("UIC_OPTIONS", this->UicConst_.Options, false)) {
return false;
}
// .ui files
@@ -2420,17 +2482,17 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
return false;
}
- auto& uiFile = UicConst_.UiFiles[entryName.asString()];
+ auto& uiFile = this->UicConst_.UiFiles[entryName.asString()];
InfoT::GetJsonArray(uiFile.Options, entryOptions);
}
}
// -- Evaluate settings
// Check if uic executable exists (by reading the file time)
- if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
- return info.LogError(cmStrCat("The uic executable ",
- MessagePath(UicConst_.Executable),
- " does not exist."));
+ if (!this->UicConst_.ExecutableTime.Load(this->UicConst_.Executable)) {
+ return info.LogError(cmStrCat(
+ "The uic executable ", this->MessagePath(this->UicConst_.Executable),
+ " does not exist."));
}
}
@@ -2452,17 +2514,20 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") ||
- testEntry(entry.size() == 3, "JSON array size invalid.")) {
+ testEntry(entry.size() == 4, "JSON array size invalid.")) {
return false;
}
Json::Value const& entryName = entry[0u];
Json::Value const& entryFlags = entry[1u];
Json::Value const& entryBuild = entry[2u];
+ Json::Value const& entryConfigs = entry[3u];
if (testEntry(entryName.isString(),
"JSON value for name is not a string.") ||
testEntry(entryFlags.isString(),
"JSON value for flags is not a string.") ||
+ testEntry(entryConfigs.isNull() || entryConfigs.isArray(),
+ "JSON value for configs is not null or array.") ||
testEntry(entryBuild.isString(),
"JSON value for build path is not a string.")) {
return false;
@@ -2475,6 +2540,22 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
return false;
}
+ if (entryConfigs.isArray()) {
+ bool configFound = false;
+ Json::ArrayIndex const configArraySize = entryConfigs.size();
+ for (Json::ArrayIndex ci = 0; ci != configArraySize; ++ci) {
+ Json::Value const& config = entryConfigs[ci];
+ if (testEntry(config.isString(),
+ "JSON value in config array is not a string.")) {
+ return false;
+ }
+ configFound = configFound || config.asString() == this->InfoConfig();
+ }
+ if (!configFound) {
+ continue;
+ }
+ }
+
cmFileTime fileTime;
if (!fileTime.Load(name)) {
return info.LogError(cmStrCat(
@@ -2486,14 +2567,15 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
sourceHandle->IsHeader = true;
sourceHandle->Moc = (flags[0] == 'M');
sourceHandle->Uic = (flags[1] == 'U');
- if (sourceHandle->Moc && MocConst().Enabled) {
+ if (sourceHandle->Moc && this->MocConst().Enabled) {
if (build.empty()) {
return info.LogError(
cmStrCat("Header file ", ii, " build path is empty"));
}
sourceHandle->BuildPath = std::move(build);
}
- BaseEval().Headers.emplace(std::move(name), std::move(sourceHandle));
+ this->BaseEval().Headers.emplace(std::move(name),
+ std::move(sourceHandle));
}
}
@@ -2515,16 +2597,19 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
Json::Value const& entry = val[ii];
if (testEntry(entry.isArray(), "JSON value is not an array.") ||
- testEntry(entry.size() == 2, "JSON array size invalid.")) {
+ testEntry(entry.size() == 3, "JSON array size invalid.")) {
return false;
}
Json::Value const& entryName = entry[0u];
Json::Value const& entryFlags = entry[1u];
+ Json::Value const& entryConfigs = entry[2u];
if (testEntry(entryName.isString(),
"JSON value for name is not a string.") ||
testEntry(entryFlags.isString(),
- "JSON value for flags is not a string.")) {
+ "JSON value for flags is not a string.") ||
+ testEntry(entryConfigs.isNull() || entryConfigs.isArray(),
+ "JSON value for configs is not null or array.")) {
return false;
}
@@ -2534,6 +2619,22 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
return false;
}
+ if (entryConfigs.isArray()) {
+ bool configFound = false;
+ Json::ArrayIndex const configArraySize = entryConfigs.size();
+ for (Json::ArrayIndex ci = 0; ci != configArraySize; ++ci) {
+ Json::Value const& config = entryConfigs[ci];
+ if (testEntry(config.isString(),
+ "JSON value in config array is not a string.")) {
+ return false;
+ }
+ configFound = configFound || config.asString() == this->InfoConfig();
+ }
+ if (!configFound) {
+ continue;
+ }
+ }
+
cmFileTime fileTime;
if (!fileTime.Load(name)) {
return info.LogError(cmStrCat(
@@ -2545,18 +2646,19 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
sourceHandle->IsHeader = false;
sourceHandle->Moc = (flags[0] == 'M');
sourceHandle->Uic = (flags[1] == 'U');
- BaseEval().Sources.emplace(std::move(name), std::move(sourceHandle));
+ this->BaseEval().Sources.emplace(std::move(name),
+ std::move(sourceHandle));
}
}
// -- Init derived information
// Moc variables
- if (MocConst().Enabled) {
+ if (this->MocConst().Enabled) {
// Compose moc includes list
{
// Compute framework paths
std::set<std::string> frameworkPaths;
- for (std::string const& path : MocConst().IncludePaths) {
+ for (std::string const& path : this->MocConst().IncludePaths) {
// Extract framework path
if (cmHasLiteralSuffix(path, ".framework/Headers")) {
// Go up twice to get to the framework root
@@ -2567,24 +2669,25 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
}
}
// Reserve options
- MocConst_.OptionsIncludes.reserve(MocConst().IncludePaths.size() +
- frameworkPaths.size() * 2);
+ this->MocConst_.OptionsIncludes.reserve(
+ this->MocConst().IncludePaths.size() + frameworkPaths.size() * 2);
// Append includes
- for (std::string const& path : MocConst().IncludePaths) {
- MocConst_.OptionsIncludes.emplace_back("-I" + path);
+ for (std::string const& path : this->MocConst().IncludePaths) {
+ this->MocConst_.OptionsIncludes.emplace_back("-I" + path);
}
// Append framework includes
for (std::string const& path : frameworkPaths) {
- MocConst_.OptionsIncludes.emplace_back("-F");
- MocConst_.OptionsIncludes.push_back(path);
+ this->MocConst_.OptionsIncludes.emplace_back("-F");
+ this->MocConst_.OptionsIncludes.push_back(path);
}
}
// Compose moc definitions list
{
- MocConst_.OptionsDefinitions.reserve(MocConst().Definitions.size());
- for (std::string const& def : MocConst().Definitions) {
- MocConst_.OptionsDefinitions.emplace_back("-D" + def);
+ this->MocConst_.OptionsDefinitions.reserve(
+ this->MocConst().Definitions.size());
+ for (std::string const& def : this->MocConst().Definitions) {
+ this->MocConst_.OptionsDefinitions.emplace_back("-D" + def);
}
}
}
@@ -2595,16 +2698,16 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
template <class JOBTYPE>
void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
{
- cmFileTime const parseCacheTime = BaseEval().ParseCacheTime;
- ParseCacheT& parseCache = BaseEval().ParseCache;
- for (auto& src : sourceMap) {
+ cmFileTime const parseCacheTime = this->BaseEval().ParseCacheTime;
+ ParseCacheT& parseCache = this->BaseEval().ParseCache;
+ for (const auto& src : sourceMap) {
// Get or create the file parse data reference
ParseCacheT::GetOrInsertT cacheEntry = parseCache.GetOrInsert(src.first);
src.second->ParseData = std::move(cacheEntry.first);
// Create a parse job if the cache file was missing or is older
if (cacheEntry.second || src.second->FileTime.Newer(parseCacheTime)) {
- BaseEval().ParseCacheChanged = true;
- WorkerPool().EmplaceJob<JOBTYPE>(src.second);
+ this->BaseEval().ParseCacheChanged = true;
+ this->WorkerPool().EmplaceJob<JOBTYPE>(src.second);
}
}
}
@@ -2612,55 +2715,56 @@ void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
/** Concurrently callable implementation of cmSystemTools::CollapseFullPath */
std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const
{
- std::lock_guard<std::mutex> guard(CMakeLibMutex_);
- return cmSystemTools::CollapseFullPath(path, ProjectDirs().CurrentSource);
+ std::lock_guard<std::mutex> guard(this->CMakeLibMutex_);
+ return cmSystemTools::CollapseFullPath(path,
+ this->ProjectDirs().CurrentSource);
}
void cmQtAutoMocUicT::InitJobs()
{
// Add moc_predefs.h job
- if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
- WorkerPool().EmplaceJob<JobMocPredefsT>();
+ if (this->MocConst().Enabled && !this->MocConst().PredefsCmd.empty()) {
+ this->WorkerPool().EmplaceJob<JobMocPredefsT>();
}
// Add header parse jobs
- CreateParseJobs<JobParseHeaderT>(BaseEval().Headers);
+ this->CreateParseJobs<JobParseHeaderT>(this->BaseEval().Headers);
// Add source parse jobs
- CreateParseJobs<JobParseSourceT>(BaseEval().Sources);
+ this->CreateParseJobs<JobParseSourceT>(this->BaseEval().Sources);
// Add parse cache evaluations jobs
{
// Add a fence job to ensure all parsing has finished
- WorkerPool().EmplaceJob<JobFenceT>();
- if (MocConst().Enabled) {
- WorkerPool().EmplaceJob<JobEvalCacheMocT>();
+ this->WorkerPool().EmplaceJob<JobFenceT>();
+ if (this->MocConst().Enabled) {
+ this->WorkerPool().EmplaceJob<JobEvalCacheMocT>();
}
- if (UicConst().Enabled) {
- WorkerPool().EmplaceJob<JobEvalCacheUicT>();
+ if (this->UicConst().Enabled) {
+ this->WorkerPool().EmplaceJob<JobEvalCacheUicT>();
}
// Add evaluate job
- WorkerPool().EmplaceJob<JobEvalCacheFinishT>();
+ this->WorkerPool().EmplaceJob<JobEvalCacheFinishT>();
}
}
bool cmQtAutoMocUicT::Process()
{
- SettingsFileRead();
- ParseCacheRead();
- if (!CreateDirectories()) {
+ this->SettingsFileRead();
+ this->ParseCacheRead();
+ if (!this->CreateDirectories()) {
return false;
}
- InitJobs();
- if (!WorkerPool_.Process(this)) {
+ this->InitJobs();
+ if (!this->WorkerPool_.Process(this)) {
return false;
}
- if (JobError_) {
+ if (this->JobError_) {
return false;
}
- if (!ParseCacheWrite()) {
+ if (!this->ParseCacheWrite()) {
return false;
}
- if (!SettingsFileWrite()) {
+ if (!this->SettingsFileWrite()) {
return false;
}
return true;
@@ -2676,70 +2780,72 @@ void cmQtAutoMocUicT::SettingsFileRead()
cryptoHash.Append(";");
};
- if (MocConst_.Enabled) {
+ if (this->MocConst_.Enabled) {
cryptoHash.Initialize();
- cha(MocConst().Executable);
- for (auto const& item : MocConst().OptionsDefinitions) {
+ cha(this->MocConst().Executable);
+ for (auto const& item : this->MocConst().OptionsDefinitions) {
cha(item);
}
- for (auto const& item : MocConst().OptionsIncludes) {
+ for (auto const& item : this->MocConst().OptionsIncludes) {
cha(item);
}
- for (auto const& item : MocConst().OptionsExtra) {
+ for (auto const& item : this->MocConst().OptionsExtra) {
cha(item);
}
- for (auto const& item : MocConst().PredefsCmd) {
+ for (auto const& item : this->MocConst().PredefsCmd) {
cha(item);
}
- for (auto const& filter : MocConst().DependFilters) {
+ for (auto const& filter : this->MocConst().DependFilters) {
cha(filter.Key);
}
- for (auto const& filter : MocConst().MacroFilters) {
+ for (auto const& filter : this->MocConst().MacroFilters) {
cha(filter.Key);
}
- SettingsStringMoc_ = cryptoHash.FinalizeHex();
+ this->SettingsStringMoc_ = cryptoHash.FinalizeHex();
}
- if (UicConst().Enabled) {
+ if (this->UicConst().Enabled) {
cryptoHash.Initialize();
- cha(UicConst().Executable);
- std::for_each(UicConst().Options.begin(), UicConst().Options.end(), cha);
- for (const auto& item : UicConst().UiFiles) {
+ cha(this->UicConst().Executable);
+ std::for_each(this->UicConst().Options.begin(),
+ this->UicConst().Options.end(), cha);
+ for (const auto& item : this->UicConst().UiFiles) {
cha(item.first);
auto const& opts = item.second.Options;
std::for_each(opts.begin(), opts.end(), cha);
}
- SettingsStringUic_ = cryptoHash.FinalizeHex();
+ this->SettingsStringUic_ = cryptoHash.FinalizeHex();
}
}
// Read old settings and compare
{
std::string content;
- if (cmQtAutoGenerator::FileRead(content, SettingsFile_)) {
- if (MocConst().Enabled) {
- if (SettingsStringMoc_ != SettingsFind(content, "moc")) {
- MocConst_.SettingsChanged = true;
+ if (cmQtAutoGenerator::FileRead(content, this->SettingsFile_)) {
+ if (this->MocConst().Enabled) {
+ if (this->SettingsStringMoc_ != SettingsFind(content, "moc")) {
+ this->MocConst_.SettingsChanged = true;
}
}
- if (UicConst().Enabled) {
- if (SettingsStringUic_ != SettingsFind(content, "uic")) {
- UicConst_.SettingsChanged = true;
+ if (this->UicConst().Enabled) {
+ if (this->SettingsStringUic_ != SettingsFind(content, "uic")) {
+ this->UicConst_.SettingsChanged = true;
}
}
// In case any setting changed remove the old settings file.
// This triggers a full rebuild on the next run if the current
// build is aborted before writing the current settings in the end.
- if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
- cmSystemTools::RemoveFile(SettingsFile_);
+ if (this->MocConst().SettingsChanged ||
+ this->UicConst().SettingsChanged) {
+ cmSystemTools::RemoveFile(this->SettingsFile_);
}
} else {
// Settings file read failed
- if (MocConst().Enabled) {
- MocConst_.SettingsChanged = true;
+ if (this->MocConst().Enabled) {
+ this->MocConst_.SettingsChanged = true;
}
- if (UicConst().Enabled) {
- UicConst_.SettingsChanged = true;
+ if (this->UicConst().Enabled) {
+ this->UicConst_.SettingsChanged = true;
}
}
}
@@ -2748,11 +2854,11 @@ void cmQtAutoMocUicT::SettingsFileRead()
bool cmQtAutoMocUicT::SettingsFileWrite()
{
// Only write if any setting changed
- if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
- if (Log().Verbose()) {
- Log().Info(
- GenT::GEN,
- cmStrCat("Writing the settings file ", MessagePath(SettingsFile_)));
+ if (this->MocConst().SettingsChanged || this->UicConst().SettingsChanged) {
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::GEN,
+ cmStrCat("Writing the settings file ",
+ this->MessagePath(this->SettingsFile_)));
}
// Compose settings file content
std::string content;
@@ -2763,17 +2869,18 @@ bool cmQtAutoMocUicT::SettingsFileWrite()
content += cmStrCat(key, ':', value, '\n');
}
};
- SettingAppend("moc", SettingsStringMoc_);
- SettingAppend("uic", SettingsStringUic_);
+ SettingAppend("moc", this->SettingsStringMoc_);
+ SettingAppend("uic", this->SettingsStringUic_);
}
// Write settings file
std::string error;
- if (!cmQtAutoGenerator::FileWrite(SettingsFile_, content, &error)) {
- Log().Error(GenT::GEN,
- cmStrCat("Writing the settings file ",
- MessagePath(SettingsFile_), " failed.\n", error));
+ if (!cmQtAutoGenerator::FileWrite(this->SettingsFile_, content, &error)) {
+ this->Log().Error(GenT::GEN,
+ cmStrCat("Writing the settings file ",
+ this->MessagePath(this->SettingsFile_),
+ " failed.\n", error));
// Remove old settings file to trigger a full rebuild on the next run
- cmSystemTools::RemoveFile(SettingsFile_);
+ cmSystemTools::RemoveFile(this->SettingsFile_);
return false;
}
}
@@ -2784,41 +2891,46 @@ void cmQtAutoMocUicT::ParseCacheRead()
{
cm::string_view reason;
// Don't read the cache if it is invalid
- if (!BaseEval().ParseCacheTime.Load(BaseConst().ParseCacheFile)) {
+ if (!this->BaseEval().ParseCacheTime.Load(
+ this->BaseConst().ParseCacheFile)) {
reason = "Refreshing parse cache because it doesn't exist.";
- } else if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
+ } else if (this->MocConst().SettingsChanged ||
+ this->UicConst().SettingsChanged) {
reason = "Refreshing parse cache because the settings changed.";
- } else if (BaseEval().ParseCacheTime.Older(
- BaseConst().CMakeExecutableTime)) {
+ } else if (this->BaseEval().ParseCacheTime.Older(
+ this->BaseConst().CMakeExecutableTime)) {
reason =
"Refreshing parse cache because it is older than the CMake executable.";
}
if (!reason.empty()) {
// Don't read but refresh the complete parse cache
- if (Log().Verbose()) {
- Log().Info(GenT::GEN, reason);
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::GEN, reason);
}
- BaseEval().ParseCacheChanged = true;
+ this->BaseEval().ParseCacheChanged = true;
} else {
// Read parse cache
- BaseEval().ParseCache.ReadFromFile(BaseConst().ParseCacheFile);
+ this->BaseEval().ParseCache.ReadFromFile(this->BaseConst().ParseCacheFile);
}
}
bool cmQtAutoMocUicT::ParseCacheWrite()
{
- if (BaseEval().ParseCacheChanged) {
- if (Log().Verbose()) {
- Log().Info(GenT::GEN,
- cmStrCat("Writing the parse cache file ",
- MessagePath(BaseConst().ParseCacheFile)));
- }
- if (!BaseEval().ParseCache.WriteToFile(BaseConst().ParseCacheFile)) {
- Log().Error(GenT::GEN,
- cmStrCat("Writing the parse cache file ",
- MessagePath(BaseConst().ParseCacheFile),
- " failed."));
+ if (this->BaseEval().ParseCacheChanged) {
+ if (this->Log().Verbose()) {
+ this->Log().Info(
+ GenT::GEN,
+ cmStrCat("Writing the parse cache file ",
+ this->MessagePath(this->BaseConst().ParseCacheFile)));
+ }
+ if (!this->BaseEval().ParseCache.WriteToFile(
+ this->BaseConst().ParseCacheFile)) {
+ this->Log().Error(
+ GenT::GEN,
+ cmStrCat("Writing the parse cache file ",
+ this->MessagePath(this->BaseConst().ParseCacheFile),
+ " failed."));
return false;
}
}
@@ -2828,11 +2940,12 @@ bool cmQtAutoMocUicT::ParseCacheWrite()
bool cmQtAutoMocUicT::CreateDirectories()
{
// Create AUTOGEN include directory
- if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
- Log().Error(GenT::GEN,
- cmStrCat("Creating the AUTOGEN include directory ",
- MessagePath(BaseConst().AutogenIncludeDir),
- " failed."));
+ if (!cmSystemTools::MakeDirectory(this->BaseConst().AutogenIncludeDir)) {
+ this->Log().Error(
+ GenT::GEN,
+ cmStrCat("Creating the AUTOGEN include directory ",
+ this->MessagePath(this->BaseConst().AutogenIncludeDir),
+ " failed."));
return false;
}
return true;
@@ -2841,34 +2954,34 @@ bool cmQtAutoMocUicT::CreateDirectories()
std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
const char* filePath)
{
- cmGccDepfileContent content = cmReadGccDepfile(filePath);
- if (content.empty()) {
+ auto const content = cmReadGccDepfile(filePath);
+ if (!content || content->empty()) {
return {};
}
// Moc outputs a depfile with exactly one rule.
// Discard the rule and return the dependencies.
- return content.front().paths;
+ return content->front().paths;
}
void cmQtAutoMocUicT::Abort(bool error)
{
if (error) {
- JobError_.store(true);
+ this->JobError_.store(true);
}
- WorkerPool_.Abort();
+ this->WorkerPool_.Abort();
}
std::string cmQtAutoMocUicT::AbsoluteBuildPath(
cm::string_view relativePath) const
{
- return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath);
+ return cmStrCat(this->BaseConst().AutogenBuildDir, '/', relativePath);
}
std::string cmQtAutoMocUicT::AbsoluteIncludePath(
cm::string_view relativePath) const
{
- return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath);
+ return cmStrCat(this->BaseConst().AutogenIncludeDir, '/', relativePath);
}
} // End of unnamed namespace
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index 08eb4b5e2..414a69275 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -35,7 +35,7 @@ public:
private:
// -- Utility
- bool IsMultiConfig() const { return MultiConfig_; }
+ bool IsMultiConfig() const { return this->MultiConfig_; }
std::string MultiConfigOutput() const;
// -- Abstract processing interface
@@ -52,7 +52,6 @@ private:
bool GenerateRcc();
bool GenerateWrapper();
-private:
// -- Config settings
bool MultiConfig_ = false;
// -- Directories
@@ -93,38 +92,41 @@ cmQtAutoRccT::~cmQtAutoRccT() = default;
bool cmQtAutoRccT::InitFromInfo(InfoT const& info)
{
// -- Required settings
- if (!info.GetBool("MULTI_CONFIG", MultiConfig_, true) ||
- !info.GetString("BUILD_DIR", AutogenBuildDir_, true) ||
- !info.GetStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
- !info.GetString("RCC_EXECUTABLE", RccExecutable_, true) ||
- !info.GetArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
- !info.GetString("LOCK_FILE", LockFile_, true) ||
- !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
- !info.GetString("SOURCE", QrcFile_, true) ||
- !info.GetString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
- !info.GetString("OUTPUT_NAME", RccFileName_, true) ||
- !info.GetArray("OPTIONS", Options_, false) ||
- !info.GetArray("INPUTS", Inputs_, false)) {
+ if (!info.GetBool("MULTI_CONFIG", this->MultiConfig_, true) ||
+ !info.GetString("BUILD_DIR", this->AutogenBuildDir_, true) ||
+ !info.GetStringConfig("INCLUDE_DIR", this->IncludeDir_, true) ||
+ !info.GetString("RCC_EXECUTABLE", this->RccExecutable_, true) ||
+ !info.GetArray("RCC_LIST_OPTIONS", this->RccListOptions_, false) ||
+ !info.GetString("LOCK_FILE", this->LockFile_, true) ||
+ !info.GetStringConfig("SETTINGS_FILE", this->SettingsFile_, true) ||
+ !info.GetString("SOURCE", this->QrcFile_, true) ||
+ !info.GetString("OUTPUT_CHECKSUM", this->RccPathChecksum_, true) ||
+ !info.GetString("OUTPUT_NAME", this->RccFileName_, true) ||
+ !info.GetArray("OPTIONS", this->Options_, false) ||
+ !info.GetArray("INPUTS", this->Inputs_, false)) {
return false;
}
// -- Derive information
- QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
- QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
- RccFilePublic_ =
- cmStrCat(AutogenBuildDir_, '/', RccPathChecksum_, '/', RccFileName_);
+ this->QrcFileName_ = cmSystemTools::GetFilenameName(this->QrcFile_);
+ this->QrcFileDir_ = cmSystemTools::GetFilenamePath(this->QrcFile_);
+ this->RccFilePublic_ =
+ cmStrCat(this->AutogenBuildDir_, '/', this->RccPathChecksum_, '/',
+ this->RccFileName_);
// rcc output file name
- if (IsMultiConfig()) {
- RccFileOutput_ = cmStrCat(IncludeDir_, '/', MultiConfigOutput());
+ if (this->IsMultiConfig()) {
+ this->RccFileOutput_ =
+ cmStrCat(this->IncludeDir_, '/', this->MultiConfigOutput());
} else {
- RccFileOutput_ = RccFilePublic_;
+ this->RccFileOutput_ = this->RccFilePublic_;
}
// -- Checks
- if (!RccExecutableTime_.Load(RccExecutable_)) {
- return info.LogError(cmStrCat(
- "The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
+ if (!this->RccExecutableTime_.Load(this->RccExecutable_)) {
+ return info.LogError(cmStrCat("The rcc executable ",
+ this->MessagePath(this->RccExecutable_),
+ " does not exist."));
}
return true;
@@ -132,41 +134,41 @@ bool cmQtAutoRccT::InitFromInfo(InfoT const& info)
bool cmQtAutoRccT::Process()
{
- if (!SettingsFileRead()) {
+ if (!this->SettingsFileRead()) {
return false;
}
// Test if the rcc output needs to be regenerated
bool generate = false;
- if (!TestQrcRccFiles(generate)) {
+ if (!this->TestQrcRccFiles(generate)) {
return false;
}
- if (!generate && !TestResources(generate)) {
+ if (!generate && !this->TestResources(generate)) {
return false;
}
// Generate on demand
if (generate) {
- if (!GenerateRcc()) {
+ if (!this->GenerateRcc()) {
return false;
}
} else {
// Test if the info file is newer than the output file
- if (!TestInfoFile()) {
+ if (!this->TestInfoFile()) {
return false;
}
}
- if (!GenerateWrapper()) {
+ if (!this->GenerateWrapper()) {
return false;
}
- return SettingsFileWrite();
+ return this->SettingsFileWrite();
}
std::string cmQtAutoRccT::MultiConfigOutput() const
{
- return cmStrCat(RccPathChecksum_, '/',
- AppendFilenameSuffix(RccFileName_, "_CMAKE_"));
+ return cmStrCat(this->RccPathChecksum_, '/',
+ AppendFilenameSuffix(this->RccFileName_, "_CMAKE_"));
}
bool cmQtAutoRccT::SettingsFileRead()
@@ -178,23 +180,25 @@ bool cmQtAutoRccT::SettingsFileRead()
cryptoHash.Append(value);
cryptoHash.Append(";");
};
- cha(RccExecutable_);
- std::for_each(RccListOptions_.begin(), RccListOptions_.end(), cha);
- cha(QrcFile_);
- cha(RccPathChecksum_);
- cha(RccFileName_);
- std::for_each(Options_.begin(), Options_.end(), cha);
- std::for_each(Inputs_.begin(), Inputs_.end(), cha);
- SettingsString_ = cryptoHash.FinalizeHex();
+ cha(this->RccExecutable_);
+ std::for_each(this->RccListOptions_.begin(), this->RccListOptions_.end(),
+ cha);
+ cha(this->QrcFile_);
+ cha(this->RccPathChecksum_);
+ cha(this->RccFileName_);
+ std::for_each(this->Options_.begin(), this->Options_.end(), cha);
+ std::for_each(this->Inputs_.begin(), this->Inputs_.end(), cha);
+ this->SettingsString_ = cryptoHash.FinalizeHex();
}
// Make sure the settings file exists
- if (!cmSystemTools::FileExists(SettingsFile_, true)) {
+ if (!cmSystemTools::FileExists(this->SettingsFile_, true)) {
// Touch the settings file to make sure it exists
- if (!cmSystemTools::Touch(SettingsFile_, true)) {
- Log().Error(GenT::RCC,
- cmStrCat("Touching the settings file ",
- MessagePath(SettingsFile_), " failed."));
+ if (!cmSystemTools::Touch(this->SettingsFile_, true)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Touching the settings file ",
+ this->MessagePath(this->SettingsFile_),
+ " failed."));
return false;
}
}
@@ -202,21 +206,23 @@ bool cmQtAutoRccT::SettingsFileRead()
// Lock the lock file
{
// Make sure the lock file exists
- if (!cmSystemTools::FileExists(LockFile_, true)) {
- if (!cmSystemTools::Touch(LockFile_, true)) {
- Log().Error(GenT::RCC,
- cmStrCat("Touching the lock file ", MessagePath(LockFile_),
- " failed."));
+ if (!cmSystemTools::FileExists(this->LockFile_, true)) {
+ if (!cmSystemTools::Touch(this->LockFile_, true)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Touching the lock file ",
+ this->MessagePath(this->LockFile_),
+ " failed."));
return false;
}
}
// Lock the lock file
- cmFileLockResult lockResult =
- LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
+ cmFileLockResult lockResult = this->LockFileLock_.Lock(
+ this->LockFile_, static_cast<unsigned long>(-1));
if (!lockResult.IsOk()) {
- Log().Error(GenT::RCC,
- cmStrCat("Locking of the lock file ", MessagePath(LockFile_),
- " failed.\n", lockResult.GetOutputMessage()));
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Locking of the lock file ",
+ this->MessagePath(this->LockFile_),
+ " failed.\n", lockResult.GetOutputMessage()));
return false;
}
}
@@ -224,23 +230,24 @@ bool cmQtAutoRccT::SettingsFileRead()
// Read old settings
{
std::string content;
- if (FileRead(content, SettingsFile_)) {
- SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
+ if (FileRead(content, this->SettingsFile_)) {
+ this->SettingsChanged_ =
+ (this->SettingsString_ != SettingsFind(content, "rcc"));
// In case any setting changed clear the old settings file.
// This triggers a full rebuild on the next run if the current
// build is aborted before writing the current settings in the end.
- if (SettingsChanged_) {
+ if (this->SettingsChanged_) {
std::string error;
- if (!FileWrite(SettingsFile_, "", &error)) {
- Log().Error(GenT::RCC,
- cmStrCat("Clearing of the settings file ",
- MessagePath(SettingsFile_), " failed.\n",
- error));
+ if (!FileWrite(this->SettingsFile_, "", &error)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Clearing of the settings file ",
+ this->MessagePath(this->SettingsFile_),
+ " failed.\n", error));
return false;
}
}
} else {
- SettingsChanged_ = true;
+ this->SettingsChanged_ = true;
}
}
@@ -250,26 +257,28 @@ bool cmQtAutoRccT::SettingsFileRead()
bool cmQtAutoRccT::SettingsFileWrite()
{
// Only write if any setting changed
- if (SettingsChanged_) {
- if (Log().Verbose()) {
- Log().Info(GenT::RCC,
- "Writing settings file " + MessagePath(SettingsFile_));
+ if (this->SettingsChanged_) {
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::RCC,
+ "Writing settings file " +
+ this->MessagePath(this->SettingsFile_));
}
// Write settings file
- std::string content = cmStrCat("rcc:", SettingsString_, '\n');
+ std::string content = cmStrCat("rcc:", this->SettingsString_, '\n');
std::string error;
- if (!FileWrite(SettingsFile_, content, &error)) {
- Log().Error(GenT::RCC,
- cmStrCat("Writing of the settings file ",
- MessagePath(SettingsFile_), " failed.\n", error));
+ if (!FileWrite(this->SettingsFile_, content, &error)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Writing of the settings file ",
+ this->MessagePath(this->SettingsFile_),
+ " failed.\n", error));
// Remove old settings file to trigger a full rebuild on the next run
- cmSystemTools::RemoveFile(SettingsFile_);
+ cmSystemTools::RemoveFile(this->SettingsFile_);
return false;
}
}
// Unlock the lock file
- LockFileLock_.Release();
+ this->LockFileLock_.Release();
return true;
}
@@ -277,52 +286,57 @@ bool cmQtAutoRccT::SettingsFileWrite()
bool cmQtAutoRccT::TestQrcRccFiles(bool& generate)
{
// Test if the rcc input file exists
- if (!QrcFileTime_.Load(QrcFile_)) {
- Log().Error(GenT::RCC,
- cmStrCat("The resources file ", MessagePath(QrcFile_),
- " does not exist"));
+ if (!this->QrcFileTime_.Load(this->QrcFile_)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("The resources file ",
+ this->MessagePath(this->QrcFile_),
+ " does not exist"));
return false;
}
// Test if the rcc output file exists
- if (!RccFileTime_.Load(RccFileOutput_)) {
- if (Log().Verbose()) {
- Reason =
- cmStrCat("Generating ", MessagePath(RccFileOutput_),
- ", because it doesn't exist, from ", MessagePath(QrcFile_));
+ if (!this->RccFileTime_.Load(this->RccFileOutput_)) {
+ if (this->Log().Verbose()) {
+ this->Reason =
+ cmStrCat("Generating ", this->MessagePath(this->RccFileOutput_),
+ ", because it doesn't exist, from ",
+ this->MessagePath(this->QrcFile_));
}
generate = true;
return true;
}
// Test if the settings changed
- if (SettingsChanged_) {
- if (Log().Verbose()) {
- Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
- ", because the rcc settings changed, from ",
- MessagePath(QrcFile_));
+ if (this->SettingsChanged_) {
+ if (this->Log().Verbose()) {
+ this->Reason =
+ cmStrCat("Generating ", this->MessagePath(this->RccFileOutput_),
+ ", because the rcc settings changed, from ",
+ this->MessagePath(this->QrcFile_));
}
generate = true;
return true;
}
// Test if the rcc output file is older than the .qrc file
- if (RccFileTime_.Older(QrcFileTime_)) {
- if (Log().Verbose()) {
- Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
- ", because it is older than ", MessagePath(QrcFile_),
- ", from ", MessagePath(QrcFile_));
+ if (this->RccFileTime_.Older(this->QrcFileTime_)) {
+ if (this->Log().Verbose()) {
+ this->Reason = cmStrCat(
+ "Generating ", this->MessagePath(this->RccFileOutput_),
+ ", because it is older than ", this->MessagePath(this->QrcFile_),
+ ", from ", this->MessagePath(this->QrcFile_));
}
generate = true;
return true;
}
// Test if the rcc output file is older than the rcc executable
- if (RccFileTime_.Older(RccExecutableTime_)) {
- if (Log().Verbose()) {
- Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
- ", because it is older than the rcc executable, from ",
- MessagePath(QrcFile_));
+ if (this->RccFileTime_.Older(this->RccExecutableTime_)) {
+ if (this->Log().Verbose()) {
+ this->Reason =
+ cmStrCat("Generating ", this->MessagePath(this->RccFileOutput_),
+ ", because it is older than the rcc executable, from ",
+ this->MessagePath(this->QrcFile_));
}
generate = true;
return true;
@@ -334,34 +348,38 @@ bool cmQtAutoRccT::TestQrcRccFiles(bool& generate)
bool cmQtAutoRccT::TestResources(bool& generate)
{
// Read resource files list
- if (Inputs_.empty()) {
+ if (this->Inputs_.empty()) {
std::string error;
- RccLister const lister(RccExecutable_, RccListOptions_);
- if (!lister.list(QrcFile_, Inputs_, error, Log().Verbose())) {
- Log().Error(
- GenT::RCC,
- cmStrCat("Listing of ", MessagePath(QrcFile_), " failed.\n", error));
+ RccLister const lister(this->RccExecutable_, this->RccListOptions_);
+ if (!lister.list(this->QrcFile_, this->Inputs_, error,
+ this->Log().Verbose())) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Listing of ",
+ this->MessagePath(this->QrcFile_),
+ " failed.\n", error));
return false;
}
}
// Check if any resource file is newer than the rcc output file
- for (std::string const& resFile : Inputs_) {
+ for (std::string const& resFile : this->Inputs_) {
// Check if the resource file exists
cmFileTime fileTime;
if (!fileTime.Load(resFile)) {
- Log().Error(GenT::RCC,
- cmStrCat("The resource file ", MessagePath(resFile),
- " listed in ", MessagePath(QrcFile_),
- " does not exist."));
+ this->Log().Error(GenT::RCC,
+ cmStrCat("The resource file ",
+ this->MessagePath(resFile), " listed in ",
+ this->MessagePath(this->QrcFile_),
+ " does not exist."));
return false;
}
// Check if the resource file is newer than the rcc output file
- if (RccFileTime_.Older(fileTime)) {
- if (Log().Verbose()) {
- Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
- ", because it is older than ", MessagePath(resFile),
- ", from ", MessagePath(QrcFile_));
+ if (this->RccFileTime_.Older(fileTime)) {
+ if (this->Log().Verbose()) {
+ this->Reason =
+ cmStrCat("Generating ", this->MessagePath(this->RccFileOutput_),
+ ", because it is older than ", this->MessagePath(resFile),
+ ", from ", this->MessagePath(this->QrcFile_));
}
generate = true;
break;
@@ -373,21 +391,23 @@ bool cmQtAutoRccT::TestResources(bool& generate)
bool cmQtAutoRccT::TestInfoFile()
{
// Test if the rcc output file is older than the info file
- if (RccFileTime_.Older(InfoFileTime())) {
- if (Log().Verbose()) {
- Log().Info(GenT::RCC,
- cmStrCat("Touching ", MessagePath(RccFileOutput_),
- " because it is older than ",
- MessagePath(InfoFile())));
+ if (this->RccFileTime_.Older(this->InfoFileTime())) {
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::RCC,
+ cmStrCat("Touching ",
+ this->MessagePath(this->RccFileOutput_),
+ " because it is older than ",
+ this->MessagePath(this->InfoFile())));
}
// Touch build file
- if (!cmSystemTools::Touch(RccFileOutput_, false)) {
- Log().Error(
- GenT::RCC,
- cmStrCat("Touching ", MessagePath(RccFileOutput_), " failed."));
+ if (!cmSystemTools::Touch(this->RccFileOutput_, false)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Touching ",
+ this->MessagePath(this->RccFileOutput_),
+ " failed."));
return false;
}
- BuildFileChanged_ = true;
+ this->BuildFileChanged_ = true;
}
return true;
@@ -396,51 +416,53 @@ bool cmQtAutoRccT::TestInfoFile()
bool cmQtAutoRccT::GenerateRcc()
{
// Make parent directory
- if (!MakeParentDirectory(RccFileOutput_)) {
- Log().Error(GenT::RCC,
- cmStrCat("Could not create parent directory of ",
- MessagePath(RccFileOutput_)));
+ if (!MakeParentDirectory(this->RccFileOutput_)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Could not create parent directory of ",
+ this->MessagePath(this->RccFileOutput_)));
return false;
}
// Compose rcc command
std::vector<std::string> cmd;
- cmd.push_back(RccExecutable_);
- cm::append(cmd, Options_);
+ cmd.push_back(this->RccExecutable_);
+ cm::append(cmd, this->Options_);
cmd.emplace_back("-o");
- cmd.push_back(RccFileOutput_);
- cmd.push_back(QrcFile_);
+ cmd.push_back(this->RccFileOutput_);
+ cmd.push_back(this->QrcFile_);
// Log reason and command
- if (Log().Verbose()) {
- Log().Info(GenT::RCC,
- cmStrCat(Reason, cmHasSuffix(Reason, '\n') ? "" : "\n",
- QuotedCommand(cmd), '\n'));
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::RCC,
+ cmStrCat(this->Reason,
+ cmHasSuffix(this->Reason, '\n') ? "" : "\n",
+ QuotedCommand(cmd), '\n'));
}
std::string rccStdOut;
std::string rccStdErr;
int retVal = 0;
bool result = cmSystemTools::RunSingleCommand(
- cmd, &rccStdOut, &rccStdErr, &retVal, AutogenBuildDir_.c_str(),
+ cmd, &rccStdOut, &rccStdErr, &retVal, this->AutogenBuildDir_.c_str(),
cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
if (!result || (retVal != 0)) {
// rcc process failed
- Log().ErrorCommand(GenT::RCC,
- cmStrCat("The rcc process failed to compile\n ",
- MessagePath(QrcFile_), "\ninto\n ",
- MessagePath(RccFileOutput_)),
- cmd, rccStdOut + rccStdErr);
- cmSystemTools::RemoveFile(RccFileOutput_);
+ this->Log().ErrorCommand(GenT::RCC,
+ cmStrCat("The rcc process failed to compile\n ",
+ this->MessagePath(this->QrcFile_),
+ "\ninto\n ",
+ this->MessagePath(this->RccFileOutput_)),
+ cmd, rccStdOut + rccStdErr);
+ cmSystemTools::RemoveFile(this->RccFileOutput_);
return false;
}
// rcc process success
// Print rcc output
if (!rccStdOut.empty()) {
- Log().Info(GenT::RCC, rccStdOut);
+ this->Log().Info(GenT::RCC, rccStdOut);
}
- BuildFileChanged_ = true;
+ this->BuildFileChanged_ = true;
return true;
}
@@ -448,47 +470,48 @@ bool cmQtAutoRccT::GenerateRcc()
bool cmQtAutoRccT::GenerateWrapper()
{
// Generate a wrapper source file on demand
- if (IsMultiConfig()) {
+ if (this->IsMultiConfig()) {
// Wrapper file content
std::string content =
cmStrCat("// This is an autogenerated configuration wrapper file.\n",
"// Changes will be overwritten.\n", "#include <",
- MultiConfigOutput(), ">\n");
+ this->MultiConfigOutput(), ">\n");
// Compare with existing file content
bool fileDiffers = true;
{
std::string oldContents;
- if (FileRead(oldContents, RccFilePublic_)) {
+ if (FileRead(oldContents, this->RccFilePublic_)) {
fileDiffers = (oldContents != content);
}
}
if (fileDiffers) {
// Write new wrapper file
- if (Log().Verbose()) {
- Log().Info(GenT::RCC,
- cmStrCat("Generating RCC wrapper file ",
- MessagePath(RccFilePublic_)));
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::RCC,
+ cmStrCat("Generating RCC wrapper file ",
+ this->MessagePath(this->RccFilePublic_)));
}
std::string error;
- if (!FileWrite(RccFilePublic_, content, &error)) {
- Log().Error(GenT::RCC,
- cmStrCat("Generating RCC wrapper file ",
- MessagePath(RccFilePublic_), " failed.\n",
- error));
+ if (!FileWrite(this->RccFilePublic_, content, &error)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Generating RCC wrapper file ",
+ this->MessagePath(this->RccFilePublic_),
+ " failed.\n", error));
return false;
}
- } else if (BuildFileChanged_) {
+ } else if (this->BuildFileChanged_) {
// Just touch the wrapper file
- if (Log().Verbose()) {
- Log().Info(
- GenT::RCC,
- cmStrCat("Touching RCC wrapper file ", MessagePath(RccFilePublic_)));
+ if (this->Log().Verbose()) {
+ this->Log().Info(GenT::RCC,
+ cmStrCat("Touching RCC wrapper file ",
+ this->MessagePath(this->RccFilePublic_)));
}
- if (!cmSystemTools::Touch(RccFilePublic_, false)) {
- Log().Error(GenT::RCC,
- cmStrCat("Touching RCC wrapper file ",
- MessagePath(RccFilePublic_), " failed."));
+ if (!cmSystemTools::Touch(this->RccFilePublic_, false)) {
+ this->Log().Error(GenT::RCC,
+ cmStrCat("Touching RCC wrapper file ",
+ this->MessagePath(this->RccFilePublic_),
+ " failed."));
return false;
}
}
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 26e93bb34..fce6e80bf 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -25,7 +25,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
, Markup(MarkupNone)
, Directive(DirectiveNone)
, CMakeDirective("^.. (cmake:)?("
- "command|variable"
+ "command|envvar|genex|variable"
")::[ \t]+([^ \t\n]+)$")
, CMakeModuleDirective("^.. cmake-module::[ \t]+([^ \t\n]+)$")
, ParsedLiteralDirective("^.. parsed-literal::[ \t]*(.*)$")
@@ -37,7 +37,8 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
, NoteDirective("^.. note::[ \t]*(.*)$")
, ModuleRST(R"(^#\[(=*)\[\.rst:$)")
, CMakeRole("(:cmake)?:("
- "command|cpack_gen|generator|variable|envvar|module|policy|"
+ "command|cpack_gen|generator|genex|"
+ "variable|envvar|module|policy|"
"prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
"prop_test|prop_tgt|"
"manual"
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index f5f9c6714..d00bbdf04 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -3,7 +3,6 @@
#include "cmRulePlaceholderExpander.h"
#include <cctype>
-#include <cstring>
#include <utility>
#include "cmOutputConverter.h"
@@ -20,11 +19,6 @@ cmRulePlaceholderExpander::cmRulePlaceholderExpander(
{
}
-cmRulePlaceholderExpander::RuleVariables::RuleVariables()
-{
- memset(this, 0, sizeof(*this));
-}
-
std::string cmRulePlaceholderExpander::ExpandRuleVariable(
cmOutputConverter* outputConverter, std::string const& variable,
const RuleVariables& replaceValues)
@@ -50,6 +44,11 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
return replaceValues.Source;
}
}
+ if (replaceValues.DynDepFile) {
+ if (variable == "DYNDEP_FILE") {
+ return replaceValues.DynDepFile;
+ }
+ }
if (replaceValues.PreprocessedSource) {
if (variable == "PREPROCESSED_SOURCE") {
return replaceValues.PreprocessedSource;
@@ -141,6 +140,11 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
return replaceValues.DependencyFile;
}
}
+ if (replaceValues.DependencyTarget) {
+ if (variable == "DEP_TARGET") {
+ return replaceValues.DependencyTarget;
+ }
+ }
if (replaceValues.Fatbinary) {
if (variable == "FATBINARY") {
return replaceValues.Fatbinary;
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index c8d107d4d..f8dc36837 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -27,45 +27,46 @@ public:
// ExpandRuleVariables
struct RuleVariables
{
- RuleVariables();
- const char* CMTargetName;
- const char* CMTargetType;
- const char* TargetPDB;
- const char* TargetCompilePDB;
- const char* TargetVersionMajor;
- const char* TargetVersionMinor;
- const char* Language;
- const char* AIXExports;
- const char* Objects;
- const char* Target;
- const char* LinkLibraries;
- const char* Source;
- const char* AssemblySource;
- const char* PreprocessedSource;
- const char* Output;
- const char* Object;
- const char* ObjectDir;
- const char* ObjectFileDir;
- const char* Flags;
- const char* ObjectsQuoted;
- const char* SONameFlag;
- const char* TargetSOName;
- const char* TargetInstallNameDir;
- const char* LinkFlags;
- const char* Manifests;
- const char* LanguageCompileFlags;
- const char* Defines;
- const char* Includes;
- const char* DependencyFile;
- const char* FilterPrefix;
- const char* SwiftLibraryName;
- const char* SwiftModule;
- const char* SwiftModuleName;
- const char* SwiftOutputFileMap;
- const char* SwiftSources;
- const char* ISPCHeader;
- const char* Fatbinary;
- const char* RegisterFile;
+ const char* CMTargetName = nullptr;
+ const char* CMTargetType = nullptr;
+ const char* TargetPDB = nullptr;
+ const char* TargetCompilePDB = nullptr;
+ const char* TargetVersionMajor = nullptr;
+ const char* TargetVersionMinor = nullptr;
+ const char* Language = nullptr;
+ const char* AIXExports = nullptr;
+ const char* Objects = nullptr;
+ const char* Target = nullptr;
+ const char* LinkLibraries = nullptr;
+ const char* Source = nullptr;
+ const char* AssemblySource = nullptr;
+ const char* PreprocessedSource = nullptr;
+ const char* DynDepFile = nullptr;
+ const char* Output = nullptr;
+ const char* Object = nullptr;
+ const char* ObjectDir = nullptr;
+ const char* ObjectFileDir = nullptr;
+ const char* Flags = nullptr;
+ const char* ObjectsQuoted = nullptr;
+ const char* SONameFlag = nullptr;
+ const char* TargetSOName = nullptr;
+ const char* TargetInstallNameDir = nullptr;
+ const char* LinkFlags = nullptr;
+ const char* Manifests = nullptr;
+ const char* LanguageCompileFlags = nullptr;
+ const char* Defines = nullptr;
+ const char* Includes = nullptr;
+ const char* DependencyFile = nullptr;
+ const char* DependencyTarget = nullptr;
+ const char* FilterPrefix = nullptr;
+ const char* SwiftLibraryName = nullptr;
+ const char* SwiftModule = nullptr;
+ const char* SwiftModuleName = nullptr;
+ const char* SwiftOutputFileMap = nullptr;
+ const char* SwiftSources = nullptr;
+ const char* ISPCHeader = nullptr;
+ const char* Fatbinary = nullptr;
+ const char* RegisterFile = nullptr;
};
// Expand rule variables in CMake of the type found in language rules
diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx
index 0781d2978..472f23469 100644
--- a/Source/cmRuntimeDependencyArchive.cxx
+++ b/Source/cmRuntimeDependencyArchive.cxx
@@ -181,13 +181,10 @@ bool cmRuntimeDependencyArchive::GetRuntimeDependencies(
return false;
}
}
- for (auto const& mod : modules) {
- if (!this->Linker->ScanDependencies(mod, cmStateEnums::MODULE_LIBRARY)) {
- return false;
- }
- }
-
- return true;
+ return std::all_of(
+ modules.begin(), modules.end(), [this](std::string const& mod) -> bool {
+ return this->Linker->ScanDependencies(mod, cmStateEnums::MODULE_LIBRARY);
+ });
}
void cmRuntimeDependencyArchive::SetError(const std::string& e)
diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx
new file mode 100644
index 000000000..e0460694e
--- /dev/null
+++ b/Source/cmScanDepFormat.cxx
@@ -0,0 +1,265 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmScanDepFormat.h"
+
+#include <cctype>
+#include <cstdio>
+
+#include <cm3p/json/reader.h>
+#include <cm3p/json/value.h>
+#include <cm3p/json/writer.h>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+static bool ParseFilename(Json::Value const& val, std::string& result)
+{
+ if (val.isString()) {
+ result = val.asString();
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+static Json::Value EncodeFilename(std::string const& path)
+{
+ std::string data;
+ data.reserve(path.size());
+
+ for (auto const& byte : path) {
+ if (std::iscntrl(byte)) {
+ // Control characters.
+ data.append("\\u");
+ char buf[5];
+ std::snprintf(buf, sizeof(buf), "%04x", byte);
+ data.append(buf);
+ } else if (byte == '"' || byte == '\\') {
+ // Special JSON characters.
+ data.push_back('\\');
+ data.push_back(byte);
+ } else {
+ // Other data.
+ data.push_back(byte);
+ }
+ }
+
+ return data;
+}
+
+#define PARSE_BLOB(val, res) \
+ do { \
+ if (!ParseFilename(val, res)) { \
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", \
+ arg_pp, ": invalid blob")); \
+ return false; \
+ } \
+ } while (0)
+
+#define PARSE_FILENAME(val, res) \
+ do { \
+ if (!ParseFilename(val, res)) { \
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", \
+ arg_pp, ": invalid filename")); \
+ return false; \
+ } \
+ \
+ if (!cmSystemTools::FileIsFullPath(res)) { \
+ res = cmStrCat(work_directory, '/', res); \
+ } \
+ } while (0)
+
+bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, cmSourceInfo* info)
+{
+ Json::Value ppio;
+ Json::Value const& ppi = ppio;
+ cmsys::ifstream ppf(arg_pp.c_str(), std::ios::in | std::ios::binary);
+ {
+ Json::Reader reader;
+ if (!reader.parse(ppf, ppio, false)) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ arg_pp,
+ reader.getFormattedErrorMessages()));
+ return false;
+ }
+ }
+
+ Json::Value const& version = ppi["version"];
+ if (version.asUInt() != 0) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ arg_pp, ": version ", version.asString()));
+ return false;
+ }
+
+ Json::Value const& rules = ppi["rules"];
+ if (rules.isArray()) {
+ if (rules.size() != 1) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ arg_pp, ": expected 1 source entry"));
+ return false;
+ }
+
+ for (auto const& rule : rules) {
+ Json::Value const& workdir = rule["work-directory"];
+ if (!workdir.isString()) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ arg_pp,
+ ": work-directory is not a string"));
+ return false;
+ }
+ std::string work_directory;
+ PARSE_BLOB(workdir, work_directory);
+
+ 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("future-compile")) {
+ Json::Value const& future_compile = rule["future-compile"];
+
+ if (future_compile.isMember("outputs")) {
+ Json::Value const& outputs = future_compile["outputs"];
+ if (outputs.isArray()) {
+ if (outputs.empty()) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
+ ": expected at least one 1 output"));
+ return false;
+ }
+
+ PARSE_FILENAME(outputs[0], info->PrimaryOutput);
+ }
+ }
+
+ 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 (future_compile.isMember("requires")) {
+ Json::Value const& reqs = future_compile["requires"];
+ if (reqs.isArray()) {
+ 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);
+ }
+
+ info->Requires.push_back(require_info);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool cmScanDepFormat_P1689_Write(std::string const& path,
+ std::string const& input,
+ cmSourceInfo const& info)
+{
+ Json::Value ddi(Json::objectValue);
+ ddi["version"] = 0;
+ ddi["revision"] = 0;
+
+ Json::Value& rules = ddi["rules"] = Json::arrayValue;
+
+ Json::Value rule(Json::objectValue);
+ rule["work-directory"] =
+ EncodeFilename(cmSystemTools::GetCurrentWorkingDirectory());
+ Json::Value& inputs = rule["inputs"] = Json::arrayValue;
+ inputs.append(EncodeFilename(input));
+
+ Json::Value& rule_outputs = rule["outputs"] = Json::arrayValue;
+ rule_outputs.append(EncodeFilename(path));
+
+ Json::Value& depends = rule["depends"] = Json::arrayValue;
+ for (auto const& include : info.Includes) {
+ depends.append(EncodeFilename(include));
+ }
+
+ 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;
+ 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 {
+ provide_obj["compiled-module-path"] =
+ EncodeFilename(provide.CompiledModulePath);
+ }
+
+ // TODO: Source file tracking. See below.
+
+ provides.append(provide_obj);
+ }
+
+ Json::Value& reqs = future_compile["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 {
+ 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).
+
+ reqs.append(require_obj);
+ }
+
+ rules.append(rule);
+
+ cmGeneratedFileStream ddif(path);
+ ddif << ddi;
+
+ return !!ddif;
+}
diff --git a/Source/cmScanDepFormat.h b/Source/cmScanDepFormat.h
new file mode 100644
index 000000000..1ad0ecf73
--- /dev/null
+++ b/Source/cmScanDepFormat.h
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <string>
+#include <vector>
+
+struct cmSourceReqInfo
+{
+ std::string LogicalName;
+ std::string CompiledModulePath;
+};
+
+struct cmSourceInfo
+{
+ std::string PrimaryOutput;
+
+ // 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);
+bool cmScanDepFormat_P1689_Write(std::string const& path,
+ std::string const& input,
+ cmSourceInfo const& info);
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index adc06792d..5ac7be968 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmScriptGenerator.h"
+#include <algorithm>
#include <utility>
#include "cmStringAlgorithms.h"
@@ -11,7 +12,6 @@ cmScriptGenerator::cmScriptGenerator(std::string config_var,
std::vector<std::string> configurations)
: RuntimeConfigVariable(std::move(config_var))
, Configurations(std::move(configurations))
- , ConfigurationName("")
, ConfigurationTypes(nullptr)
, ActionsPerConfig(false)
{
@@ -120,12 +120,10 @@ bool cmScriptGenerator::GeneratesForConfig(const std::string& config)
// This is a configuration-specific rule. Check if the config
// matches this rule.
std::string config_upper = cmSystemTools::UpperCase(config);
- for (std::string const& cfg : this->Configurations) {
- if (cmSystemTools::UpperCase(cfg) == config_upper) {
- return true;
- }
- }
- return false;
+ return std::any_of(this->Configurations.begin(), this->Configurations.end(),
+ [&config_upper](std::string const& cfg) -> bool {
+ return cmSystemTools::UpperCase(cfg) == config_upper;
+ });
}
void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
deleted file mode 100644
index 7f9740626..000000000
--- a/Source/cmServer.cxx
+++ /dev/null
@@ -1,570 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmServer.h"
-
-#include <algorithm>
-#include <cassert>
-#include <csignal>
-#include <cstdint>
-#include <iostream>
-#include <mutex>
-#include <utility>
-
-#include <cm/memory>
-#include <cm/shared_mutex>
-
-#include <cm3p/json/reader.h>
-#include <cm3p/json/writer.h>
-
-#include "cmsys/FStream.hxx"
-
-#include "cmConnection.h"
-#include "cmFileMonitor.h"
-#include "cmJsonObjectDictionary.h"
-#include "cmServerDictionary.h"
-#include "cmServerProtocol.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
-
-void on_signal(uv_signal_t* signal, int signum)
-{
- auto conn = static_cast<cmServerBase*>(signal->data);
- conn->OnSignal(signum);
-}
-
-static void on_walk_to_shutdown(uv_handle_t* handle, void* arg)
-{
- (void)arg;
- assert(uv_is_closing(handle));
- if (!uv_is_closing(handle)) {
- uv_close(handle, &cmEventBasedConnection::on_close);
- }
-}
-
-class cmServer::DebugInfo
-{
-public:
- DebugInfo()
- : StartTime(uv_hrtime())
- {
- }
-
- bool PrintStatistics = false;
-
- std::string OutputFile;
- uint64_t StartTime;
-};
-
-cmServer::cmServer(cmConnection* conn, bool supportExperimental)
- : cmServerBase(conn)
- , SupportExperimental(supportExperimental)
-{
- // Register supported protocols:
- this->RegisterProtocol(cm::make_unique<cmServerProtocol1>());
-}
-
-cmServer::~cmServer()
-{
- Close();
-}
-
-void cmServer::ProcessRequest(cmConnection* connection,
- const std::string& input)
-{
- Json::Reader reader;
- Json::Value value;
- if (!reader.parse(input, value)) {
- this->WriteParseError(connection, "Failed to parse JSON input.");
- return;
- }
-
- std::unique_ptr<DebugInfo> debug;
- Json::Value debugValue = value["debug"];
- if (!debugValue.isNull()) {
- debug = cm::make_unique<DebugInfo>();
- debug->OutputFile = debugValue["dumpToFile"].asString();
- debug->PrintStatistics = debugValue["showStats"].asBool();
- }
-
- const cmServerRequest request(this, connection, value[kTYPE_KEY].asString(),
- value[kCOOKIE_KEY].asString(), value);
-
- if (request.Type.empty()) {
- cmServerResponse response(request);
- response.SetError("No type given in request.");
- this->WriteResponse(connection, response, nullptr);
- return;
- }
-
- cmSystemTools::SetMessageCallback(
- [&request](const std::string& msg, const char* title) {
- reportMessage(msg, title, request);
- });
-
- if (this->Protocol) {
- this->Protocol->CMakeInstance()->SetProgressCallback(
- [&request](const std::string& msg, float prog) {
- reportProgress(msg, prog, request);
- });
- this->WriteResponse(connection, this->Protocol->Process(request),
- debug.get());
- } else {
- this->WriteResponse(connection, this->SetProtocolVersion(request),
- debug.get());
- }
-}
-
-void cmServer::RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol)
-{
- if (protocol->IsExperimental() && !this->SupportExperimental) {
- protocol.reset();
- return;
- }
- auto version = protocol->ProtocolVersion();
- assert(version.first >= 0);
- assert(version.second >= 0);
- auto it = std::find_if(
- this->SupportedProtocols.begin(), this->SupportedProtocols.end(),
- [version](const std::unique_ptr<cmServerProtocol>& p) {
- return p->ProtocolVersion() == version;
- });
- if (it == this->SupportedProtocols.end()) {
- this->SupportedProtocols.push_back(std::move(protocol));
- }
-}
-
-void cmServer::PrintHello(cmConnection* connection) const
-{
- Json::Value hello = Json::objectValue;
- hello[kTYPE_KEY] = "hello";
-
- Json::Value& protocolVersions = hello[kSUPPORTED_PROTOCOL_VERSIONS] =
- Json::arrayValue;
-
- for (auto const& proto : this->SupportedProtocols) {
- auto version = proto->ProtocolVersion();
- Json::Value tmp = Json::objectValue;
- tmp[kMAJOR_KEY] = version.first;
- tmp[kMINOR_KEY] = version.second;
- if (proto->IsExperimental()) {
- tmp[kIS_EXPERIMENTAL_KEY] = true;
- }
- protocolVersions.append(tmp);
- }
-
- this->WriteJsonObject(connection, hello, nullptr);
-}
-
-void cmServer::reportProgress(const std::string& msg, float progress,
- const cmServerRequest& request)
-{
- if (progress < 0.0f || progress > 1.0f) {
- request.ReportMessage(msg, "");
- } else {
- request.ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
- }
-}
-
-void cmServer::reportMessage(const std::string& msg, const char* title,
- const cmServerRequest& request)
-{
- std::string titleString;
- if (title) {
- titleString = title;
- }
- request.ReportMessage(msg, titleString);
-}
-
-cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
-{
- if (request.Type != kHANDSHAKE_TYPE) {
- return request.ReportError("Waiting for type \"" + kHANDSHAKE_TYPE +
- "\".");
- }
-
- Json::Value requestedProtocolVersion = request.Data[kPROTOCOL_VERSION_KEY];
- if (requestedProtocolVersion.isNull()) {
- return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
- "\" is required for \"" + kHANDSHAKE_TYPE +
- "\".");
- }
-
- if (!requestedProtocolVersion.isObject()) {
- return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
- "\" must be a JSON object.");
- }
-
- Json::Value majorValue = requestedProtocolVersion[kMAJOR_KEY];
- if (!majorValue.isInt()) {
- return request.ReportError("\"" + kMAJOR_KEY +
- "\" must be set and an integer.");
- }
-
- Json::Value minorValue = requestedProtocolVersion[kMINOR_KEY];
- if (!minorValue.isNull() && !minorValue.isInt()) {
- return request.ReportError("\"" + kMINOR_KEY +
- "\" must be unset or an integer.");
- }
-
- const int major = majorValue.asInt();
- const int minor = minorValue.isNull() ? -1 : minorValue.asInt();
- if (major < 0) {
- return request.ReportError("\"" + kMAJOR_KEY + "\" must be >= 0.");
- }
- if (!minorValue.isNull() && minor < 0) {
- return request.ReportError("\"" + kMINOR_KEY +
- "\" must be >= 0 when set.");
- }
-
- this->Protocol =
- cmServer::FindMatchingProtocol(this->SupportedProtocols, major, minor);
- if (!this->Protocol) {
- return request.ReportError("Protocol version not supported.");
- }
-
- std::string errorMessage;
- if (!this->Protocol->Activate(this, request, &errorMessage)) {
- this->Protocol = nullptr;
- return request.ReportError("Failed to activate protocol version: " +
- errorMessage);
- }
- return request.Reply(Json::objectValue);
-}
-
-bool cmServer::Serve(std::string* errorMessage)
-{
- if (this->SupportedProtocols.empty()) {
- *errorMessage =
- "No protocol versions defined. Maybe you need --experimental?";
- return false;
- }
- assert(!this->Protocol);
-
- return cmServerBase::Serve(errorMessage);
-}
-
-cmFileMonitor* cmServer::FileMonitor() const
-{
- return fileMonitor.get();
-}
-
-void cmServer::WriteJsonObject(const Json::Value& jsonValue,
- const DebugInfo* debug) const
-{
- cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
- for (auto& connection : this->Connections) {
- WriteJsonObject(connection.get(), jsonValue, debug);
- }
-}
-
-void cmServer::WriteJsonObject(cmConnection* connection,
- const Json::Value& jsonValue,
- const DebugInfo* debug) const
-{
- Json::FastWriter writer;
-
- auto beforeJson = uv_hrtime();
- std::string result = writer.write(jsonValue);
-
- if (debug) {
- Json::Value copy = jsonValue;
- if (debug->PrintStatistics) {
- Json::Value stats = Json::objectValue;
- auto endTime = uv_hrtime();
-
- stats["jsonSerialization"] = double(endTime - beforeJson) / 1000000.0;
- stats["totalTime"] = double(endTime - debug->StartTime) / 1000000.0;
- stats["size"] = static_cast<int>(result.size());
- if (!debug->OutputFile.empty()) {
- stats["dumpFile"] = debug->OutputFile;
- }
-
- copy["zzzDebug"] = stats;
-
- result = writer.write(copy); // Update result to include debug info
- }
-
- if (!debug->OutputFile.empty()) {
- cmsys::ofstream myfile(debug->OutputFile.c_str());
- myfile << result;
- }
- }
-
- connection->WriteData(result);
-}
-
-cmServerProtocol* cmServer::FindMatchingProtocol(
- const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major,
- int minor)
-{
- cmServerProtocol* bestMatch = nullptr;
- for (const auto& protocol : protocols) {
- auto version = protocol->ProtocolVersion();
- if (major != version.first) {
- continue;
- }
- if (minor == version.second) {
- return protocol.get();
- }
- if (!bestMatch || bestMatch->ProtocolVersion().second < version.second) {
- bestMatch = protocol.get();
- }
- }
- return minor < 0 ? bestMatch : nullptr;
-}
-
-void cmServer::WriteProgress(const cmServerRequest& request, int min,
- int current, int max,
- const std::string& message) const
-{
- assert(min <= current && current <= max);
- assert(message.length() != 0);
-
- Json::Value obj = Json::objectValue;
- obj[kTYPE_KEY] = kPROGRESS_TYPE;
- obj[kREPLY_TO_KEY] = request.Type;
- obj[kCOOKIE_KEY] = request.Cookie;
- obj[kPROGRESS_MESSAGE_KEY] = message;
- obj[kPROGRESS_MINIMUM_KEY] = min;
- obj[kPROGRESS_MAXIMUM_KEY] = max;
- obj[kPROGRESS_CURRENT_KEY] = current;
-
- this->WriteJsonObject(request.Connection, obj, nullptr);
-}
-
-void cmServer::WriteMessage(const cmServerRequest& request,
- const std::string& message,
- const std::string& title) const
-{
- if (message.empty()) {
- return;
- }
-
- Json::Value obj = Json::objectValue;
- obj[kTYPE_KEY] = kMESSAGE_TYPE;
- obj[kREPLY_TO_KEY] = request.Type;
- obj[kCOOKIE_KEY] = request.Cookie;
- obj[kMESSAGE_KEY] = message;
- if (!title.empty()) {
- obj[kTITLE_KEY] = title;
- }
-
- WriteJsonObject(request.Connection, obj, nullptr);
-}
-
-void cmServer::WriteParseError(cmConnection* connection,
- const std::string& message) const
-{
- Json::Value obj = Json::objectValue;
- obj[kTYPE_KEY] = kERROR_TYPE;
- obj[kERROR_MESSAGE_KEY] = message;
- obj[kREPLY_TO_KEY] = "";
- obj[kCOOKIE_KEY] = "";
-
- this->WriteJsonObject(connection, obj, nullptr);
-}
-
-void cmServer::WriteSignal(const std::string& name,
- const Json::Value& data) const
-{
- assert(data.isObject());
- Json::Value obj = data;
- obj[kTYPE_KEY] = kSIGNAL_TYPE;
- obj[kREPLY_TO_KEY] = "";
- obj[kCOOKIE_KEY] = "";
- obj[kNAME_KEY] = name;
-
- WriteJsonObject(obj, nullptr);
-}
-
-void cmServer::WriteResponse(cmConnection* connection,
- const cmServerResponse& response,
- const DebugInfo* debug) const
-{
- assert(response.IsComplete());
-
- Json::Value obj = response.Data();
- obj[kCOOKIE_KEY] = response.Cookie;
- obj[kTYPE_KEY] = response.IsError() ? kERROR_TYPE : kREPLY_TYPE;
- obj[kREPLY_TO_KEY] = response.Type;
- if (response.IsError()) {
- obj[kERROR_MESSAGE_KEY] = response.ErrorMessage();
- }
-
- this->WriteJsonObject(connection, obj, debug);
-}
-
-void cmServer::OnConnected(cmConnection* connection)
-{
- PrintHello(connection);
-}
-
-void cmServer::OnServeStart()
-{
- cmServerBase::OnServeStart();
- fileMonitor = std::make_shared<cmFileMonitor>(GetLoop());
-}
-
-void cmServer::StartShutDown()
-{
- if (fileMonitor) {
- fileMonitor->StopMonitoring();
- fileMonitor.reset();
- }
- cmServerBase::StartShutDown();
-}
-
-static void __start_thread(void* arg)
-{
- auto server = static_cast<cmServerBase*>(arg);
- std::string error;
- bool success = server->Serve(&error);
- if (!success || !error.empty()) {
- std::cerr << "Error during serve: " << error << std::endl;
- }
-}
-
-bool cmServerBase::StartServeThread()
-{
- ServeThreadRunning = true;
- uv_thread_create(&ServeThread, __start_thread, this);
- return true;
-}
-
-static void __shutdownThread(uv_async_t* arg)
-{
- auto server = static_cast<cmServerBase*>(arg->data);
- server->StartShutDown();
-}
-
-bool cmServerBase::Serve(std::string* errorMessage)
-{
-#ifndef NDEBUG
- uv_thread_t blank_thread_t = {};
- assert(uv_thread_equal(&blank_thread_t, &ServeThreadId));
- ServeThreadId = uv_thread_self();
-#endif
-
- errorMessage->clear();
-
- ShutdownSignal.init(Loop, __shutdownThread, this);
-
- SIGINTHandler.init(Loop, this);
- SIGHUPHandler.init(Loop, this);
-
- SIGINTHandler.start(&on_signal, SIGINT);
- SIGHUPHandler.start(&on_signal, SIGHUP);
-
- OnServeStart();
-
- {
- cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
- for (auto& connection : Connections) {
- if (!connection->OnServeStart(errorMessage)) {
- return false;
- }
- }
- }
-
- if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
- // It is important we don't ever let the event loop exit with open handles
- // at best this is a memory leak, but it can also introduce race conditions
- // which can hang the program.
- assert(false && "Event loop stopped in unclean state.");
-
- *errorMessage = "Internal Error: Event loop stopped in unclean state.";
- return false;
- }
-
- return true;
-}
-
-void cmServerBase::OnConnected(cmConnection*)
-{
-}
-
-void cmServerBase::OnServeStart()
-{
-}
-
-void cmServerBase::StartShutDown()
-{
- ShutdownSignal.reset();
- SIGINTHandler.reset();
- SIGHUPHandler.reset();
-
- {
- std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
- for (auto& connection : Connections) {
- connection->OnConnectionShuttingDown();
- }
- Connections.clear();
- }
-
- uv_walk(&Loop, on_walk_to_shutdown, nullptr);
-}
-
-bool cmServerBase::OnSignal(int signum)
-{
- (void)signum;
- StartShutDown();
- return true;
-}
-
-cmServerBase::cmServerBase(cmConnection* connection)
-{
- auto err = uv_loop_init(&Loop);
- (void)err;
- Loop.data = this;
- assert(err == 0);
-
- AddNewConnection(connection);
-}
-
-void cmServerBase::Close()
-{
- if (Loop.data) {
- if (ServeThreadRunning) {
- this->ShutdownSignal.send();
- uv_thread_join(&ServeThread);
- }
-
- uv_loop_close(&Loop);
- Loop.data = nullptr;
- }
-}
-cmServerBase::~cmServerBase()
-{
- Close();
-}
-
-void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
-{
- {
- std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
- Connections.emplace_back(ownedConnection);
- }
- ownedConnection->SetServer(this);
-}
-
-uv_loop_t* cmServerBase::GetLoop()
-{
- return &Loop;
-}
-
-void cmServerBase::OnDisconnect(cmConnection* pConnection)
-{
- auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
- return m.get() == pConnection;
- };
- {
- std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
- Connections.erase(
- std::remove_if(Connections.begin(), Connections.end(), pred),
- Connections.end());
- }
-
- if (Connections.empty()) {
- this->ShutdownSignal.send();
- }
-}
diff --git a/Source/cmServer.h b/Source/cmServer.h
deleted file mode 100644
index 954332908..000000000
--- a/Source/cmServer.h
+++ /dev/null
@@ -1,162 +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 <memory>
-#include <string>
-#include <vector>
-
-#include <cm/shared_mutex>
-
-#include <cm3p/json/value.h>
-#include <cm3p/uv.h>
-
-#include "cmUVHandlePtr.h"
-
-class cmConnection;
-class cmFileMonitor;
-class cmServerProtocol;
-class cmServerRequest;
-class cmServerResponse;
-
-/***
- * This essentially hold and manages a libuv event queue and responds to
- * messages
- * on any of its connections.
- */
-class cmServerBase
-{
-public:
- cmServerBase(cmConnection* connection);
- virtual ~cmServerBase();
-
- virtual void AddNewConnection(cmConnection* ownedConnection);
-
- /***
- * The main override responsible for tailoring behavior towards
- * whatever the given server is supposed to do
- *
- * This should almost always be called by the given connections
- * directly.
- *
- * @param connection The connection the request was received on
- * @param request The actual request
- */
- virtual void ProcessRequest(cmConnection* connection,
- const std::string& request) = 0;
- virtual void OnConnected(cmConnection* connection);
-
- /***
- * Start a dedicated thread. If this is used to start the server, it will
- * join on the
- * servers dtor.
- */
- virtual bool StartServeThread();
- virtual bool Serve(std::string* errorMessage);
-
- virtual void OnServeStart();
- virtual void StartShutDown();
-
- virtual bool OnSignal(int signum);
- uv_loop_t* GetLoop();
- void Close();
- void OnDisconnect(cmConnection* pConnection);
-
-protected:
- mutable cm::shared_mutex ConnectionsMutex;
- std::vector<std::unique_ptr<cmConnection>> Connections;
-
- bool ServeThreadRunning = false;
- uv_thread_t ServeThread;
- cm::uv_async_ptr ShutdownSignal;
-#ifndef NDEBUG
-public:
- // When the server starts it will mark down it's current thread ID,
- // which is useful in other contexts to just assert that operations
- // are performed on that same thread.
- uv_thread_t ServeThreadId = {};
-
-protected:
-#endif
-
- uv_loop_t Loop;
-
- cm::uv_signal_ptr SIGINTHandler;
- cm::uv_signal_ptr SIGHUPHandler;
-};
-
-class cmServer : public cmServerBase
-{
-public:
- class DebugInfo;
-
- cmServer(cmConnection* conn, bool supportExperimental);
- ~cmServer() override;
-
- cmServer(cmServer const&) = delete;
- cmServer& operator=(cmServer const&) = delete;
-
- bool Serve(std::string* errorMessage) override;
-
- cmFileMonitor* FileMonitor() const;
-
-private:
- void RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol);
-
- // Callbacks from cmServerConnection:
-
- void ProcessRequest(cmConnection* connection,
- const std::string& request) override;
- std::shared_ptr<cmFileMonitor> fileMonitor;
-
-public:
- void OnServeStart() override;
-
- void StartShutDown() override;
-
-public:
- void OnConnected(cmConnection* connection) override;
-
-private:
- static void reportProgress(const std::string& msg, float progress,
- const cmServerRequest& request);
- static void reportMessage(const std::string& msg, const char* title,
- const cmServerRequest& request);
-
- // Handle requests:
- cmServerResponse SetProtocolVersion(const cmServerRequest& request);
-
- void PrintHello(cmConnection* connection) const;
-
- // Write responses:
- void WriteProgress(const cmServerRequest& request, int min, int current,
- int max, const std::string& message) const;
- void WriteMessage(const cmServerRequest& request, const std::string& message,
- const std::string& title) const;
- void WriteResponse(cmConnection* connection,
- const cmServerResponse& response,
- const DebugInfo* debug) const;
- void WriteParseError(cmConnection* connection,
- const std::string& message) const;
- void WriteSignal(const std::string& name, const Json::Value& obj) const;
-
- void WriteJsonObject(Json::Value const& jsonValue,
- const DebugInfo* debug) const;
-
- void WriteJsonObject(cmConnection* connection, Json::Value const& jsonValue,
- const DebugInfo* debug) const;
-
- static cmServerProtocol* FindMatchingProtocol(
- const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major,
- int minor);
-
- const bool SupportExperimental;
-
- cmServerProtocol* Protocol = nullptr;
- std::vector<std::unique_ptr<cmServerProtocol>> SupportedProtocols;
-
- friend class cmServerProtocol;
- friend class cmServerRequest;
-};
diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx
deleted file mode 100644
index b4f41a09e..000000000
--- a/Source/cmServerConnection.cxx
+++ /dev/null
@@ -1,165 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmConfigure.h"
-
-#include "cmServerConnection.h"
-
-#include <cm3p/uv.h>
-
-#include "cmServer.h"
-#include "cmServerDictionary.h"
-
-#ifdef _WIN32
-# include "io.h"
-#else
-# include <unistd.h>
-#endif
-#include <cassert>
-#include <utility>
-
-cmStdIoConnection::cmStdIoConnection(
- cmConnectionBufferStrategy* bufferStrategy)
- : cmEventBasedConnection(bufferStrategy)
-{
-}
-
-cm::uv_stream_ptr cmStdIoConnection::SetupStream(int file_id)
-{
- switch (uv_guess_handle(file_id)) {
- case UV_TTY: {
- cm::uv_tty_ptr tty;
- tty.init(*this->Server->GetLoop(), file_id, file_id == 0,
- static_cast<cmEventBasedConnection*>(this));
- uv_tty_set_mode(tty, UV_TTY_MODE_NORMAL);
- return { std::move(tty) };
- }
- case UV_FILE:
- if (file_id == 0) {
- return nullptr;
- }
- // Intentional fallthrough; stdin can _not_ be treated as a named
- // pipe, however stdout can be.
- CM_FALLTHROUGH;
- case UV_NAMED_PIPE: {
- cm::uv_pipe_ptr pipe;
- pipe.init(*this->Server->GetLoop(), 0,
- static_cast<cmEventBasedConnection*>(this));
- uv_pipe_open(pipe, file_id);
- return { std::move(pipe) };
- }
- default:
- assert(false && "Unable to determine stream type");
- return nullptr;
- }
-}
-
-void cmStdIoConnection::SetServer(cmServerBase* s)
-{
- cmConnection::SetServer(s);
- if (!s) {
- return;
- }
-
- this->ReadStream = SetupStream(0);
- this->WriteStream = SetupStream(1);
-}
-
-void shutdown_connection(uv_prepare_t* prepare)
-{
- cmStdIoConnection* connection =
- static_cast<cmStdIoConnection*>(prepare->data);
-
- if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(prepare))) {
- uv_close(reinterpret_cast<uv_handle_t*>(prepare),
- &cmEventBasedConnection::on_close_delete<uv_prepare_t>);
- }
- connection->OnDisconnect(0);
-}
-
-bool cmStdIoConnection::OnServeStart(std::string* pString)
-{
- Server->OnConnected(this);
- if (this->ReadStream.get()) {
- uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
- } else if (uv_guess_handle(0) == UV_FILE) {
- char buffer[1024];
- while (auto len = read(0, buffer, sizeof(buffer))) {
- ReadData(std::string(buffer, buffer + len));
- }
-
- // We can't start the disconnect from here, add a prepare hook to do that
- // for us
- auto prepare = new uv_prepare_t();
- prepare->data = this;
- uv_prepare_init(Server->GetLoop(), prepare);
- uv_prepare_start(prepare, shutdown_connection);
- }
- return cmConnection::OnServeStart(pString);
-}
-
-bool cmStdIoConnection::OnConnectionShuttingDown()
-{
- if (ReadStream.get()) {
- uv_read_stop(ReadStream);
- ReadStream->data = nullptr;
- }
-
- this->ReadStream.reset();
-
- cmEventBasedConnection::OnConnectionShuttingDown();
-
- return true;
-}
-
-cmServerPipeConnection::cmServerPipeConnection(const std::string& name)
- : cmPipeConnection(name, new cmServerBufferStrategy)
-{
-}
-
-cmServerStdIoConnection::cmServerStdIoConnection()
- : cmStdIoConnection(new cmServerBufferStrategy)
-{
-}
-
-cmConnectionBufferStrategy::~cmConnectionBufferStrategy() = default;
-
-void cmConnectionBufferStrategy::clear()
-{
-}
-
-std::string cmServerBufferStrategy::BufferOutMessage(
- const std::string& rawBuffer) const
-{
- return std::string("\n") + kSTART_MAGIC + std::string("\n") + rawBuffer +
- kEND_MAGIC + std::string("\n");
-}
-
-std::string cmServerBufferStrategy::BufferMessage(std::string& RawReadBuffer)
-{
- for (;;) {
- auto needle = RawReadBuffer.find('\n');
-
- if (needle == std::string::npos) {
- return "";
- }
- std::string line = RawReadBuffer.substr(0, needle);
- const auto ls = line.size();
- if (ls > 1 && line.at(ls - 1) == '\r') {
- line.erase(ls - 1, 1);
- }
- RawReadBuffer.erase(RawReadBuffer.begin(),
- RawReadBuffer.begin() + static_cast<long>(needle) + 1);
- if (line == kSTART_MAGIC) {
- RequestBuffer.clear();
- continue;
- }
- if (line == kEND_MAGIC) {
- std::string rtn;
- rtn.swap(this->RequestBuffer);
- return rtn;
- }
-
- this->RequestBuffer += line;
- this->RequestBuffer += "\n";
- }
-}
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
deleted file mode 100644
index a70edb4b5..000000000
--- a/Source/cmServerConnection.h
+++ /dev/null
@@ -1,67 +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>
-
-#include "cmConnection.h"
-#include "cmPipeConnection.h"
-#include "cmUVHandlePtr.h"
-
-class cmServerBase;
-
-/***
- * This connection buffer strategy accepts messages in the form of
- * [== "CMake Server" ==[
-{
- ... some JSON message ...
-}
-]== "CMake Server" ==]
- * and only passes on the core json; it discards the envelope.
- */
-class cmServerBufferStrategy : public cmConnectionBufferStrategy
-{
-public:
- std::string BufferMessage(std::string& rawBuffer) override;
- std::string BufferOutMessage(const std::string& rawBuffer) const override;
-
-private:
- std::string RequestBuffer;
-};
-
-/***
- * Generic connection over std io interfaces -- tty
- */
-class cmStdIoConnection : public cmEventBasedConnection
-{
-public:
- cmStdIoConnection(cmConnectionBufferStrategy* bufferStrategy);
-
- void SetServer(cmServerBase* s) override;
-
- bool OnConnectionShuttingDown() override;
-
- bool OnServeStart(std::string* pString) override;
-
-private:
- cm::uv_stream_ptr SetupStream(int file_id);
- cm::uv_stream_ptr ReadStream;
-};
-
-/***
- * These specific connections use the cmake server
- * buffering strategy.
- */
-class cmServerStdIoConnection : public cmStdIoConnection
-{
-public:
- cmServerStdIoConnection();
-};
-
-class cmServerPipeConnection : public cmPipeConnection
-{
-public:
- cmServerPipeConnection(const std::string& name);
-};
diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h
deleted file mode 100644
index 961e4b7ea..000000000
--- a/Source/cmServerDictionary.h
+++ /dev/null
@@ -1,67 +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 <string>
-
-// Vocabulary:
-
-static const std::string kDIRTY_SIGNAL = "dirty";
-static const std::string kFILE_CHANGE_SIGNAL = "fileChange";
-
-static const std::string kCACHE_TYPE = "cache";
-static const std::string kCMAKE_INPUTS_TYPE = "cmakeInputs";
-static const std::string kCODE_MODEL_TYPE = "codemodel";
-static const std::string kCOMPUTE_TYPE = "compute";
-static const std::string kCONFIGURE_TYPE = "configure";
-static const std::string kERROR_TYPE = "error";
-static const std::string kFILESYSTEM_WATCHERS_TYPE = "fileSystemWatchers";
-static const std::string kGLOBAL_SETTINGS_TYPE = "globalSettings";
-static const std::string kHANDSHAKE_TYPE = "handshake";
-static const std::string kMESSAGE_TYPE = "message";
-static const std::string kPROGRESS_TYPE = "progress";
-static const std::string kREPLY_TYPE = "reply";
-static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings";
-static const std::string kSIGNAL_TYPE = "signal";
-static const std::string kCTEST_INFO_TYPE = "ctestInfo";
-
-static const std::string kBUILD_FILES_KEY = "buildFiles";
-static const std::string kCACHE_ARGUMENTS_KEY = "cacheArguments";
-static const std::string kCACHE_KEY = "cache";
-static const std::string kCAPABILITIES_KEY = "capabilities";
-static const std::string kCHECK_SYSTEM_VARS_KEY = "checkSystemVars";
-static const std::string kCMAKE_ROOT_DIRECTORY_KEY = "cmakeRootDirectory";
-static const std::string kCOOKIE_KEY = "cookie";
-static const std::string kDEBUG_OUTPUT_KEY = "debugOutput";
-static const std::string kERROR_MESSAGE_KEY = "errorMessage";
-static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator";
-static const std::string kGENERATOR_KEY = "generator";
-static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental";
-static const std::string kKEYS_KEY = "keys";
-static const std::string kMAJOR_KEY = "major";
-static const std::string kMESSAGE_KEY = "message";
-static const std::string kMINOR_KEY = "minor";
-static const std::string kPLATFORM_KEY = "platform";
-static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent";
-static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum";
-static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage";
-static const std::string kPROGRESS_MINIMUM_KEY = "progressMinimum";
-static const std::string kPROTOCOL_VERSION_KEY = "protocolVersion";
-static const std::string kREPLY_TO_KEY = "inReplyTo";
-static const std::string kSUPPORTED_PROTOCOL_VERSIONS =
- "supportedProtocolVersions";
-static const std::string kTITLE_KEY = "title";
-static const std::string kTOOLSET_KEY = "toolset";
-static const std::string kTRACE_EXPAND_KEY = "traceExpand";
-static const std::string kTRACE_KEY = "trace";
-static const std::string kWARN_UNINITIALIZED_KEY = "warnUninitialized";
-static const std::string kWARN_UNUSED_CLI_KEY = "warnUnusedCli";
-static const std::string kWARN_UNUSED_KEY = "warnUnused";
-static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
-static const std::string kWATCHED_FILES_KEY = "watchedFiles";
-
-static const std::string kSTART_MAGIC = "[== \"CMake Server\" ==[";
-static const std::string kEND_MAGIC = "]== \"CMake Server\" ==]";
-
-static const std::string kRENAME_PROPERTY_VALUE = "rename";
-static const std::string kCHANGE_PROPERTY_VALUE = "change";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
deleted file mode 100644
index e586fd9d8..000000000
--- a/Source/cmServerProtocol.cxx
+++ /dev/null
@@ -1,760 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmServerProtocol.h"
-
-#include <algorithm>
-#include <cassert>
-#include <functional>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <cm/memory>
-#include <cmext/algorithm>
-
-#include <cm3p/uv.h>
-
-#include "cmExternalMakefileProjectGenerator.h"
-#include "cmFileMonitor.h"
-#include "cmGlobalGenerator.h"
-#include "cmJsonObjectDictionary.h"
-#include "cmJsonObjects.h"
-#include "cmMessageType.h"
-#include "cmProperty.h"
-#include "cmServer.h"
-#include "cmServerDictionary.h"
-#include "cmState.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
-
-// Get rid of some windows macros:
-#undef max
-
-namespace {
-
-std::vector<std::string> toStringList(const Json::Value& in)
-{
- std::vector<std::string> result;
- for (auto const& it : in) {
- result.push_back(it.asString());
- }
- return result;
-}
-
-} // namespace
-
-cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection,
- std::string t, std::string c, Json::Value d)
- : Type(std::move(t))
- , Cookie(std::move(c))
- , Data(std::move(d))
- , Connection(connection)
- , m_Server(server)
-{
-}
-
-void cmServerRequest::ReportProgress(int min, int current, int max,
- const std::string& message) const
-{
- this->m_Server->WriteProgress(*this, min, current, max, message);
-}
-
-void cmServerRequest::ReportMessage(const std::string& message,
- const std::string& title) const
-{
- m_Server->WriteMessage(*this, message, title);
-}
-
-cmServerResponse cmServerRequest::Reply(const Json::Value& data) const
-{
- cmServerResponse response(*this);
- response.SetData(data);
- return response;
-}
-
-cmServerResponse cmServerRequest::ReportError(const std::string& message) const
-{
- cmServerResponse response(*this);
- response.SetError(message);
- return response;
-}
-
-cmServerResponse::cmServerResponse(const cmServerRequest& request)
- : Type(request.Type)
- , Cookie(request.Cookie)
-{
-}
-
-void cmServerResponse::SetData(const Json::Value& data)
-{
- assert(this->m_Payload == PAYLOAD_UNKNOWN);
- if (!data[kCOOKIE_KEY].isNull() || !data[kTYPE_KEY].isNull()) {
- this->SetError("Response contains cookie or type field.");
- return;
- }
- this->m_Payload = PAYLOAD_DATA;
- this->m_Data = data;
-}
-
-void cmServerResponse::SetError(const std::string& message)
-{
- assert(this->m_Payload == PAYLOAD_UNKNOWN);
- this->m_Payload = PAYLOAD_ERROR;
- this->m_ErrorMessage = message;
-}
-
-bool cmServerResponse::IsComplete() const
-{
- return this->m_Payload != PAYLOAD_UNKNOWN;
-}
-
-bool cmServerResponse::IsError() const
-{
- assert(this->m_Payload != PAYLOAD_UNKNOWN);
- return this->m_Payload == PAYLOAD_ERROR;
-}
-
-std::string cmServerResponse::ErrorMessage() const
-{
- if (this->m_Payload == PAYLOAD_ERROR) {
- return this->m_ErrorMessage;
- }
- return std::string();
-}
-
-Json::Value cmServerResponse::Data() const
-{
- assert(this->m_Payload != PAYLOAD_UNKNOWN);
- return this->m_Data;
-}
-
-bool cmServerProtocol::Activate(cmServer* server,
- const cmServerRequest& request,
- std::string* errorMessage)
-{
- assert(server);
- this->m_Server = server;
- this->m_CMakeInstance =
- cm::make_unique<cmake>(cmake::RoleProject, cmState::Project);
- this->m_WarnUnused = false;
- const bool result = this->DoActivate(request, errorMessage);
- if (!result) {
- this->m_CMakeInstance = nullptr;
- }
- return result;
-}
-
-cmFileMonitor* cmServerProtocol::FileMonitor() const
-{
- return this->m_Server ? this->m_Server->FileMonitor() : nullptr;
-}
-
-void cmServerProtocol::SendSignal(const std::string& name,
- const Json::Value& data) const
-{
- if (this->m_Server) {
- this->m_Server->WriteSignal(name, data);
- }
-}
-
-cmake* cmServerProtocol::CMakeInstance() const
-{
- return this->m_CMakeInstance.get();
-}
-
-bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
- std::string* /*errorMessage*/)
-{
- return true;
-}
-
-std::pair<int, int> cmServerProtocol1::ProtocolVersion() const
-{
- return { 1, 2 };
-}
-
-static void setErrorMessage(std::string* errorMessage, const std::string& text)
-{
- if (errorMessage) {
- *errorMessage = text;
- }
-}
-
-static bool getOrTestHomeDirectory(cmState* state, std::string& value,
- std::string* errorMessage)
-{
- const std::string cachedValue =
- *state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
- if (value.empty()) {
- value = cachedValue;
- return true;
- }
- const std::string suffix = "/CMakeLists.txt";
- const std::string cachedValueCML = cachedValue + suffix;
- const std::string valueCML = value + suffix;
- if (!cmSystemTools::SameFile(valueCML, cachedValueCML)) {
- setErrorMessage(errorMessage,
- std::string("\"CMAKE_HOME_DIRECTORY\" is set but "
- "incompatible with configured "
- "source directory value."));
- return false;
- }
- return true;
-}
-
-static bool getOrTestValue(cmState* state, const std::string& key,
- std::string& value,
- const std::string& keyDescription,
- std::string* errorMessage)
-{
- const std::string cachedValue = state->GetSafeCacheEntryValue(key);
- if (value.empty()) {
- value = cachedValue;
- }
- if (!cachedValue.empty() && cachedValue != value) {
- setErrorMessage(errorMessage,
- std::string("\"") + key +
- "\" is set but incompatible with configured " +
- keyDescription + " value.");
- return false;
- }
- return true;
-}
-
-bool cmServerProtocol1::DoActivate(const cmServerRequest& request,
- std::string* errorMessage)
-{
- std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString();
- std::string buildDirectory = request.Data[kBUILD_DIRECTORY_KEY].asString();
- std::string generator = request.Data[kGENERATOR_KEY].asString();
- std::string extraGenerator = request.Data[kEXTRA_GENERATOR_KEY].asString();
- std::string toolset = request.Data[kTOOLSET_KEY].asString();
- std::string platform = request.Data[kPLATFORM_KEY].asString();
-
- // normalize source and build directory
- if (!sourceDirectory.empty()) {
- sourceDirectory = cmSystemTools::CollapseFullPath(sourceDirectory);
- cmSystemTools::ConvertToUnixSlashes(sourceDirectory);
- }
- if (!buildDirectory.empty()) {
- buildDirectory = cmSystemTools::CollapseFullPath(buildDirectory);
- cmSystemTools::ConvertToUnixSlashes(buildDirectory);
- }
-
- if (buildDirectory.empty()) {
- setErrorMessage(errorMessage,
- std::string("\"") + kBUILD_DIRECTORY_KEY +
- "\" is missing.");
- return false;
- }
-
- cmake* cm = CMakeInstance();
- if (cmSystemTools::PathExists(buildDirectory)) {
- if (!cmSystemTools::FileIsDirectory(buildDirectory)) {
- setErrorMessage(errorMessage,
- std::string("\"") + kBUILD_DIRECTORY_KEY +
- "\" exists but is not a directory.");
- return false;
- }
-
- const std::string cachePath = cmake::FindCacheFile(buildDirectory);
- if (cm->LoadCache(cachePath)) {
- cmState* state = cm->GetState();
-
- // Check generator:
- if (!getOrTestValue(state, "CMAKE_GENERATOR", generator, "generator",
- errorMessage)) {
- return false;
- }
-
- // check extra generator:
- if (!getOrTestValue(state, "CMAKE_EXTRA_GENERATOR", extraGenerator,
- "extra generator", errorMessage)) {
- return false;
- }
-
- // check sourcedir:
- if (!getOrTestHomeDirectory(state, sourceDirectory, errorMessage)) {
- return false;
- }
-
- // check toolset:
- if (!getOrTestValue(state, "CMAKE_GENERATOR_TOOLSET", toolset, "toolset",
- errorMessage)) {
- return false;
- }
-
- // check platform:
- if (!getOrTestValue(state, "CMAKE_GENERATOR_PLATFORM", platform,
- "platform", errorMessage)) {
- return false;
- }
- }
- }
-
- if (sourceDirectory.empty()) {
- setErrorMessage(errorMessage,
- std::string("\"") + kSOURCE_DIRECTORY_KEY +
- "\" is unset but required.");
- return false;
- }
- if (!cmSystemTools::FileIsDirectory(sourceDirectory)) {
- setErrorMessage(errorMessage,
- std::string("\"") + kSOURCE_DIRECTORY_KEY +
- "\" is not a directory.");
- return false;
- }
- if (generator.empty()) {
- setErrorMessage(errorMessage,
- std::string("\"") + kGENERATOR_KEY +
- "\" is unset but required.");
- return false;
- }
-
- std::vector<cmake::GeneratorInfo> generators;
- cm->GetRegisteredGenerators(generators);
- auto baseIt = std::find_if(generators.begin(), generators.end(),
- [&generator](const cmake::GeneratorInfo& info) {
- return info.name == generator;
- });
- if (baseIt == generators.end()) {
- setErrorMessage(errorMessage,
- std::string("Generator \"") + generator +
- "\" not supported.");
- return false;
- }
- auto extraIt = std::find_if(
- generators.begin(), generators.end(),
- [&generator, &extraGenerator](const cmake::GeneratorInfo& info) {
- return info.baseName == generator && info.extraName == extraGenerator;
- });
- if (extraIt == generators.end()) {
- setErrorMessage(errorMessage,
- std::string("The combination of generator \"" + generator +
- "\" and extra generator \"" + extraGenerator +
- "\" is not supported."));
- return false;
- }
- if (!extraIt->supportsToolset && !toolset.empty()) {
- setErrorMessage(errorMessage,
- std::string("Toolset was provided but is not supported by "
- "the requested generator."));
- return false;
- }
- if (!extraIt->supportsPlatform && !platform.empty()) {
- setErrorMessage(errorMessage,
- std::string("Platform was provided but is not supported "
- "by the requested generator."));
- return false;
- }
-
- this->GeneratorInfo =
- GeneratorInformation(generator, extraGenerator, toolset, platform,
- sourceDirectory, buildDirectory);
-
- this->m_State = STATE_ACTIVE;
- return true;
-}
-
-void cmServerProtocol1::HandleCMakeFileChanges(const std::string& path,
- int event, int status)
-{
- assert(status == 0);
- static_cast<void>(status);
-
- if (!m_isDirty) {
- m_isDirty = true;
- SendSignal(kDIRTY_SIGNAL, Json::objectValue);
- }
- Json::Value obj = Json::objectValue;
- obj[kPATH_KEY] = path;
- Json::Value properties = Json::arrayValue;
- if (event & UV_RENAME) {
- properties.append(kRENAME_PROPERTY_VALUE);
- }
- if (event & UV_CHANGE) {
- properties.append(kCHANGE_PROPERTY_VALUE);
- }
-
- obj[kPROPERTIES_KEY] = properties;
- SendSignal(kFILE_CHANGE_SIGNAL, obj);
-}
-
-cmServerResponse cmServerProtocol1::Process(const cmServerRequest& request)
-{
- assert(this->m_State >= STATE_ACTIVE);
-
- if (request.Type == kCACHE_TYPE) {
- return this->ProcessCache(request);
- }
- if (request.Type == kCMAKE_INPUTS_TYPE) {
- return this->ProcessCMakeInputs(request);
- }
- if (request.Type == kCODE_MODEL_TYPE) {
- return this->ProcessCodeModel(request);
- }
- if (request.Type == kCOMPUTE_TYPE) {
- return this->ProcessCompute(request);
- }
- if (request.Type == kCONFIGURE_TYPE) {
- return this->ProcessConfigure(request);
- }
- if (request.Type == kFILESYSTEM_WATCHERS_TYPE) {
- return this->ProcessFileSystemWatchers(request);
- }
- if (request.Type == kGLOBAL_SETTINGS_TYPE) {
- return this->ProcessGlobalSettings(request);
- }
- if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) {
- return this->ProcessSetGlobalSettings(request);
- }
- if (request.Type == kCTEST_INFO_TYPE) {
- return this->ProcessCTests(request);
- }
-
- return request.ReportError("Unknown command!");
-}
-
-bool cmServerProtocol1::IsExperimental() const
-{
- return true;
-}
-
-cmServerResponse cmServerProtocol1::ProcessCache(
- const cmServerRequest& request)
-{
- cmState* state = this->CMakeInstance()->GetState();
-
- Json::Value result = Json::objectValue;
-
- std::vector<std::string> allKeys = state->GetCacheEntryKeys();
-
- Json::Value list = Json::arrayValue;
- std::vector<std::string> keys = toStringList(request.Data[kKEYS_KEY]);
- if (keys.empty()) {
- keys = allKeys;
- } else {
- for (auto const& i : keys) {
- if (!cm::contains(allKeys, i)) {
- return request.ReportError("Key \"" + i + "\" not found in cache.");
- }
- }
- }
- std::sort(keys.begin(), keys.end());
- for (auto const& key : keys) {
- Json::Value entry = Json::objectValue;
- entry[kKEY_KEY] = key;
- entry[kTYPE_KEY] =
- cmState::CacheEntryTypeToString(state->GetCacheEntryType(key));
- entry[kVALUE_KEY] = *state->GetCacheEntryValue(key);
-
- Json::Value props = Json::objectValue;
- bool haveProperties = false;
- for (auto const& prop : state->GetCacheEntryPropertyList(key)) {
- haveProperties = true;
- props[prop] = *state->GetCacheEntryProperty(key, prop);
- }
- if (haveProperties) {
- entry[kPROPERTIES_KEY] = props;
- }
-
- list.append(entry);
- }
-
- result[kCACHE_KEY] = list;
- return request.Reply(result);
-}
-
-cmServerResponse cmServerProtocol1::ProcessCMakeInputs(
- const cmServerRequest& request)
-{
- if (this->m_State < STATE_CONFIGURED) {
- return request.ReportError("This instance was not yet configured.");
- }
-
- const cmake* cm = this->CMakeInstance();
- const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot();
- const std::string& sourceDir = cm->GetHomeDirectory();
-
- Json::Value result = Json::objectValue;
- result[kSOURCE_DIRECTORY_KEY] = sourceDir;
- result[kCMAKE_ROOT_DIRECTORY_KEY] = cmakeRootDir;
- result[kBUILD_FILES_KEY] = cmDumpCMakeInputs(cm);
- return request.Reply(result);
-}
-
-cmServerResponse cmServerProtocol1::ProcessCodeModel(
- const cmServerRequest& request)
-{
- if (this->m_State != STATE_COMPUTED) {
- return request.ReportError("No build system was generated yet.");
- }
-
- return request.Reply(cmDumpCodeModel(this->CMakeInstance()));
-}
-
-cmServerResponse cmServerProtocol1::ProcessCompute(
- const cmServerRequest& request)
-{
- if (this->m_State > STATE_CONFIGURED) {
- return request.ReportError("This build system was already generated.");
- }
- if (this->m_State < STATE_CONFIGURED) {
- return request.ReportError("This project was not configured yet.");
- }
-
- cmake* cm = this->CMakeInstance();
- int ret = cm->Generate();
-
- if (ret < 0) {
- return request.ReportError("Failed to compute build system.");
- }
- m_State = STATE_COMPUTED;
- return request.Reply(Json::Value());
-}
-
-cmServerResponse cmServerProtocol1::ProcessConfigure(
- const cmServerRequest& request)
-{
- if (this->m_State == STATE_INACTIVE) {
- return request.ReportError("This instance is inactive.");
- }
-
- FileMonitor()->StopMonitoring();
-
- std::string errorMessage;
- cmake* cm = this->CMakeInstance();
- this->GeneratorInfo.SetupGenerator(cm, &errorMessage);
- if (!errorMessage.empty()) {
- return request.ReportError(errorMessage);
- }
-
- // Make sure the types of cacheArguments matches (if given):
- std::vector<std::string> cacheArgs = { "unused" };
- bool cacheArgumentsError = false;
- const Json::Value passedArgs = request.Data[kCACHE_ARGUMENTS_KEY];
- if (!passedArgs.isNull()) {
- if (passedArgs.isString()) {
- cacheArgs.push_back(passedArgs.asString());
- } else if (passedArgs.isArray()) {
- for (auto const& arg : passedArgs) {
- if (!arg.isString()) {
- cacheArgumentsError = true;
- break;
- }
- cacheArgs.push_back(arg.asString());
- }
- } else {
- cacheArgumentsError = true;
- }
- }
- if (cacheArgumentsError) {
- request.ReportError(
- "cacheArguments must be unset, a string or an array of strings.");
- }
-
- std::string sourceDir = cm->GetHomeDirectory();
- const std::string buildDir = cm->GetHomeOutputDirectory();
-
- cmGlobalGenerator* gg = cm->GetGlobalGenerator();
-
- if (buildDir.empty()) {
- return request.ReportError("No build directory set via Handshake.");
- }
-
- if (cm->LoadCache(buildDir)) {
- // build directory has been set up before
- cmProp cachedSourceDir =
- cm->GetState()->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
- if (!cachedSourceDir) {
- return request.ReportError("No CMAKE_HOME_DIRECTORY found in cache.");
- }
- if (sourceDir.empty()) {
- sourceDir = *cachedSourceDir;
- cm->SetHomeDirectory(sourceDir);
- }
-
- cmProp cachedGenerator =
- cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR");
- if (cachedGenerator) {
- if (gg && gg->GetName() != *cachedGenerator) {
- return request.ReportError("Configured generator does not match with "
- "CMAKE_GENERATOR found in cache.");
- }
- }
- } else {
- // build directory has not been set up before
- if (sourceDir.empty()) {
- return request.ReportError("No sourceDirectory set via "
- "setGlobalSettings and no cache found in "
- "buildDirectory.");
- }
- }
-
- cmSystemTools::ResetErrorOccuredFlag(); // Reset error state
-
- if (cm->AddCMakePaths() != 1) {
- return request.ReportError("Failed to set CMake paths.");
- }
-
- if (!cm->SetCacheArgs(cacheArgs)) {
- return request.ReportError("cacheArguments could not be set.");
- }
-
- int ret = cm->Configure();
- cm->IssueMessage(
- MessageType::DEPRECATION_WARNING,
- "The 'cmake-server(7)' is deprecated. "
- "Please port clients to use the 'cmake-file-api(7)' instead.");
- if (ret < 0) {
- return request.ReportError("Configuration failed.");
- }
-
- std::vector<std::string> toWatchList;
- cmGetCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList,
- nullptr);
-
- FileMonitor()->MonitorPaths(toWatchList,
- [this](const std::string& p, int e, int s) {
- this->HandleCMakeFileChanges(p, e, s);
- });
-
- m_State = STATE_CONFIGURED;
- m_isDirty = false;
- return request.Reply(Json::Value());
-}
-
-cmServerResponse cmServerProtocol1::ProcessGlobalSettings(
- const cmServerRequest& request)
-{
- cmake* cm = this->CMakeInstance();
- Json::Value obj = Json::objectValue;
-
- // Capabilities information:
- obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson();
-
- obj[kDEBUG_OUTPUT_KEY] = cm->GetDebugOutput();
- obj[kTRACE_KEY] = cm->GetTrace();
- obj[kTRACE_EXPAND_KEY] = cm->GetTraceExpand();
- obj[kWARN_UNINITIALIZED_KEY] = cm->GetWarnUninitialized();
- obj[kWARN_UNUSED_KEY] = m_WarnUnused;
- obj[kWARN_UNUSED_CLI_KEY] = cm->GetWarnUnusedCli();
- obj[kCHECK_SYSTEM_VARS_KEY] = cm->GetCheckSystemVars();
-
- obj[kSOURCE_DIRECTORY_KEY] = this->GeneratorInfo.SourceDirectory;
- obj[kBUILD_DIRECTORY_KEY] = this->GeneratorInfo.BuildDirectory;
-
- // Currently used generator:
- obj[kGENERATOR_KEY] = this->GeneratorInfo.GeneratorName;
- obj[kEXTRA_GENERATOR_KEY] = this->GeneratorInfo.ExtraGeneratorName;
-
- return request.Reply(obj);
-}
-
-static void setBool(const cmServerRequest& request, const std::string& key,
- std::function<void(bool)> const& setter)
-{
- if (request.Data[key].isNull()) {
- return;
- }
- setter(request.Data[key].asBool());
-}
-
-cmServerResponse cmServerProtocol1::ProcessSetGlobalSettings(
- const cmServerRequest& request)
-{
- const std::vector<std::string> boolValues = {
- kDEBUG_OUTPUT_KEY, kTRACE_KEY, kTRACE_EXPAND_KEY,
- kWARN_UNINITIALIZED_KEY, kWARN_UNUSED_KEY, kWARN_UNUSED_CLI_KEY,
- kCHECK_SYSTEM_VARS_KEY
- };
- for (std::string const& i : boolValues) {
- if (!request.Data[i].isNull() && !request.Data[i].isBool()) {
- return request.ReportError("\"" + i +
- "\" must be unset or a bool value.");
- }
- }
-
- cmake* cm = this->CMakeInstance();
-
- setBool(request, kDEBUG_OUTPUT_KEY,
- [cm](bool e) { cm->SetDebugOutputOn(e); });
- setBool(request, kTRACE_KEY, [cm](bool e) { cm->SetTrace(e); });
- setBool(request, kTRACE_EXPAND_KEY, [cm](bool e) { cm->SetTraceExpand(e); });
- setBool(request, kWARN_UNINITIALIZED_KEY,
- [cm](bool e) { cm->SetWarnUninitialized(e); });
- setBool(request, kWARN_UNUSED_KEY, [this](bool e) { m_WarnUnused = e; });
- setBool(request, kWARN_UNUSED_CLI_KEY,
- [cm](bool e) { cm->SetWarnUnusedCli(e); });
- setBool(request, kCHECK_SYSTEM_VARS_KEY,
- [cm](bool e) { cm->SetCheckSystemVars(e); });
-
- return request.Reply(Json::Value());
-}
-
-cmServerResponse cmServerProtocol1::ProcessFileSystemWatchers(
- const cmServerRequest& request)
-{
- const cmFileMonitor* const fm = FileMonitor();
- Json::Value result = Json::objectValue;
- Json::Value files = Json::arrayValue;
- for (auto const& f : fm->WatchedFiles()) {
- files.append(f);
- }
- Json::Value directories = Json::arrayValue;
- for (auto const& d : fm->WatchedDirectories()) {
- directories.append(d);
- }
- result[kWATCHED_FILES_KEY] = files;
- result[kWATCHED_DIRECTORIES_KEY] = directories;
-
- return request.Reply(result);
-}
-
-cmServerResponse cmServerProtocol1::ProcessCTests(
- const cmServerRequest& request)
-{
- if (this->m_State < STATE_COMPUTED) {
- return request.ReportError("This instance was not yet computed.");
- }
-
- return request.Reply(cmDumpCTestInfo(this->CMakeInstance()));
-}
-
-cmServerProtocol1::GeneratorInformation::GeneratorInformation(
- std::string generatorName, std::string extraGeneratorName,
- std::string toolset, std::string platform, std::string sourceDirectory,
- std::string buildDirectory)
- : GeneratorName(std::move(generatorName))
- , ExtraGeneratorName(std::move(extraGeneratorName))
- , Toolset(std::move(toolset))
- , Platform(std::move(platform))
- , SourceDirectory(std::move(sourceDirectory))
- , BuildDirectory(std::move(buildDirectory))
-{
-}
-
-void cmServerProtocol1::GeneratorInformation::SetupGenerator(
- cmake* cm, std::string* errorMessage)
-{
- const std::string fullGeneratorName =
- cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- GeneratorName, ExtraGeneratorName);
-
- cm->SetHomeDirectory(SourceDirectory);
- cm->SetHomeOutputDirectory(BuildDirectory);
-
- auto gg = cm->CreateGlobalGenerator(fullGeneratorName);
- if (!gg) {
- setErrorMessage(
- errorMessage,
- std::string("Could not set up the requested combination of \"") +
- kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\"");
- return;
- }
-
- cm->SetGlobalGenerator(std::move(gg));
-
- cm->SetGeneratorToolset(Toolset);
- cm->SetGeneratorPlatform(Platform);
-}
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
deleted file mode 100644
index 6009e23bf..000000000
--- a/Source/cmServerProtocol.h
+++ /dev/null
@@ -1,162 +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 <memory>
-#include <string>
-#include <utility>
-
-#include <cm3p/json/value.h>
-
-#include "cmake.h"
-
-class cmConnection;
-class cmFileMonitor;
-class cmServer;
-class cmServerRequest;
-
-class cmServerResponse
-{
-public:
- explicit cmServerResponse(const cmServerRequest& request);
-
- void SetData(const Json::Value& data);
- void SetError(const std::string& message);
-
- bool IsComplete() const;
- bool IsError() const;
- std::string ErrorMessage() const;
- Json::Value Data() const;
-
- const std::string Type;
- const std::string Cookie;
-
-private:
- enum PayLoad
- {
- PAYLOAD_UNKNOWN,
- PAYLOAD_ERROR,
- PAYLOAD_DATA
- };
- PayLoad m_Payload = PAYLOAD_UNKNOWN;
- std::string m_ErrorMessage;
- Json::Value m_Data;
-};
-
-class cmServerRequest
-{
-public:
- cmServerResponse Reply(const Json::Value& data) const;
- cmServerResponse ReportError(const std::string& message) const;
-
- const std::string Type;
- const std::string Cookie;
- const Json::Value Data;
- cmConnection* Connection;
-
-private:
- cmServerRequest(cmServer* server, cmConnection* connection, std::string t,
- std::string c, Json::Value d);
-
- void ReportProgress(int min, int current, int max,
- const std::string& message) const;
- void ReportMessage(const std::string& message,
- const std::string& title) const;
-
- cmServer* m_Server;
-
- friend class cmServer;
-};
-
-class cmServerProtocol
-{
-public:
- cmServerProtocol() = default;
- virtual ~cmServerProtocol() = default;
-
- cmServerProtocol(cmServerProtocol const&) = delete;
- cmServerProtocol& operator=(cmServerProtocol const&) = delete;
-
- virtual std::pair<int, int> ProtocolVersion() const = 0;
- virtual bool IsExperimental() const = 0;
- virtual cmServerResponse Process(const cmServerRequest& request) = 0;
-
- bool Activate(cmServer* server, const cmServerRequest& request,
- std::string* errorMessage);
-
- cmFileMonitor* FileMonitor() const;
- void SendSignal(const std::string& name, const Json::Value& data) const;
-
-protected:
- cmake* CMakeInstance() const;
- // Implement protocol specific activation tasks here. Called from Activate().
- virtual bool DoActivate(const cmServerRequest& request,
- std::string* errorMessage);
- bool m_WarnUnused = false; // storage for legacy option
-
-private:
- std::unique_ptr<cmake> m_CMakeInstance;
- cmServer* m_Server = nullptr; // not owned!
-
- friend class cmServer;
-};
-
-class cmServerProtocol1 : public cmServerProtocol
-{
-public:
- std::pair<int, int> ProtocolVersion() const override;
- bool IsExperimental() const override;
- cmServerResponse Process(const cmServerRequest& request) override;
-
-private:
- bool DoActivate(const cmServerRequest& request,
- std::string* errorMessage) override;
-
- void HandleCMakeFileChanges(const std::string& path, int event, int status);
-
- // Handle requests:
- cmServerResponse ProcessCache(const cmServerRequest& request);
- cmServerResponse ProcessCMakeInputs(const cmServerRequest& request);
- cmServerResponse ProcessCodeModel(const cmServerRequest& request);
- cmServerResponse ProcessCompute(const cmServerRequest& request);
- cmServerResponse ProcessConfigure(const cmServerRequest& request);
- cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
- cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
- cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request);
- cmServerResponse ProcessCTests(const cmServerRequest& request);
-
- enum State
- {
- STATE_INACTIVE,
- STATE_ACTIVE,
- STATE_CONFIGURED,
- STATE_COMPUTED
- };
- State m_State = STATE_INACTIVE;
-
- bool m_isDirty = false;
-
- struct GeneratorInformation
- {
- public:
- GeneratorInformation() = default;
- GeneratorInformation(std::string generatorName,
- std::string extraGeneratorName, std::string toolset,
- std::string platform, std::string sourceDirectory,
- std::string buildDirectory);
-
- void SetupGenerator(cmake* cm, std::string* errorMessage);
-
- std::string GeneratorName;
- std::string ExtraGeneratorName;
- std::string Toolset;
- std::string Platform;
-
- std::string SourceDirectory;
- std::string BuildDirectory;
- };
-
- GeneratorInformation GeneratorInfo;
-};
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index df6a38a31..c8990537b 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -10,9 +10,12 @@
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -157,7 +160,7 @@ bool HandleSourceFileDirectoryScopeValidation(
return true;
}
-bool HandleAndValidateSourceFileDirectortoryScopes(
+bool HandleAndValidateSourceFileDirectoryScopes(
cmExecutionStatus& status, bool source_file_directory_option_enabled,
bool source_file_target_option_enabled,
std::vector<std::string>& source_file_directories,
@@ -186,7 +189,7 @@ std::string MakeSourceFilePathAbsoluteIfNeeded(
if (!needed) {
return source_file_path;
}
- const std::string absolute_file_path = cmSystemTools::CollapseFullPath(
+ std::string absolute_file_path = cmSystemTools::CollapseFullPath(
source_file_path, status.GetMakefile().GetCurrentSourceDirectory());
return absolute_file_path;
}
@@ -216,8 +219,92 @@ void MakeSourceFilePathsAbsoluteIfNeeded(
source_files_absolute_paths.push_back(absolute_file_path);
}
}
+
+bool HandleAndValidateSourceFilePropertyGENERATED(
+ cmSourceFile* sf, std::string const& propertyValue, PropertyOp op)
+{
+ const auto& mf = *sf->GetLocation().GetMakefile();
+ auto policyStatus = mf.GetPolicyStatus(cmPolicies::CMP0118);
+
+ const bool policyWARN = policyStatus == cmPolicies::WARN;
+ const bool policyNEW = policyStatus != cmPolicies::OLD && !policyWARN;
+
+ if (policyWARN) {
+ if (!cmIsOn(propertyValue) && !cmIsOff(propertyValue)) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0118),
+ "\nAttempt to set property 'GENERATED' with the following "
+ "non-boolean value (which will be interpreted as \"0\"):\n",
+ propertyValue,
+ "\nThat exact value will not be retrievable. A value of "
+ "\"0\" will be returned instead.\n"
+ "This will be an error under policy CMP0118.\n"));
+ }
+ if (cmIsOff(propertyValue)) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0118),
+ "\nUnsetting property 'GENERATED' will not be allowed under "
+ "policy CMP0118!\n"));
+ }
+ if (op == PropertyOp::Append || op == PropertyOp::AppendAsString) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0118),
+ "\nAppending to property 'GENERATED' will not be allowed "
+ "under policy CMP0118!\n"));
+ }
+ } else if (policyNEW) {
+ if (!cmIsOn(propertyValue) && !cmIsOff(propertyValue)) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_ERROR,
+ cmStrCat(
+ "Policy CMP0118 is set to NEW and the following non-boolean value "
+ "given for property 'GENERATED' is therefore not allowed:\n",
+ propertyValue, "\nReplace it with a boolean value!\n"));
+ return true;
+ }
+ if (cmIsOff(propertyValue)) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_ERROR,
+ "Unsetting the 'GENERATED' property is not allowed under CMP0118!\n");
+ return true;
+ }
+ if (op == PropertyOp::Append || op == PropertyOp::AppendAsString) {
+ mf.IssueMessage(MessageType::AUTHOR_ERROR,
+ "Policy CMP0118 is set to NEW and appending to the "
+ "'GENERATED' property is therefore not allowed. Only "
+ "setting it to \"1\" is allowed!\n");
+ return true;
+ }
+ }
+
+ // Set property.
+ if (!policyNEW) {
+ // Do it the traditional way.
+ switch (op) {
+ case PropertyOp::Append:
+ sf->AppendProperty("GENERATED", propertyValue, false);
+ break;
+ case PropertyOp::AppendAsString:
+ sf->AppendProperty("GENERATED", propertyValue, true);
+ break;
+ case PropertyOp::Remove:
+ sf->SetProperty("GENERATED", nullptr);
+ break;
+ case PropertyOp::Set:
+ sf->SetProperty("GENERATED", propertyValue.c_str());
+ break;
+ }
+ } else {
+ sf->MarkAsGenerated();
+ }
+ return true;
}
+} // END: namespace SetPropertyCommand
+
bool cmSetPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -324,7 +411,7 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args,
std::vector<cmMakefile*> source_file_directory_makefiles;
bool file_scopes_handled =
- SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
status, source_file_directory_option_enabled,
source_file_target_option_enabled, source_file_directories,
source_file_target_directories, source_file_directory_makefiles);
@@ -367,7 +454,7 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args,
return true;
}
-namespace {
+namespace /* anonymous */ {
bool HandleGlobalMode(cmExecutionStatus& status,
const std::set<std::string>& names,
const std::string& propertyName,
@@ -502,7 +589,7 @@ bool HandleSourceMode(cmExecutionStatus& status,
status, files_absolute, unique_files.begin(), unique_files.end(),
source_file_paths_should_be_absolute);
- for (const auto mf : directory_makefiles) {
+ for (auto* const mf : directory_makefiles) {
for (std::string const& name : files_absolute) {
// Get the source file.
if (cmSourceFile* sf = mf->GetOrCreateSource(name)) {
@@ -525,6 +612,18 @@ bool HandleSource(cmSourceFile* sf, const std::string& propertyName,
const std::string& propertyValue, bool appendAsString,
bool appendMode, bool remove)
{
+ // Special validation and handling of GENERATED flag?
+ if (propertyName == "GENERATED") {
+ SetPropertyCommand::PropertyOp op = (remove)
+ ? SetPropertyCommand::PropertyOp::Remove
+ : (appendAsString)
+ ? SetPropertyCommand::PropertyOp::AppendAsString
+ : (appendMode) ? SetPropertyCommand::PropertyOp::Append
+ : SetPropertyCommand::PropertyOp::Set;
+ return SetPropertyCommand::HandleAndValidateSourceFilePropertyGENERATED(
+ sf, propertyValue, op);
+ }
+
// Set or append the property.
if (appendMode) {
sf->AppendProperty(propertyName, propertyValue, appendAsString);
diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h
index 89fdd9af1..05c487309 100644
--- a/Source/cmSetPropertyCommand.h
+++ b/Source/cmSetPropertyCommand.h
@@ -9,6 +9,7 @@
class cmMakefile;
class cmExecutionStatus;
+class cmSourceFile;
bool cmSetPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status);
@@ -25,7 +26,7 @@ bool HandleSourceFileDirectoryScopeValidation(
std::vector<std::string>& source_file_directories,
std::vector<std::string>& source_file_target_directories);
-bool HandleAndValidateSourceFileDirectortoryScopes(
+bool HandleAndValidateSourceFileDirectoryScopes(
cmExecutionStatus& status, bool source_directories_option_encountered,
bool source_target_directories_option_encountered,
std::vector<std::string>& source_directories,
@@ -39,4 +40,16 @@ void MakeSourceFilePathsAbsoluteIfNeeded(
std::vector<std::string>& source_files_absolute_paths,
std::vector<std::string>::const_iterator files_it_begin,
std::vector<std::string>::const_iterator files_it_end, bool needed);
+
+enum class PropertyOp
+{
+ Remove,
+ Set,
+ Append,
+ AppendAsString
+};
+
+bool HandleAndValidateSourceFilePropertyGENERATED(
+ cmSourceFile* sf, std::string const& propertyValue,
+ PropertyOp op = PropertyOp::Set);
}
diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx
index c1b0c28db..237b67fed 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.cxx
+++ b/Source/cmSetSourceFilesPropertiesCommand.cxx
@@ -7,6 +7,7 @@
#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
@@ -82,7 +83,7 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
const auto props_begin = options_it;
bool file_scopes_handled =
- SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
+ SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
status, source_file_directory_option_enabled,
source_file_target_option_enabled, source_file_directories,
source_file_target_directories, source_file_directory_makefiles);
@@ -100,7 +101,7 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
// Now call the worker function for each directory scope represented by a
// cmMakefile instance.
std::string errors;
- for (const auto mf : source_file_directory_makefiles) {
+ for (auto* const mf : source_file_directory_makefiles) {
bool ret = RunCommandForScope(mf, files.begin(), files.end(), props_begin,
args.end(), errors);
if (!ret) {
@@ -167,7 +168,13 @@ static bool RunCommandForScope(
if (cmSourceFile* sf = mf->GetOrCreateSource(sfname)) {
// loop through the props and set them
for (auto k = propertyPairs.begin(); k != propertyPairs.end(); k += 2) {
- sf->SetProperty(*k, (k + 1)->c_str());
+ // Special handling for GENERATED property?
+ if (*k == "GENERATED"_s) {
+ SetPropertyCommand::HandleAndValidateSourceFilePropertyGENERATED(
+ sf, *(k + 1));
+ } else {
+ sf->SetProperty(*k, (k + 1)->c_str());
+ }
}
}
}
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index ef44a578d..3f3c8d501 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -8,6 +8,7 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
@@ -15,9 +16,12 @@
#include "cmake.h"
cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name,
- cmSourceFileLocationKind kind)
- : Location(mf, name, kind)
+ bool generated, cmSourceFileLocationKind kind)
+ : Location(mf, name, (!generated) ? kind : cmSourceFileLocationKind::Known)
{
+ if (generated) {
+ this->MarkAsGenerated();
+ }
}
std::string const& cmSourceFile::GetExtension() const
@@ -25,6 +29,8 @@ std::string const& cmSourceFile::GetExtension() const
return this->Extension;
}
+const std::string propTRUE = "1";
+const std::string propFALSE = "0";
const std::string cmSourceFile::propLANGUAGE = "LANGUAGE";
const std::string cmSourceFile::propLOCATION = "LOCATION";
const std::string cmSourceFile::propGENERATED = "GENERATED";
@@ -54,16 +60,14 @@ std::string const& cmSourceFile::GetOrDetermineLanguage()
}
// Perform computation needed to get the language if necessary.
- if (this->FullPath.empty() && this->Language.empty()) {
- // If a known extension is given or a known full path is given
- // then trust that the current extension is sufficient to
- // determine the language. This will fail only if the user
- // specifies a full path to the source but leaves off the
- // extension, which is kind of weird.
- if (this->Location.ExtensionIsAmbiguous() &&
+ if (this->Language.empty()) {
+ // If a known extension is given or a known full path is given then trust
+ // that the current extension is sufficient to determine the language. This
+ // will fail only if the user specifies a full path to the source but
+ // leaves off the extension, which is kind of weird.
+ if (this->FullPath.empty() && this->Location.ExtensionIsAmbiguous() &&
this->Location.DirectoryIsAmbiguous()) {
- // Finalize the file location to get the extension and set the
- // language.
+ // Finalize the file location to get the extension and set the language.
this->ResolveFullPath();
} else {
// Use the known extension to get the language if possible.
@@ -93,10 +97,11 @@ cmSourceFileLocation const& cmSourceFile::GetLocation() const
return this->Location;
}
-std::string const& cmSourceFile::ResolveFullPath(std::string* error)
+std::string const& cmSourceFile::ResolveFullPath(std::string* error,
+ std::string* cmp0115Warning)
{
if (this->FullPath.empty()) {
- if (this->FindFullPath(error)) {
+ if (this->FindFullPath(error, cmp0115Warning)) {
this->CheckExtension();
}
}
@@ -108,14 +113,18 @@ std::string const& cmSourceFile::GetFullPath() const
return this->FullPath;
}
-bool cmSourceFile::FindFullPath(std::string* error)
+bool cmSourceFile::FindFullPath(std::string* error,
+ std::string* cmp0115Warning)
{
// If the file is generated compute the location without checking on disk.
- if (this->GetIsGenerated()) {
+ // Note: We also check for a locally set GENERATED property, because
+ // it might have been set before policy CMP0118 was set to NEW.
+ if (this->GetIsGenerated(CheckScope::GlobalAndLocal)) {
// The file is either already a full path or is relative to the
// build directory for the target.
this->Location.DirectoryUseBinary();
this->FullPath = this->Location.GetFullPath();
+ this->FindFullPathFailed = false;
return true;
}
@@ -131,23 +140,52 @@ bool cmSourceFile::FindFullPath(std::string* error)
// List of extension lists
std::vector<std::string> exts =
makefile->GetCMakeInstance()->GetAllExtensions();
+ auto cmp0115 = makefile->GetPolicyStatus(cmPolicies::CMP0115);
+ auto cmp0118 = makefile->GetPolicyStatus(cmPolicies::CMP0118);
+ bool const cmp0118new =
+ cmp0118 != cmPolicies::OLD && cmp0118 != cmPolicies::WARN;
// Tries to find the file in a given directory
- auto findInDir = [this, &exts, &lPath](std::string const& dir) -> bool {
+ auto findInDir = [this, &exts, &lPath, cmp0115, cmp0115Warning, cmp0118new,
+ makefile](std::string const& dir) -> bool {
// Compute full path
std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir);
// Try full path
- if (cmSystemTools::FileExists(fullPath)) {
+ if (cmp0118new &&
+ makefile->GetGlobalGenerator()->IsGeneratedFile(fullPath)) {
+ this->IsGenerated = true;
+ }
+ if (this->IsGenerated || cmSystemTools::FileExists(fullPath)) {
this->FullPath = fullPath;
return true;
}
- // Try full path with extension
- for (std::string const& ext : exts) {
- if (!ext.empty()) {
- std::string extPath = cmStrCat(fullPath, '.', ext);
- if (cmSystemTools::FileExists(extPath)) {
- this->FullPath = extPath;
- return true;
+ // This has to be an if statement due to a bug in Oracle Developer Studio.
+ // See https://community.oracle.com/tech/developers/discussion/4476246/
+ // for details.
+ if (cmp0115 == cmPolicies::OLD || cmp0115 == cmPolicies::WARN) {
+ // Try full path with extension
+ for (std::string const& ext : exts) {
+ if (!ext.empty()) {
+ std::string extPath = cmStrCat(fullPath, '.', ext);
+ if (cmp0118new &&
+ makefile->GetGlobalGenerator()->IsGeneratedFile(extPath)) {
+ this->IsGenerated = true;
+ }
+ if (this->IsGenerated || cmSystemTools::FileExists(extPath)) {
+ this->FullPath = extPath;
+ if (cmp0115 == cmPolicies::WARN) {
+ std::string warning =
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0115),
+ "\nFile:\n ", extPath);
+ if (cmp0115Warning) {
+ *cmp0115Warning = std::move(warning);
+ } else {
+ makefile->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING, warning);
+ }
+ }
+ return true;
+ }
}
}
}
@@ -168,11 +206,19 @@ bool cmSourceFile::FindFullPath(std::string* error)
}
// Compose error
- std::string err =
- cmStrCat("Cannot find source file:\n ", lPath, "\nTried extensions");
- for (std::string const& ext : exts) {
- err += " .";
- err += ext;
+ std::string err = cmStrCat("Cannot find source file:\n ", lPath);
+ switch (cmp0115) {
+ case cmPolicies::OLD:
+ case cmPolicies::WARN:
+ err = cmStrCat(err, "\nTried extensions");
+ for (auto const& ext : exts) {
+ err = cmStrCat(err, " .", ext);
+ }
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ break;
}
if (error != nullptr) {
*error = std::move(err);
@@ -246,11 +292,6 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value)
} else {
this->Properties.SetProperty(prop, value);
}
-
- // Update IsGenerated flag
- if (prop == propGENERATED) {
- this->IsGenerated = cmIsOn(value);
- }
}
void cmSourceFile::AppendProperty(const std::string& prop,
@@ -274,14 +315,9 @@ void cmSourceFile::AppendProperty(const std::string& prop,
} else {
this->Properties.AppendProperty(prop, value, asString);
}
-
- // Update IsGenerated flag
- if (prop == propGENERATED) {
- this->IsGenerated = this->GetPropertyAsBool(propGENERATED);
- }
}
-const char* cmSourceFile::GetPropertyForUser(const std::string& prop)
+cmProp cmSourceFile::GetPropertyForUser(const std::string& prop)
{
// This method is a consequence of design history and backwards
// compatibility. GetProperty is (and should be) a const method.
@@ -305,13 +341,27 @@ const char* cmSourceFile::GetPropertyForUser(const std::string& prop)
// Similarly, LANGUAGE can be determined by the file extension
// if it is requested by the user.
if (prop == propLANGUAGE) {
- // The c_str pointer is valid until `this->Language` is modified.
- return this->GetOrDetermineLanguage().c_str();
+ // The pointer is valid until `this->Language` is modified.
+ return &this->GetOrDetermineLanguage();
+ }
+
+ // Special handling for GENERATED property.
+ if (prop == propGENERATED) {
+ // We need to check policy CMP0118 in order to determine if we need to
+ // possibly consider the value of a locally set GENERATED property, too.
+ auto policyStatus =
+ this->Location.GetMakefile()->GetPolicyStatus(cmPolicies::CMP0118);
+ if (this->GetIsGenerated(
+ (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)
+ ? CheckScope::GlobalAndLocal
+ : CheckScope::Global)) {
+ return &propTRUE;
+ }
+ return &propFALSE;
}
// Perform the normal property lookup.
- cmProp p = this->GetProperty(prop);
- return p ? p->c_str() : nullptr;
+ return this->GetProperty(prop);
}
cmProp cmSourceFile::GetProperty(const std::string& prop) const
@@ -369,13 +419,15 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
return retVal;
}
-const char* cmSourceFile::GetSafeProperty(const std::string& prop) const
+const std::string& cmSourceFile::GetSafeProperty(const std::string& prop) const
{
cmProp ret = this->GetProperty(prop);
- if (!ret) {
- return "";
+ if (ret) {
+ return *ret;
}
- return ret->c_str();
+
+ static std::string const s_empty;
+ return s_empty;
}
bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const
@@ -383,11 +435,29 @@ bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const
return cmIsOn(this->GetProperty(prop));
}
+void cmSourceFile::MarkAsGenerated()
+{
+ this->IsGenerated = true;
+ const auto& mf = *this->Location.GetMakefile();
+ mf.GetGlobalGenerator()->MarkAsGeneratedFile(this->ResolveFullPath());
+}
+
+bool cmSourceFile::GetIsGenerated(CheckScope checkScope) const
+{
+ if (this->IsGenerated) {
+ // Globally marked as generated!
+ return true;
+ }
+ if (checkScope == CheckScope::GlobalAndLocal) {
+ // Check locally stored properties.
+ return this->GetPropertyAsBool(propGENERATED);
+ }
+ return false;
+}
+
void cmSourceFile::SetProperties(cmPropertyMap properties)
{
this->Properties = std::move(properties);
-
- this->IsGenerated = this->GetPropertyAsBool(propGENERATED);
}
cmCustomCommand* cmSourceFile::GetCustomCommand() const
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 39ea8e33f..76a5ded89 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -20,18 +20,18 @@ class cmMakefile;
/** \class cmSourceFile
* \brief Represent a class loaded from a makefile.
*
- * cmSourceFile is represents a class loaded from
- * a makefile.
+ * cmSourceFile represents a class loaded from a makefile.
*/
class cmSourceFile
{
public:
/**
- * Construct with the makefile storing the source and the initial
- * name referencing it.
+ * Construct with the makefile storing the source and the initial name
+ * referencing it. If it shall be marked as generated, this source file's
+ * kind is assumed to be known, regardless of the given value.
*/
cmSourceFile(
- cmMakefile* mf, const std::string& name,
+ cmMakefile* mf, const std::string& name, bool generated,
cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
/**
@@ -47,16 +47,36 @@ public:
//! Might return a nullptr if the property is not set or invalid
cmProp GetProperty(const std::string& prop) const;
//! Always returns a valid pointer
- const char* GetSafeProperty(const std::string& prop) const;
+ const std::string& GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
/** Implement getting a property when called from a CMake language
command like get_property or get_source_file_property. */
- const char* GetPropertyForUser(const std::string& prop);
+ cmProp GetPropertyForUser(const std::string& prop);
- //! Checks is the GENERATED property is set and true
- /// @return Equivalent to GetPropertyAsBool("GENERATED")
- bool GetIsGenerated() const { return this->IsGenerated; }
+ /// Marks this file as generated
+ /**
+ * This stores this file's path in the global table for all generated source
+ * files.
+ */
+ void MarkAsGenerated();
+ enum class CheckScope
+ {
+ Global,
+ GlobalAndLocal
+ };
+ /// Determines if this source file is marked as generated.
+ /**
+ * This will check if this file's path is stored in the global table of all
+ * generated source files. If that is not the case and checkScope is set to
+ * GlobalAndLocal the value of the possibly existing local GENERATED property
+ * is returned instead.
+ * @param checkScope Determines if alternatively for backwards-compatibility
+ * a local GENERATED property should be considered, too.
+ * @return true if this source file is marked as generated, otherwise false.
+ */
+ bool GetIsGenerated(
+ CheckScope checkScope = CheckScope::GlobalAndLocal) const;
const std::vector<BT<std::string>>& GetCompileOptions() const
{
@@ -77,7 +97,8 @@ public:
* Resolves the full path to the file. Attempts to locate the file on disk
* and finalizes its location.
*/
- std::string const& ResolveFullPath(std::string* error = nullptr);
+ std::string const& ResolveFullPath(std::string* error = nullptr,
+ std::string* cmp0115Warning = nullptr);
/**
* The resolved full path to the file. The returned file name might be empty
@@ -138,7 +159,7 @@ private:
bool FindFullPathFailed = false;
bool IsGenerated = false;
- bool FindFullPath(std::string* error);
+ bool FindFullPath(std::string* error, std::string* cmp0115Warning);
void CheckExtension();
void CheckLanguage(std::string const& ext);
@@ -154,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|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \
+ "\\.(C|F|M|c|c\\+\\+|cc|cpp|mpp|cxx|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/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 222bafac8..8c7154d7f 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -33,8 +33,7 @@ cmSourceFileLocation::cmSourceFileLocation(cmMakefile const* mf,
this->AmbiguousExtension = true;
this->Directory = cmSystemTools::GetFilenamePath(name);
if (cmSystemTools::FileIsFullPath(this->Directory)) {
- this->Directory = cmSystemTools::CollapseFullPath(
- this->Directory, mf->GetHomeOutputDirectory());
+ this->Directory = cmSystemTools::CollapseFullPath(this->Directory);
}
this->Name = cmSystemTools::GetFilenameName(name);
if (kind == cmSourceFileLocationKind::Known) {
@@ -99,7 +98,7 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name)
// The global generator checks extensions of enabled languages.
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
cmMakefile const* mf = this->Makefile;
- auto cm = mf->GetCMakeInstance();
+ auto* cm = mf->GetCMakeInstance();
if (!gg->GetLanguageFromExtension(ext.c_str()).empty() ||
cm->IsAKnownExtension(ext)) {
// This is a known extension. Use the given filename with extension.
@@ -156,7 +155,7 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension(
// disk. One of these must match if loc refers to this source file.
auto ext = cm::string_view(this->Name).substr(loc.Name.size() + 1);
cmMakefile const* mf = this->Makefile;
- auto cm = mf->GetCMakeInstance();
+ auto* cm = mf->GetCMakeInstance();
return cm->IsAKnownExtension(ext);
}
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index 8672f614b..bf6925e87 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -44,6 +44,16 @@ struct StandardNeeded
int value;
};
+int ParseStd(std::string const& level)
+{
+ try {
+ return std::stoi(level);
+ } catch (std::invalid_argument&) {
+ // Fall through to use an invalid value.
+ }
+ return -1;
+}
+
struct StanardLevelComputer
{
explicit StanardLevelComputer(std::string lang, std::vector<int> levels,
@@ -113,17 +123,8 @@ struct StanardLevelComputer
standardStr = "03";
}
- int standardValue = -1;
- int defaultValue = -1;
- try {
- standardValue = std::stoi(standardStr);
- defaultValue = std::stoi(*defaultStd);
- } catch (std::invalid_argument&) {
- // fall through as we want an error
- // when we can't find the bad value in the `stds` vector
- }
-
- auto stdIt = std::find(cm::cbegin(stds), cm::cend(stds), standardValue);
+ auto stdIt =
+ std::find(cm::cbegin(stds), cm::cend(stds), ParseStd(standardStr));
if (stdIt == cm::cend(stds)) {
std::string e =
cmStrCat(this->Language, "_STANDARD is set to invalid value '",
@@ -134,7 +135,7 @@ struct StanardLevelComputer
}
auto defaultStdIt =
- std::find(cm::cbegin(stds), cm::cend(stds), defaultValue);
+ std::find(cm::cbegin(stds), cm::cend(stds), ParseStd(*defaultStd));
if (defaultStdIt == cm::cend(stds)) {
std::string e = cmStrCat("CMAKE_", this->Language,
"_STANDARD_DEFAULT is set to invalid value '",
@@ -195,7 +196,7 @@ struct StanardLevelComputer
if (existingStandard) {
existingLevelIter =
std::find(cm::cbegin(this->Levels), cm::cend(this->Levels),
- std::stoi(*existingStandard));
+ ParseStd(*existingStandard));
if (existingLevelIter == cm::cend(this->Levels)) {
const std::string e =
cmStrCat("The ", this->Language, "_STANDARD property on target \"",
@@ -240,7 +241,7 @@ struct StanardLevelComputer
}
// convert defaultStandard to an integer
if (std::find(cm::cbegin(this->Levels), cm::cend(this->Levels),
- std::stoi(*defaultStandard)) == cm::cend(this->Levels)) {
+ ParseStd(*defaultStandard)) == cm::cend(this->Levels)) {
const std::string e = cmStrCat("The CMAKE_", this->Language,
"_STANDARD_DEFAULT variable contains an "
"invalid value: \"",
@@ -257,7 +258,7 @@ struct StanardLevelComputer
auto existingLevelIter =
std::find(cm::cbegin(this->Levels), cm::cend(this->Levels),
- std::stoi(*existingStandard));
+ ParseStd(*existingStandard));
if (existingLevelIter == cm::cend(this->Levels)) {
const std::string e =
cmStrCat("The ", this->Language, "_STANDARD property on target \"",
@@ -311,19 +312,19 @@ std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
std::vector<std::string>{ "90", "99", "11" } } },
{ "CXX",
StanardLevelComputer{
- "CXX", std::vector<int>{ 98, 11, 14, 17, 20 },
- std::vector<std::string>{ "98", "11", "14", "17", "20" } } },
+ "CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
{ "CUDA",
StanardLevelComputer{
- "CUDA", std::vector<int>{ 03, 11, 14, 17, 20 },
- std::vector<std::string>{ "03", "11", "14", "17", "20" } } },
+ "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" } } },
{ "OBJCXX",
StanardLevelComputer{
- "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20 },
- std::vector<std::string>{ "98", "11", "14", "17", "20" } } },
+ "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
};
}
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index 64c1645a6..1da8c9844 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -4,18 +4,22 @@
#if defined(__linux)
/* Needed for glibc < 2.12 */
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _XOPEN_SOURCE 600
#endif
#if !defined(_POSIX_C_SOURCE) && !defined(_WIN32) && !defined(__sun)
/* POSIX APIs are needed */
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _POSIX_C_SOURCE 200809L
#endif
#if defined(__sun) && defined(__GNUC__) && !defined(__cplusplus)
/* C sources: for fileno and strdup */
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _XOPEN_SOURCE 600
#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
/* For isascii */
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _XOPEN_SOURCE 700
#endif
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index d268e6233..d97762bb6 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -110,12 +110,9 @@ bool cmState::StringToCacheEntryType(const std::string& s,
bool cmState::IsCacheEntryType(std::string const& key)
{
- for (const std::string& i : cmCacheEntryTypes) {
- if (key == i) {
- return true;
- }
- }
- return false;
+ return std::any_of(
+ cmCacheEntryTypes.begin(), cmCacheEntryTypes.end(),
+ [&key](std::string const& i) -> bool { return key == i; });
}
bool cmState::LoadCache(const std::string& path, bool internal,
@@ -347,7 +344,7 @@ cmPropertyDefinition const* cmState::GetPropertyDefinition(
bool cmState::IsPropertyChained(const std::string& name,
cmProperty::ScopeType scope) const
{
- if (auto def = this->GetPropertyDefinition(name, scope)) {
+ if (const auto* def = this->GetPropertyDefinition(name, scope)) {
return def->IsChained();
}
return false;
@@ -441,6 +438,19 @@ void cmState::AddBuiltinCommand(std::string const& name,
});
}
+void cmState::AddFlowControlCommand(std::string const& name, Command command)
+{
+ this->FlowControlCommands.insert(name);
+ this->AddBuiltinCommand(name, std::move(command));
+}
+
+void cmState::AddFlowControlCommand(std::string const& name,
+ BuiltinCommand command)
+{
+ this->FlowControlCommands.insert(name);
+ this->AddBuiltinCommand(name, command);
+}
+
void cmState::AddDisallowedCommand(std::string const& name,
BuiltinCommand command,
cmPolicies::PolicyID policy,
@@ -470,7 +480,7 @@ void cmState::AddDisallowedCommand(std::string const& name,
void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
{
- this->AddBuiltinCommand(
+ this->AddFlowControlCommand(
name,
[name, error](std::vector<cmListFileArgument> const&,
cmExecutionStatus& status) -> bool {
@@ -485,21 +495,33 @@ void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
});
}
-void cmState::AddScriptedCommand(std::string const& name, Command command)
+bool cmState::AddScriptedCommand(std::string const& name, BT<Command> command,
+ cmMakefile& mf)
{
std::string sName = cmSystemTools::LowerCase(name);
+ if (this->FlowControlCommands.count(sName)) {
+ mf.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Built-in flow control command \"", sName,
+ "\" cannot be overridden."),
+ command.Backtrace);
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
// if the command already exists, give a new name to the old command.
if (Command oldCmd = this->GetCommandByExactName(sName)) {
this->ScriptedCommands["_" + sName] = oldCmd;
}
- this->ScriptedCommands[sName] = std::move(command);
+ this->ScriptedCommands[sName] = std::move(command.Value);
+ return true;
}
cmState::Command cmState::GetCommand(std::string const& name) const
{
- return GetCommandByExactName(cmSystemTools::LowerCase(name));
+ return this->GetCommandByExactName(cmSystemTools::LowerCase(name));
}
cmState::Command cmState::GetCommandByExactName(std::string const& name) const
diff --git a/Source/cmState.h b/Source/cmState.h
index e4c9eb524..4e411560a 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -9,6 +9,7 @@
#include <set>
#include <string>
#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "cmDefinitions.h"
@@ -24,6 +25,7 @@
class cmCacheManager;
class cmCommand;
class cmGlobVerificationManager;
+class cmMakefile;
class cmStateSnapshot;
class cmMessenger;
class cmExecutionStatus;
@@ -159,10 +161,13 @@ public:
std::unique_ptr<cmCommand> command);
void AddBuiltinCommand(std::string const& name, Command command);
void AddBuiltinCommand(std::string const& name, BuiltinCommand command);
+ void AddFlowControlCommand(std::string const& name, Command command);
+ void AddFlowControlCommand(std::string const& name, BuiltinCommand command);
void AddDisallowedCommand(std::string const& name, BuiltinCommand command,
cmPolicies::PolicyID policy, const char* message);
void AddUnexpectedCommand(std::string const& name, const char* error);
- void AddScriptedCommand(std::string const& name, Command command);
+ bool AddScriptedCommand(std::string const& name, BT<Command> command,
+ cmMakefile& mf);
void RemoveBuiltinCommand(std::string const& name);
void RemoveUserDefinedCommands();
std::vector<std::string> GetCommandNames() const;
@@ -225,6 +230,7 @@ private:
std::vector<std::string> EnabledLanguages;
std::unordered_map<std::string, Command> BuiltinCommands;
std::unordered_map<std::string, Command> ScriptedCommands;
+ std::unordered_set<std::string> FlowControlCommands;
cmPropertyMap GlobalProperties;
std::unique_ptr<cmCacheManager> CacheManager;
std::unique_ptr<cmGlobVerificationManager> GlobVerificationManager;
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 796bb1f75..7ce362a58 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -148,11 +148,13 @@ bool cmStateDirectory::ContainsBoth(std::string const& local_path,
cmSystemTools::IsSubDirectory(a, b));
};
- bool bothInBinary = PathEqOrSubDir(local_path, GetRelativePathTopBinary()) &&
- PathEqOrSubDir(remote_path, GetRelativePathTopBinary());
+ bool bothInBinary =
+ PathEqOrSubDir(local_path, this->GetRelativePathTopBinary()) &&
+ PathEqOrSubDir(remote_path, this->GetRelativePathTopBinary());
- bool bothInSource = PathEqOrSubDir(local_path, GetRelativePathTopSource()) &&
- PathEqOrSubDir(remote_path, GetRelativePathTopSource());
+ bool bothInSource =
+ PathEqOrSubDir(local_path, this->GetRelativePathTopSource()) &&
+ PathEqOrSubDir(remote_path, this->GetRelativePathTopSource());
return bothInBinary || bothInSource;
}
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index 56a262d87..70c19bc1c 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -97,7 +97,6 @@ private:
void ComputeRelativePathTopSource();
void ComputeRelativePathTopBinary();
-private:
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator
DirectoryState;
cmStateSnapshot Snapshot_;
diff --git a/Source/cmString.cxx b/Source/cmString.cxx
index 898b8286e..aefaa6465 100644
--- a/Source/cmString.cxx
+++ b/Source/cmString.cxx
@@ -1,5 +1,6 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
#define _SCL_SECURE_NO_WARNINGS
#include "cmString.hxx"
@@ -19,17 +20,17 @@ void String::internally_mutate_to_stable_string()
// We assume that only one thread mutates this instance at
// a time even if we point to a shared string buffer referenced
// by other threads.
- *this = String(data(), size());
+ *this = String(this->data(), this->size());
}
bool String::is_stable() const
{
- return str_if_stable() != nullptr;
+ return this->str_if_stable() != nullptr;
}
void String::stabilize()
{
- if (is_stable()) {
+ if (this->is_stable()) {
return;
}
this->internally_mutate_to_stable_string();
@@ -37,16 +38,17 @@ void String::stabilize()
std::string const* String::str_if_stable() const
{
- if (!data()) {
+ if (!this->data()) {
// We view no string.
// This is stable for the lifetime of our current value.
return &empty_string_;
}
- if (string_ && data() == string_->data() && size() == string_->size()) {
+ if (this->string_ && this->data() == this->string_->data() &&
+ this->size() == this->string_->size()) {
// We view an entire string.
// This is stable for the lifetime of our current value.
- return string_.get();
+ return this->string_.get();
}
return nullptr;
@@ -54,18 +56,18 @@ std::string const* String::str_if_stable() const
std::string const& String::str()
{
- if (std::string const* s = str_if_stable()) {
+ if (std::string const* s = this->str_if_stable()) {
return *s;
}
// Mutate to hold a std::string that is stable for the lifetime
// of our current value.
this->internally_mutate_to_stable_string();
- return *string_;
+ return *this->string_;
}
const char* String::c_str()
{
- const char* c = data();
+ const char* c = this->data();
if (c == nullptr) {
return c;
}
@@ -73,42 +75,42 @@ const char* String::c_str()
// We always point into a null-terminated string so it is safe to
// access one past the end. If it is a null byte then we can use
// the pointer directly.
- if (c[size()] == '\0') {
+ if (c[this->size()] == '\0') {
return c;
}
// Mutate to hold a std::string so we can get a null terminator.
this->internally_mutate_to_stable_string();
- c = string_->c_str();
+ c = this->string_->c_str();
return c;
}
String& String::insert(size_type index, size_type count, char ch)
{
std::string s;
- s.reserve(size() + count);
- s.assign(data(), size());
+ s.reserve(this->size() + count);
+ s.assign(this->data(), this->size());
s.insert(index, count, ch);
return *this = std::move(s);
}
String& String::erase(size_type index, size_type count)
{
- if (index > size()) {
+ if (index > this->size()) {
throw std::out_of_range("Index out of range in String::erase");
}
- size_type const rcount = std::min(count, size() - index);
+ size_type const rcount = std::min(count, this->size() - index);
size_type const rindex = index + rcount;
std::string s;
- s.reserve(size() - rcount);
- s.assign(data(), index);
- s.append(data() + rindex, size() - rindex);
+ s.reserve(this->size() - rcount);
+ s.assign(this->data(), index);
+ s.append(this->data() + rindex, this->size() - rindex);
return *this = std::move(s);
}
String String::substr(size_type pos, size_type count) const
{
- if (pos > size()) {
+ if (pos > this->size()) {
throw std::out_of_range("Index out of range in String::substr");
}
return String(*this, pos, count);
@@ -116,14 +118,14 @@ String String::substr(size_type pos, size_type count) const
String::String(std::string&& s, Private)
: string_(std::make_shared<std::string>(std::move(s)))
- , view_(string_->data(), string_->size())
+ , view_(this->string_->data(), this->string_->size())
{
}
String::size_type String::copy(char* dest, size_type count,
size_type pos) const
{
- return view_.copy(dest, count, pos);
+ return this->view_.copy(dest, count, pos);
}
std::ostream& operator<<(std::ostream& os, String const& s)
diff --git a/Source/cmString.hxx b/Source/cmString.hxx
index b41b9605b..f1e462bb2 100644
--- a/Source/cmString.hxx
+++ b/Source/cmString.hxx
@@ -301,8 +301,8 @@ public:
The other instance is left as a null string. */
String& operator=(String&& s) noexcept
{
- string_ = std::move(s.string_);
- view_ = s.view_;
+ this->string_ = std::move(s.string_);
+ this->view_ = s.view_;
s.view_ = string_view();
return *this;
}
@@ -340,33 +340,33 @@ public:
}
/** Return true if the instance is not a null string. */
- explicit operator bool() const noexcept { return data() != nullptr; }
+ explicit operator bool() const noexcept { return this->data() != nullptr; }
/** Return a view of the string. */
- string_view view() const noexcept { return view_; }
+ string_view view() const noexcept { return this->view_; }
operator string_view() const noexcept { return this->view(); }
/** Return true if the instance is an empty stringn or null string. */
- bool empty() const noexcept { return view_.empty(); }
+ bool empty() const noexcept { return this->view_.empty(); }
/** Return a pointer to the start of the string. */
- const char* data() const noexcept { return view_.data(); }
+ const char* data() const noexcept { return this->view_.data(); }
/** Return the length of the string in bytes. */
- size_type size() const noexcept { return view_.size(); }
- size_type length() const noexcept { return view_.length(); }
+ size_type size() const noexcept { return this->view_.size(); }
+ size_type length() const noexcept { return this->view_.length(); }
/** Return the character at the given position.
No bounds checking is performed. */
- char operator[](size_type pos) const noexcept { return view_[pos]; }
+ char operator[](size_type pos) const noexcept { return this->view_[pos]; }
/** Return the character at the given position.
If the position is out of bounds, throws std::out_of_range. */
- char at(size_type pos) const { return view_.at(pos); }
+ char at(size_type pos) const { return this->view_.at(pos); }
- char front() const noexcept { return view_.front(); }
+ char front() const noexcept { return this->view_.front(); }
- char back() const noexcept { return view_.back(); }
+ char back() const noexcept { return this->view_.back(); }
/** Return true if this instance is stable and otherwise false.
An instance is stable if it is in the 'null' state or if it is
@@ -392,15 +392,18 @@ public:
or str() is called. */
const char* c_str();
- const_iterator begin() const noexcept { return view_.begin(); }
- const_iterator end() const noexcept { return view_.end(); }
- const_iterator cbegin() const noexcept { return begin(); }
- const_iterator cend() const noexcept { return end(); }
+ const_iterator begin() const noexcept { return this->view_.begin(); }
+ const_iterator end() const noexcept { return this->view_.end(); }
+ const_iterator cbegin() const noexcept { return this->begin(); }
+ const_iterator cend() const noexcept { return this->end(); }
- const_reverse_iterator rbegin() const noexcept { return view_.rbegin(); }
- const_reverse_iterator rend() const noexcept { return view_.rend(); }
- const_reverse_iterator crbegin() const noexcept { return rbegin(); }
- const_reverse_iterator crend() const noexcept { return rend(); }
+ const_reverse_iterator rbegin() const noexcept
+ {
+ return this->view_.rbegin();
+ }
+ const_reverse_iterator rend() const noexcept { return this->view_.rend(); }
+ const_reverse_iterator crbegin() const noexcept { return this->rbegin(); }
+ const_reverse_iterator crend() const noexcept { return this->rend(); }
/** Append to the string using any type that implements the
AsStringView trait. */
@@ -410,8 +413,8 @@ public:
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
std::string r;
- r.reserve(size() + v.size());
- r.assign(data(), size());
+ r.reserve(this->size() + v.size());
+ r.assign(this->data(), this->size());
r.append(v.data(), v.size());
return *this = std::move(r);
}
@@ -428,21 +431,21 @@ public:
void push_back(char ch)
{
std::string s;
- s.reserve(size() + 1);
- s.assign(data(), size());
+ s.reserve(this->size() + 1);
+ s.assign(this->data(), this->size());
s.push_back(ch);
*this = std::move(s);
}
- void pop_back() { *this = String(*this, 0, size() - 1); }
+ void pop_back() { *this = String(*this, 0, this->size() - 1); }
template <typename T>
typename std::enable_if<AsStringView<T>::value, String&>::type replace(
size_type pos, size_type count, T&& s)
{
- const_iterator first = begin() + pos;
+ const_iterator first = this->begin() + pos;
const_iterator last = first + count;
- return replace(first, last, std::forward<T>(s));
+ return this->replace(first, last, std::forward<T>(s));
}
template <typename InputIterator>
@@ -450,9 +453,9 @@ public:
InputIterator first2, InputIterator last2)
{
std::string out;
- out.append(view_.begin(), first);
+ out.append(this->view_.begin(), first);
out.append(first2, last2);
- out.append(last, view_.end());
+ out.append(last, this->view_.end());
return *this = std::move(out);
}
@@ -462,10 +465,11 @@ public:
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
std::string out;
- out.reserve((first - view_.begin()) + v.size() + (view_.end() - last));
- out.append(view_.begin(), first);
+ out.reserve((first - this->view_.begin()) + v.size() +
+ (this->view_.end() - last));
+ out.append(this->view_.begin(), first);
out.append(v.data(), v.size());
- out.append(last, view_.end());
+ out.append(last, this->view_.end());
return *this = std::move(out);
}
@@ -476,39 +480,40 @@ public:
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
v = v.substr(pos2, count2);
- return replace(pos, count, v);
+ return this->replace(pos, count, v);
}
String& replace(size_type pos, size_type count, size_type count2, char ch)
{
- const_iterator first = begin() + pos;
+ const_iterator first = this->begin() + pos;
const_iterator last = first + count;
- return replace(first, last, count2, ch);
+ return this->replace(first, last, count2, ch);
}
String& replace(const_iterator first, const_iterator last, size_type count2,
char ch)
{
std::string out;
- out.reserve((first - view_.begin()) + count2 + (view_.end() - last));
- out.append(view_.begin(), first);
+ out.reserve((first - this->view_.begin()) + count2 +
+ (this->view_.end() - last));
+ out.append(this->view_.begin(), first);
out.append(count2, ch);
- out.append(last, view_.end());
+ out.append(last, this->view_.end());
return *this = std::move(out);
}
size_type copy(char* dest, size_type count, size_type pos = 0) const;
- void resize(size_type count) { resize(count, char()); }
+ void resize(size_type count) { this->resize(count, char()); }
void resize(size_type count, char ch)
{
std::string s;
s.reserve(count);
- if (count <= size()) {
- s.assign(data(), count);
+ if (count <= this->size()) {
+ s.assign(this->data(), count);
} else {
- s.assign(data(), size());
+ s.assign(this->data(), this->size());
s.resize(count, ch);
}
*this = std::move(s);
@@ -516,8 +521,8 @@ public:
void swap(String& other)
{
- std::swap(string_, other.string_);
- std::swap(view_, other.view_);
+ std::swap(this->string_, other.string_);
+ std::swap(this->view_, other.view_);
}
/** Return a substring starting at position 'pos' and
@@ -528,29 +533,29 @@ public:
typename std::enable_if<AsStringView<T>::value, int>::type compare(
T&& s) const
{
- return view_.compare(AsStringView<T>::view(std::forward<T>(s)));
+ return this->view_.compare(AsStringView<T>::view(std::forward<T>(s)));
}
int compare(size_type pos1, size_type count1, string_view v) const
{
- return view_.compare(pos1, count1, v);
+ return this->view_.compare(pos1, count1, v);
}
int compare(size_type pos1, size_type count1, string_view v, size_type pos2,
size_type count2) const
{
- return view_.compare(pos1, count1, v, pos2, count2);
+ return this->view_.compare(pos1, count1, v, pos2, count2);
}
int compare(size_type pos1, size_type count1, const char* s) const
{
- return view_.compare(pos1, count1, s);
+ return this->view_.compare(pos1, count1, s);
}
int compare(size_type pos1, size_type count1, const char* s,
size_type count2) const
{
- return view_.compare(pos1, count1, s, count2);
+ return this->view_.compare(pos1, count1, s, count2);
}
template <typename T>
@@ -558,12 +563,12 @@ public:
T&& s, size_type pos = 0) const
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
- return view_.find(v, pos);
+ return this->view_.find(v, pos);
}
size_type find(const char* s, size_type pos, size_type count) const
{
- return view_.find(s, pos, count);
+ return this->view_.find(s, pos, count);
}
template <typename T>
@@ -571,12 +576,12 @@ public:
T&& s, size_type pos = npos) const
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
- return view_.rfind(v, pos);
+ return this->view_.rfind(v, pos);
}
size_type rfind(const char* s, size_type pos, size_type count) const
{
- return view_.rfind(s, pos, count);
+ return this->view_.rfind(s, pos, count);
}
template <typename T>
@@ -584,12 +589,12 @@ public:
find_first_of(T&& s, size_type pos = 0) const
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
- return view_.find_first_of(v, pos);
+ return this->view_.find_first_of(v, pos);
}
size_type find_first_of(const char* s, size_type pos, size_type count) const
{
- return view_.find_first_of(s, pos, count);
+ return this->view_.find_first_of(s, pos, count);
}
template <typename T>
@@ -597,13 +602,13 @@ public:
find_first_not_of(T&& s, size_type pos = 0) const
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
- return view_.find_first_not_of(v, pos);
+ return this->view_.find_first_not_of(v, pos);
}
size_type find_first_not_of(const char* s, size_type pos,
size_type count) const
{
- return view_.find_first_not_of(s, pos, count);
+ return this->view_.find_first_not_of(s, pos, count);
}
template <typename T>
@@ -611,12 +616,12 @@ public:
find_last_of(T&& s, size_type pos = npos) const
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
- return view_.find_last_of(v, pos);
+ return this->view_.find_last_of(v, pos);
}
size_type find_last_of(const char* s, size_type pos, size_type count) const
{
- return view_.find_last_of(s, pos, count);
+ return this->view_.find_last_of(s, pos, count);
}
template <typename T>
@@ -624,13 +629,13 @@ public:
find_last_not_of(T&& s, size_type pos = npos) const
{
string_view v = AsStringView<T>::view(std::forward<T>(s));
- return view_.find_last_not_of(v, pos);
+ return this->view_.find_last_not_of(v, pos);
}
size_type find_last_not_of(const char* s, size_type pos,
size_type count) const
{
- return view_.find_last_not_of(s, pos, count);
+ return this->view_.find_last_not_of(s, pos, count);
}
private:
@@ -822,7 +827,10 @@ struct StringOpPlus
}
#endif
operator std::string() const;
- std::string::size_type size() const { return l.size() + r.size(); }
+ std::string::size_type size() const
+ {
+ return this->l.size() + this->r.size();
+ }
};
template <typename T>
@@ -848,7 +856,7 @@ template <typename L, typename R>
StringOpPlus<L, R>::operator std::string() const
{
std::string s;
- s.reserve(size());
+ s.reserve(this->size());
s += *this;
return s;
}
diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx
index e0af28185..5bb6e7bc5 100644
--- a/Source/cmStringAlgorithms.cxx
+++ b/Source/cmStringAlgorithms.cxx
@@ -11,6 +11,9 @@
std::string cmTrimWhitespace(cm::string_view str)
{
+ // XXX(clang-tidy): This declaration and the next cannot be `const auto*`
+ // because the qualification of `auto` is platform-dependent.
+ // NOLINTNEXTLINE(readability-qualified-auto)
auto start = str.begin();
while (start != str.end() && cmIsSpace(*start)) {
++start;
@@ -18,6 +21,7 @@ std::string cmTrimWhitespace(cm::string_view str)
if (start == str.end()) {
return std::string();
}
+ // NOLINTNEXTLINE(readability-qualified-auto)
auto stop = str.end() - 1;
while (cmIsSpace(*stop)) {
--stop;
@@ -161,42 +165,42 @@ inline void MakeDigits(cm::string_view& view, char (&digits)[N],
cmAlphaNum::cmAlphaNum(int val)
{
- MakeDigits(View_, Digits_, "%i", val);
+ MakeDigits(this->View_, this->Digits_, "%i", val);
}
cmAlphaNum::cmAlphaNum(unsigned int val)
{
- MakeDigits(View_, Digits_, "%u", val);
+ MakeDigits(this->View_, this->Digits_, "%u", val);
}
cmAlphaNum::cmAlphaNum(long int val)
{
- MakeDigits(View_, Digits_, "%li", val);
+ MakeDigits(this->View_, this->Digits_, "%li", val);
}
cmAlphaNum::cmAlphaNum(unsigned long int val)
{
- MakeDigits(View_, Digits_, "%lu", val);
+ MakeDigits(this->View_, this->Digits_, "%lu", val);
}
cmAlphaNum::cmAlphaNum(long long int val)
{
- MakeDigits(View_, Digits_, "%lli", val);
+ MakeDigits(this->View_, this->Digits_, "%lli", val);
}
cmAlphaNum::cmAlphaNum(unsigned long long int val)
{
- MakeDigits(View_, Digits_, "%llu", val);
+ MakeDigits(this->View_, this->Digits_, "%llu", val);
}
cmAlphaNum::cmAlphaNum(float val)
{
- MakeDigits(View_, Digits_, "%g", static_cast<double>(val));
+ MakeDigits(this->View_, this->Digits_, "%g", static_cast<double>(val));
}
cmAlphaNum::cmAlphaNum(double val)
{
- MakeDigits(View_, Digits_, "%g", val);
+ MakeDigits(this->View_, this->Digits_, "%g", val);
}
std::string cmCatViews(std::initializer_list<cm::string_view> views)
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
index 01e3d940e..6b458ec52 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -48,7 +48,7 @@ struct cmStrCmp
{
}
- bool operator()(cm::string_view sv) const { return Test_ == sv; }
+ bool operator()(cm::string_view sv) const { return this->Test_ == sv; }
private:
std::string const Test_;
@@ -163,9 +163,9 @@ public:
{
}
cmAlphaNum(char ch)
- : View_(Digits_, 1)
+ : View_(this->Digits_, 1)
{
- Digits_[0] = ch;
+ this->Digits_[0] = ch;
}
cmAlphaNum(int val);
cmAlphaNum(unsigned int val);
@@ -176,7 +176,7 @@ public:
cmAlphaNum(float val);
cmAlphaNum(double val);
- cm::string_view View() const { return View_; }
+ cm::string_view View() const { return this->View_; }
private:
cm::string_view View_;
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index b28fca954..23fc3e0f6 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -1,5 +1,6 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
#define _SCL_SECURE_NO_WARNINGS
#include "cmStringCommand.h"
@@ -966,21 +967,21 @@ public:
const std::string& Args::PopFront(cm::string_view error)
{
- if (empty()) {
+ if (this->empty()) {
throw json_error({ error });
}
- const std::string& res = *begin();
- advance(1);
+ const std::string& res = *this->begin();
+ this->advance(1);
return res;
}
const std::string& Args::PopBack(cm::string_view error)
{
- if (empty()) {
+ if (this->empty()) {
throw json_error({ error });
}
- const std::string& res = *(end() - 1);
- retreat(1);
+ const std::string& res = *(this->end() - 1);
+ this->retreat(1);
return res;
}
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 6a705f480..080759077 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -3,11 +3,13 @@
#if !defined(_WIN32) && !defined(__sun)
// POSIX APIs are needed
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _POSIX_C_SOURCE 200809L
#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__QNX__)
// For isascii
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _XOPEN_SOURCE 700
#endif
@@ -43,14 +45,18 @@
# include "cmCryptoHash.h"
#endif
-#if defined(CMAKE_USE_ELF_PARSER)
+#if defined(CMake_USE_ELF_PARSER)
# include "cmELF.h"
#endif
-#if defined(CMAKE_USE_MACH_PARSER)
+#if defined(CMake_USE_MACH_PARSER)
# include "cmMachO.h"
#endif
+#if defined(CMake_USE_XCOFF_PARSER)
+# include "cmXCOFF.h"
+#endif
+
#include <algorithm>
#include <cassert>
#include <cctype>
@@ -1255,6 +1261,30 @@ void cmSystemTools::ConvertToOutputSlashes(std::string& path)
#endif
}
+void cmSystemTools::ConvertToLongPath(std::string& path)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Try to convert path to a long path only if the path contains character '~'
+ if (path.find('~') == std::string::npos) {
+ return;
+ }
+
+ std::wstring wPath = cmsys::Encoding::ToWide(path);
+ DWORD ret = GetLongPathNameW(wPath.c_str(), nullptr, 0);
+ std::vector<wchar_t> buffer(ret);
+ if (ret != 0) {
+ ret = GetLongPathNameW(wPath.c_str(), buffer.data(),
+ static_cast<DWORD>(buffer.size()));
+ }
+
+ if (ret != 0) {
+ path = cmsys::Encoding::ToNarrow(buffer.data());
+ }
+#else
+ static_cast<void>(path);
+#endif
+}
+
std::string cmSystemTools::ConvertToRunCommandPath(const std::string& path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -2291,7 +2321,7 @@ bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
{
// For ELF shared libraries use a real parser to get the correct
// soname.
-#if defined(CMAKE_USE_ELF_PARSER)
+#if defined(CMake_USE_ELF_PARSER)
cmELF elf(fullPath.c_str());
if (elf) {
return elf.GetSOName(soname);
@@ -2321,7 +2351,7 @@ bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
std::string& soname)
{
-#if defined(CMAKE_USE_MACH_PARSER)
+#if defined(CMake_USE_MACH_PARSER)
cmMachO macho(fullPath.c_str());
if (macho) {
return macho.GetInstallName(soname);
@@ -2334,9 +2364,9 @@ bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
return false;
}
-#if defined(CMAKE_USE_ELF_PARSER)
-std::string::size_type cmSystemToolsFindRPath(std::string const& have,
- std::string const& want)
+#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER)
+std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
+ cm::string_view const& want)
{
std::string::size_type pos = 0;
while (pos < have.size()) {
@@ -2368,7 +2398,7 @@ std::string::size_type cmSystemToolsFindRPath(std::string const& have,
}
#endif
-#if defined(CMAKE_USE_ELF_PARSER)
+#if defined(CMake_USE_ELF_PARSER)
struct cmSystemToolsRPathInfo
{
unsigned long Position;
@@ -2378,7 +2408,8 @@ struct cmSystemToolsRPathInfo
};
#endif
-#if defined(CMAKE_USE_ELF_PARSER)
+// 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,
@@ -2550,6 +2581,75 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
}
return true;
}
+#elif defined(CMake_USE_XCOFF_PARSER)
+bool cmSystemTools::ChangeRPath(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath, std::string* emsg,
+ bool* changed)
+{
+ if (changed) {
+ *changed = false;
+ }
+
+ bool chg = false;
+ cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite);
+ if (cm::optional<cm::string_view> maybeLibPath = xcoff.GetLibPath()) {
+ cm::string_view libPath = *maybeLibPath;
+ // Make sure the current rpath contains the old rpath.
+ std::string::size_type pos = cmSystemToolsFindRPath(libPath, oldRPath);
+ if (pos == std::string::npos) {
+ // If it contains the new rpath instead then it is okay.
+ if (cmSystemToolsFindRPath(libPath, newRPath) != std::string::npos) {
+ return true;
+ }
+ if (emsg) {
+ std::ostringstream e;
+ /* clang-format off */
+ e << "The current RPATH is:\n"
+ << " " << libPath << "\n"
+ << "which does not contain:\n"
+ << " " << oldRPath << "\n"
+ << "as was expected.";
+ /* clang-format on */
+ *emsg = e.str();
+ }
+ return false;
+ }
+
+ // The prefix is either empty or ends in a ':'.
+ cm::string_view prefix = libPath.substr(0, pos);
+ if (newRPath.empty() && !prefix.empty()) {
+ prefix.remove_suffix(1);
+ }
+
+ // The suffix is either empty or starts in a ':'.
+ cm::string_view suffix = libPath.substr(pos + oldRPath.length());
+
+ // Construct the new value which preserves the part of the path
+ // not being changed.
+ std::string newLibPath;
+ if (!removeEnvironmentRPath) {
+ newLibPath = std::string(prefix);
+ }
+ newLibPath += newRPath;
+ newLibPath += suffix;
+
+ chg = xcoff.SetLibPath(newLibPath);
+ }
+ if (!xcoff) {
+ if (emsg) {
+ *emsg = xcoff.GetErrorMessage();
+ }
+ return false;
+ }
+
+ // Everything was updated successfully.
+ if (changed) {
+ *changed = chg;
+ }
+ return true;
+}
#else
bool cmSystemTools::ChangeRPath(std::string const& /*file*/,
std::string const& /*oldRPath*/,
@@ -2694,7 +2794,8 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs)
return cm_strverscmp(lhs.c_str(), rhs.c_str());
}
-#if defined(CMAKE_USE_ELF_PARSER)
+// FIXME: Dispatch if multiple formats are supported.
+#if defined(CMake_USE_ELF_PARSER)
bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
bool* removed)
{
@@ -2835,6 +2936,28 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
}
return true;
}
+#elif defined(CMake_USE_XCOFF_PARSER)
+bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
+ bool* removed)
+{
+ if (removed) {
+ *removed = false;
+ }
+
+ cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite);
+ bool rm = xcoff.RemoveLibPath();
+ if (!xcoff) {
+ if (emsg) {
+ *emsg = xcoff.GetErrorMessage();
+ }
+ return false;
+ }
+
+ if (removed) {
+ *removed = rm;
+ }
+ return true;
+}
#else
bool cmSystemTools::RemoveRPath(std::string const& /*file*/,
std::string* /*emsg*/, bool* /*removed*/)
@@ -2843,10 +2966,11 @@ bool cmSystemTools::RemoveRPath(std::string const& /*file*/,
}
#endif
+// FIXME: Dispatch if multiple formats are supported.
bool cmSystemTools::CheckRPath(std::string const& file,
std::string const& newRPath)
{
-#if defined(CMAKE_USE_ELF_PARSER)
+#if defined(CMake_USE_ELF_PARSER)
// Parse the ELF binary.
cmELF elf(file.c_str());
@@ -2868,6 +2992,15 @@ bool cmSystemTools::CheckRPath(std::string const& file,
}
}
return false;
+#elif defined(CMake_USE_XCOFF_PARSER)
+ // Parse the XCOFF binary.
+ cmXCOFF xcoff(file.c_str());
+ if (cm::optional<cm::string_view> libPath = xcoff.GetLibPath()) {
+ if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) {
+ return true;
+ }
+ }
+ return false;
#else
(void)file;
(void)newRPath;
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 1100f05bd..5bbbb0c7b 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -287,6 +287,12 @@ public:
// running cmake needs paths to be in its format
static std::string ConvertToRunCommandPath(const std::string& path);
+ /**
+ * For windows computes the long path for the given path,
+ * For Unix, it is a noop
+ */
+ static void ConvertToLongPath(std::string& path);
+
/** compute the relative path from local to remote. local must
be a directory. remote can be a file or a directory.
Both remote and local must be full paths. Basically, if
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index bda2b30b1..91dcd0efc 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -209,11 +209,10 @@ public:
TLLCommands;
cmListFileBacktrace Backtrace;
-public:
bool CheckImportedLibName(std::string const& prop,
std::string const& value) const;
- std::string ProcessSourceItemCMP0049(const std::string& s);
+ std::string ProcessSourceItemCMP0049(const std::string& s) const;
};
namespace {
@@ -230,34 +229,35 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
: impl(cm::make_unique<cmTargetInternals>())
{
assert(mf);
- impl->TargetType = type;
- impl->Makefile = mf;
- impl->Name = name;
- impl->IsGeneratorProvided = false;
- impl->HaveInstallRule = false;
- impl->IsDLLPlatform = false;
- impl->IsAIX = false;
- impl->IsAndroid = false;
- impl->IsImportedTarget =
+ this->impl->TargetType = type;
+ this->impl->Makefile = mf;
+ this->impl->Name = name;
+ this->impl->IsGeneratorProvided = false;
+ this->impl->HaveInstallRule = false;
+ this->impl->IsDLLPlatform = false;
+ this->impl->IsAIX = false;
+ this->impl->IsAndroid = false;
+ this->impl->IsImportedTarget =
(vis == VisibilityImported || vis == VisibilityImportedGlobally);
- impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
- impl->BuildInterfaceIncludesAppended = false;
- impl->PerConfig = (perConfig == PerConfig::Yes);
+ this->impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
+ this->impl->BuildInterfaceIncludesAppended = false;
+ this->impl->PerConfig = (perConfig == PerConfig::Yes);
// Check whether this is a DLL platform.
- impl->IsDLLPlatform =
- !impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
+ this->impl->IsDLLPlatform =
+ !this->impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")
+ .empty();
// Check whether we are targeting AIX.
{
std::string const& systemName =
- impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
- impl->IsAIX = (systemName == "AIX" || systemName == "OS400");
+ this->impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
+ this->impl->IsAIX = (systemName == "AIX" || systemName == "OS400");
}
// Check whether we are targeting an Android platform.
- impl->IsAndroid =
- (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
+ this->impl->IsAndroid = (this->impl->Makefile->GetSafeDefinition(
+ "CMAKE_SYSTEM_NAME") == "Android");
std::string defKey;
defKey.reserve(128);
@@ -373,12 +373,16 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("ISPC_INSTRUCTION_SETS");
initProp("LINK_SEARCH_START_STATIC");
initProp("LINK_SEARCH_END_STATIC");
+ initProp("OBJC_CLANG_TIDY");
+ initProp("OBJCXX_CLANG_TIDY");
initProp("Swift_LANGUAGE_VERSION");
initProp("Swift_MODULE_DIRECTORY");
initProp("VS_JUST_MY_CODE_DEBUGGING");
initProp("DISABLE_PRECOMPILE_HEADERS");
initProp("UNITY_BUILD");
+ initProp("UNITY_BUILD_UNIQUE_ID");
initProp("OPTIMIZE_DEPENDENCIES");
+ initProp("EXPORT_COMPILE_COMMANDS");
initPropValue("UNITY_BUILD_BATCH_SIZE", "8");
initPropValue("UNITY_BUILD_MODE", "BATCH");
initPropValue("PCH_WARN_INVALID", "ON");
@@ -433,7 +437,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
for (auto const& prop : configProps) {
// Interface libraries have no output locations, so honor only
// the configuration map.
- if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY &&
+ if (this->impl->TargetType == cmStateEnums::INTERFACE_LIBRARY &&
strcmp(prop, "MAP_IMPORTED_CONFIG_") != 0) {
continue;
}
@@ -446,15 +450,15 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// compatibility with previous CMake versions in which executables
// did not support this variable. Projects may still specify the
// property directly.
- if (impl->TargetType != cmStateEnums::EXECUTABLE &&
- impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->impl->TargetType != cmStateEnums::EXECUTABLE &&
+ this->impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
std::string property =
cmStrCat(cmSystemTools::UpperCase(configName), "_POSTFIX");
initProp(property);
}
- if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
- impl->TargetType == cmStateEnums::STATIC_LIBRARY) {
+ if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
+ this->impl->TargetType == cmStateEnums::STATIC_LIBRARY) {
std::string property = cmStrCat("FRAMEWORK_MULTI_CONFIG_POSTFIX_",
cmSystemTools::UpperCase(configName));
initProp(property);
@@ -463,66 +467,67 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
}
// Save the backtrace of target construction.
- impl->Backtrace = impl->Makefile->GetBacktrace();
+ this->impl->Backtrace = this->impl->Makefile->GetBacktrace();
if (!this->IsImported()) {
// Initialize the INCLUDE_DIRECTORIES property based on the current value
// of the same directory property:
- cm::append(impl->IncludeDirectoriesEntries,
- impl->Makefile->GetIncludeDirectoriesEntries());
- cm::append(impl->IncludeDirectoriesBacktraces,
- impl->Makefile->GetIncludeDirectoriesBacktraces());
+ cm::append(this->impl->IncludeDirectoriesEntries,
+ this->impl->Makefile->GetIncludeDirectoriesEntries());
+ cm::append(this->impl->IncludeDirectoriesBacktraces,
+ this->impl->Makefile->GetIncludeDirectoriesBacktraces());
{
- auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories();
- impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end());
+ auto const& sysInc = this->impl->Makefile->GetSystemIncludeDirectories();
+ this->impl->SystemIncludeDirectories.insert(sysInc.begin(),
+ sysInc.end());
}
- cm::append(impl->CompileOptionsEntries,
- impl->Makefile->GetCompileOptionsEntries());
- cm::append(impl->CompileOptionsBacktraces,
- impl->Makefile->GetCompileOptionsBacktraces());
+ cm::append(this->impl->CompileOptionsEntries,
+ this->impl->Makefile->GetCompileOptionsEntries());
+ cm::append(this->impl->CompileOptionsBacktraces,
+ this->impl->Makefile->GetCompileOptionsBacktraces());
- cm::append(impl->LinkOptionsEntries,
- impl->Makefile->GetLinkOptionsEntries());
- cm::append(impl->LinkOptionsBacktraces,
- impl->Makefile->GetLinkOptionsBacktraces());
+ cm::append(this->impl->LinkOptionsEntries,
+ this->impl->Makefile->GetLinkOptionsEntries());
+ cm::append(this->impl->LinkOptionsBacktraces,
+ this->impl->Makefile->GetLinkOptionsBacktraces());
- cm::append(impl->LinkDirectoriesEntries,
- impl->Makefile->GetLinkDirectoriesEntries());
- cm::append(impl->LinkDirectoriesBacktraces,
- impl->Makefile->GetLinkDirectoriesBacktraces());
+ cm::append(this->impl->LinkDirectoriesEntries,
+ this->impl->Makefile->GetLinkDirectoriesEntries());
+ cm::append(this->impl->LinkDirectoriesBacktraces,
+ this->impl->Makefile->GetLinkDirectoriesBacktraces());
}
- if (impl->TargetType == cmStateEnums::EXECUTABLE) {
+ if (this->impl->TargetType == cmStateEnums::EXECUTABLE) {
initProp("ANDROID_GUI");
initProp("CROSSCOMPILING_EMULATOR");
initProp("ENABLE_EXPORTS");
}
- if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
- impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
+ if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
+ this->impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
} else if (this->CanCompileSources()) {
initProp("POSITION_INDEPENDENT_CODE");
}
- if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
- impl->TargetType == cmStateEnums::EXECUTABLE) {
+ if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
+ this->impl->TargetType == cmStateEnums::EXECUTABLE) {
initProp("AIX_EXPORT_ALL_SYMBOLS");
initProp("WINDOWS_EXPORT_ALL_SYMBOLS");
}
// Record current policies for later use.
- impl->Makefile->RecordPolicies(impl->PolicyMap);
+ this->impl->Makefile->RecordPolicies(this->impl->PolicyMap);
- if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->impl->TargetType == cmStateEnums::INTERFACE_LIBRARY) {
// This policy is checked in a few conditions. The properties relevant
// to the policy are always ignored for cmStateEnums::INTERFACE_LIBRARY
// targets,
// so ensure that the conditions don't lead to nonsense.
- impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
+ this->impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
}
- if (impl->TargetType <= cmStateEnums::GLOBAL_TARGET) {
+ if (this->impl->TargetType <= cmStateEnums::GLOBAL_TARGET) {
initProp("DOTNET_TARGET_FRAMEWORK");
initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
}
@@ -555,40 +560,40 @@ cmTarget& cmTarget::operator=(cmTarget&&) noexcept = default;
cmStateEnums::TargetType cmTarget::GetType() const
{
- return impl->TargetType;
+ return this->impl->TargetType;
}
cmMakefile* cmTarget::GetMakefile() const
{
- return impl->Makefile;
+ return this->impl->Makefile;
}
cmPolicies::PolicyMap const& cmTarget::GetPolicyMap() const
{
- return impl->PolicyMap;
+ return this->impl->PolicyMap;
}
const std::string& cmTarget::GetName() const
{
- return impl->Name;
+ return this->impl->Name;
}
cmPolicies::PolicyStatus cmTarget::GetPolicyStatus(
cmPolicies::PolicyID policy) const
{
- return impl->PolicyMap.Get(policy);
+ return this->impl->PolicyMap.Get(policy);
}
cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
{
- return impl->Makefile->GetGlobalGenerator();
+ return this->impl->Makefile->GetGlobalGenerator();
}
BTs<std::string> const* cmTarget::GetLanguageStandardProperty(
const std::string& propertyName) const
{
- auto entry = impl->LanguageStandardProperties.find(propertyName);
- if (entry != impl->LanguageStandardProperties.end()) {
+ auto entry = this->impl->LanguageStandardProperties.find(propertyName);
+ if (entry != this->impl->LanguageStandardProperties.end()) {
return &entry->second;
}
@@ -600,17 +605,17 @@ void cmTarget::SetLanguageStandardProperty(std::string const& lang,
const std::string& feature)
{
cmListFileBacktrace featureBacktrace;
- for (size_t i = 0; i < impl->CompileFeaturesEntries.size(); i++) {
- if (impl->CompileFeaturesEntries[i] == feature) {
- if (i < impl->CompileFeaturesBacktraces.size()) {
- featureBacktrace = impl->CompileFeaturesBacktraces[i];
+ for (size_t i = 0; i < this->impl->CompileFeaturesEntries.size(); i++) {
+ if (this->impl->CompileFeaturesEntries[i] == feature) {
+ if (i < this->impl->CompileFeaturesBacktraces.size()) {
+ featureBacktrace = this->impl->CompileFeaturesBacktraces[i];
}
break;
}
}
BTs<std::string>& languageStandardProperty =
- impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")];
+ this->impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")];
if (languageStandardProperty.Value != value) {
languageStandardProperty.Value = value;
languageStandardProperty.Backtraces.clear();
@@ -620,19 +625,24 @@ void cmTarget::SetLanguageStandardProperty(std::string const& lang,
void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf)
{
- impl->Utilities.insert(BT<std::pair<std::string, bool>>(
+ this->impl->Utilities.insert(BT<std::pair<std::string, bool>>(
{ name, cross }, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
}
+void cmTarget::AddUtility(BT<std::pair<std::string, bool>> util)
+{
+ this->impl->Utilities.emplace(std::move(util));
+}
+
std::set<BT<std::pair<std::string, bool>>> const& cmTarget::GetUtilities()
const
{
- return impl->Utilities;
+ return this->impl->Utilities;
}
cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
- return impl->Backtrace;
+ return this->impl->Backtrace;
}
bool cmTarget::IsExecutableWithExports() const
@@ -645,74 +655,74 @@ bool cmTarget::IsFrameworkOnApple() const
{
return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
- impl->Makefile->IsOn("APPLE") &&
+ this->impl->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("FRAMEWORK"));
}
bool cmTarget::IsAppBundleOnApple() const
{
return (this->GetType() == cmStateEnums::EXECUTABLE &&
- impl->Makefile->IsOn("APPLE") &&
+ this->impl->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("MACOSX_BUNDLE"));
}
bool cmTarget::IsAndroidGuiExecutable() const
{
- return (this->GetType() == cmStateEnums::EXECUTABLE && impl->IsAndroid &&
- this->GetPropertyAsBool("ANDROID_GUI"));
+ return (this->GetType() == cmStateEnums::EXECUTABLE &&
+ this->impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI"));
}
std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const
{
- return impl->PreBuildCommands;
+ return this->impl->PreBuildCommands;
}
void cmTarget::AddPreBuildCommand(cmCustomCommand const& cmd)
{
- impl->PreBuildCommands.push_back(cmd);
+ this->impl->PreBuildCommands.push_back(cmd);
}
void cmTarget::AddPreBuildCommand(cmCustomCommand&& cmd)
{
- impl->PreBuildCommands.push_back(std::move(cmd));
+ this->impl->PreBuildCommands.push_back(std::move(cmd));
}
std::vector<cmCustomCommand> const& cmTarget::GetPreLinkCommands() const
{
- return impl->PreLinkCommands;
+ return this->impl->PreLinkCommands;
}
void cmTarget::AddPreLinkCommand(cmCustomCommand const& cmd)
{
- impl->PreLinkCommands.push_back(cmd);
+ this->impl->PreLinkCommands.push_back(cmd);
}
void cmTarget::AddPreLinkCommand(cmCustomCommand&& cmd)
{
- impl->PreLinkCommands.push_back(std::move(cmd));
+ this->impl->PreLinkCommands.push_back(std::move(cmd));
}
std::vector<cmCustomCommand> const& cmTarget::GetPostBuildCommands() const
{
- return impl->PostBuildCommands;
+ return this->impl->PostBuildCommands;
}
void cmTarget::AddPostBuildCommand(cmCustomCommand const& cmd)
{
- impl->PostBuildCommands.push_back(cmd);
+ this->impl->PostBuildCommands.push_back(cmd);
}
void cmTarget::AddPostBuildCommand(cmCustomCommand&& cmd)
{
- impl->PostBuildCommands.push_back(std::move(cmd));
+ this->impl->PostBuildCommands.push_back(std::move(cmd));
}
void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
if (!srcs.empty()) {
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->SourceEntries.push_back(cmJoin(srcs, ";"));
- impl->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->SourceEntries.push_back(cmJoin(srcs, ";"));
+ this->impl->SourceBacktraces.push_back(lfbt);
}
}
@@ -723,25 +733,26 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
for (auto filename : srcs) {
if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
if (!filename.empty()) {
- filename = impl->ProcessSourceItemCMP0049(filename);
+ filename = this->impl->ProcessSourceItemCMP0049(filename);
if (filename.empty()) {
return;
}
}
- impl->Makefile->GetOrCreateSource(filename);
+ this->impl->Makefile->GetOrCreateSource(filename);
}
srcFiles += sep;
srcFiles += filename;
sep = ";";
}
if (!srcFiles.empty()) {
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->SourceEntries.push_back(std::move(srcFiles));
- impl->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->SourceEntries.push_back(std::move(srcFiles));
+ this->impl->SourceBacktraces.push_back(lfbt);
}
}
-std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
+std::string cmTargetInternals::ProcessSourceItemCMP0049(
+ const std::string& s) const
{
std::string src = s;
@@ -780,7 +791,7 @@ std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
std::string cmTarget::GetSourceCMP0049(const std::string& s)
{
- return impl->ProcessSourceItemCMP0049(s);
+ return this->impl->ProcessSourceItemCMP0049(s);
}
struct CreateLocation
@@ -792,7 +803,7 @@ struct CreateLocation
{
}
- cmSourceFileLocation operator()(const std::string& filename)
+ cmSourceFileLocation operator()(const std::string& filename) const
{
return cmSourceFileLocation(this->Makefile, filename);
}
@@ -839,26 +850,28 @@ public:
cmSourceFile* cmTarget::AddSource(const std::string& src, bool before)
{
- cmSourceFileLocation sfl(impl->Makefile, src,
+ cmSourceFileLocation sfl(this->impl->Makefile, src,
cmSourceFileLocationKind::Known);
- if (std::find_if(impl->SourceEntries.begin(), impl->SourceEntries.end(),
- TargetPropertyEntryFinder(sfl)) ==
- impl->SourceEntries.end()) {
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->SourceEntries.insert(
- before ? impl->SourceEntries.begin() : impl->SourceEntries.end(), src);
- impl->SourceBacktraces.insert(before ? impl->SourceBacktraces.begin()
- : impl->SourceBacktraces.end(),
- lfbt);
+ if (std::find_if(
+ this->impl->SourceEntries.begin(), this->impl->SourceEntries.end(),
+ TargetPropertyEntryFinder(sfl)) == this->impl->SourceEntries.end()) {
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->SourceEntries.insert(before ? this->impl->SourceEntries.begin()
+ : this->impl->SourceEntries.end(),
+ src);
+ this->impl->SourceBacktraces.insert(
+ before ? this->impl->SourceBacktraces.begin()
+ : this->impl->SourceBacktraces.end(),
+ lfbt);
}
if (cmGeneratorExpression::Find(src) != std::string::npos) {
return nullptr;
}
- return impl->Makefile->GetOrCreateSource(src, false,
- cmSourceFileLocationKind::Known);
+ return this->impl->Makefile->GetOrCreateSource(
+ src, false, cmSourceFileLocationKind::Known);
}
-void cmTarget::ClearDependencyInformation(cmMakefile& mf)
+void cmTarget::ClearDependencyInformation(cmMakefile& mf) const
{
std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS");
mf.RemoveCacheDefinition(depname);
@@ -873,7 +886,7 @@ std::string cmTarget::GetDebugGeneratorExpressions(
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> debugConfigs =
- impl->Makefile->GetCMakeInstance()->GetDebugConfigs();
+ this->impl->Makefile->GetCMakeInstance()->GetDebugConfigs();
std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
@@ -899,13 +912,14 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature,
cmListFileContext const& lfc)
{
bool ret = true;
- if (!impl->TLLCommands.empty()) {
- if (impl->TLLCommands.back().first != signature) {
+ if (!this->impl->TLLCommands.empty()) {
+ if (this->impl->TLLCommands.back().first != signature) {
ret = false;
}
}
- if (impl->TLLCommands.empty() || impl->TLLCommands.back().second != lfc) {
- impl->TLLCommands.emplace_back(signature, lfc);
+ if (this->impl->TLLCommands.empty() ||
+ this->impl->TLLCommands.back().second != lfc) {
+ this->impl->TLLCommands.emplace_back(signature, lfc);
}
return ret;
}
@@ -915,12 +929,13 @@ 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 = impl->Makefile->GetStateSnapshot().GetDirectory();
- for (auto const& cmd : impl->TLLCommands) {
+ 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(
- impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
+ this->impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
s << " * " << lfc << '\n';
}
}
@@ -928,59 +943,59 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
std::string const& cmTarget::GetInstallPath() const
{
- return impl->InstallPath;
+ return this->impl->InstallPath;
}
void cmTarget::SetInstallPath(std::string const& name)
{
- impl->InstallPath = name;
+ this->impl->InstallPath = name;
}
std::string const& cmTarget::GetRuntimeInstallPath() const
{
- return impl->RuntimeInstallPath;
+ return this->impl->RuntimeInstallPath;
}
void cmTarget::SetRuntimeInstallPath(std::string const& name)
{
- impl->RuntimeInstallPath = name;
+ this->impl->RuntimeInstallPath = name;
}
bool cmTarget::GetHaveInstallRule() const
{
- return impl->HaveInstallRule;
+ return this->impl->HaveInstallRule;
}
void cmTarget::SetHaveInstallRule(bool hir)
{
- impl->HaveInstallRule = hir;
+ this->impl->HaveInstallRule = hir;
}
void cmTarget::AddInstallGenerator(cmInstallTargetGenerator* g)
{
- impl->InstallGenerators.emplace_back(g);
+ this->impl->InstallGenerators.emplace_back(g);
}
std::vector<cmInstallTargetGenerator*> const& cmTarget::GetInstallGenerators()
const
{
- return impl->InstallGenerators;
+ return this->impl->InstallGenerators;
}
bool cmTarget::GetIsGeneratorProvided() const
{
- return impl->IsGeneratorProvided;
+ return this->impl->IsGeneratorProvided;
}
void cmTarget::SetIsGeneratorProvided(bool igp)
{
- impl->IsGeneratorProvided = igp;
+ this->impl->IsGeneratorProvided = igp;
}
cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries()
const
{
- return impl->OriginalLinkLibraries;
+ return this->impl->OriginalLinkLibraries;
}
void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
@@ -1002,11 +1017,11 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
(tgt &&
(tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
- (impl->Name == lib)) {
+ (this->impl->Name == lib)) {
return;
}
- impl->OriginalLinkLibraries.emplace_back(lib, llt);
+ this->impl->OriginalLinkLibraries.emplace_back(lib, llt);
// Add the explicit dependency information for libraries. This is
// simply a set of libraries separated by ";". There should always
@@ -1016,11 +1031,11 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
// may be purposefully duplicated to handle recursive dependencies,
// and we removing one instance will break the link line. Duplicates
// will be appropriately eliminated at emit time.
- if (impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
- impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
+ if (this->impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
+ this->impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
(this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
- std::string targetEntry = cmStrCat(impl->Name, "_LIB_DEPENDS");
+ std::string targetEntry = cmStrCat(this->impl->Name, "_LIB_DEPENDS");
std::string dependencies;
cmProp old_val = mf.GetDefinition(targetEntry);
if (old_val) {
@@ -1047,102 +1062,102 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
void cmTarget::AddSystemIncludeDirectories(const std::set<std::string>& incs)
{
- impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
+ this->impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
}
std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
{
- return impl->SystemIncludeDirectories;
+ return this->impl->SystemIncludeDirectories;
}
cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
- return cmMakeRange(impl->IncludeDirectoriesEntries);
+ return cmMakeRange(this->impl->IncludeDirectoriesEntries);
}
cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const
{
- return cmMakeRange(impl->IncludeDirectoriesBacktraces);
+ return cmMakeRange(this->impl->IncludeDirectoriesBacktraces);
}
cmStringRange cmTarget::GetCompileOptionsEntries() const
{
- return cmMakeRange(impl->CompileOptionsEntries);
+ return cmMakeRange(this->impl->CompileOptionsEntries);
}
cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const
{
- return cmMakeRange(impl->CompileOptionsBacktraces);
+ return cmMakeRange(this->impl->CompileOptionsBacktraces);
}
cmStringRange cmTarget::GetCompileFeaturesEntries() const
{
- return cmMakeRange(impl->CompileFeaturesEntries);
+ return cmMakeRange(this->impl->CompileFeaturesEntries);
}
cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const
{
- return cmMakeRange(impl->CompileFeaturesBacktraces);
+ return cmMakeRange(this->impl->CompileFeaturesBacktraces);
}
cmStringRange cmTarget::GetCompileDefinitionsEntries() const
{
- return cmMakeRange(impl->CompileDefinitionsEntries);
+ return cmMakeRange(this->impl->CompileDefinitionsEntries);
}
cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const
{
- return cmMakeRange(impl->CompileDefinitionsBacktraces);
+ return cmMakeRange(this->impl->CompileDefinitionsBacktraces);
}
cmStringRange cmTarget::GetPrecompileHeadersEntries() const
{
- return cmMakeRange(impl->PrecompileHeadersEntries);
+ return cmMakeRange(this->impl->PrecompileHeadersEntries);
}
cmBacktraceRange cmTarget::GetPrecompileHeadersBacktraces() const
{
- return cmMakeRange(impl->PrecompileHeadersBacktraces);
+ return cmMakeRange(this->impl->PrecompileHeadersBacktraces);
}
cmStringRange cmTarget::GetSourceEntries() const
{
- return cmMakeRange(impl->SourceEntries);
+ return cmMakeRange(this->impl->SourceEntries);
}
cmBacktraceRange cmTarget::GetSourceBacktraces() const
{
- return cmMakeRange(impl->SourceBacktraces);
+ return cmMakeRange(this->impl->SourceBacktraces);
}
cmStringRange cmTarget::GetLinkOptionsEntries() const
{
- return cmMakeRange(impl->LinkOptionsEntries);
+ return cmMakeRange(this->impl->LinkOptionsEntries);
}
cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const
{
- return cmMakeRange(impl->LinkOptionsBacktraces);
+ return cmMakeRange(this->impl->LinkOptionsBacktraces);
}
cmStringRange cmTarget::GetLinkDirectoriesEntries() const
{
- return cmMakeRange(impl->LinkDirectoriesEntries);
+ return cmMakeRange(this->impl->LinkDirectoriesEntries);
}
cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const
{
- return cmMakeRange(impl->LinkDirectoriesBacktraces);
+ return cmMakeRange(this->impl->LinkDirectoriesBacktraces);
}
cmStringRange cmTarget::GetLinkImplementationEntries() const
{
- return cmMakeRange(impl->LinkImplementationPropertyEntries);
+ return cmMakeRange(this->impl->LinkImplementationPropertyEntries);
}
cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
{
- return cmMakeRange(impl->LinkImplementationPropertyBacktraces);
+ return cmMakeRange(this->impl->LinkImplementationPropertyBacktraces);
}
void cmTarget::SetProperty(const std::string& prop, const char* value)
@@ -1171,154 +1186,154 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
MAKE_STATIC_PROP(TYPE);
#undef MAKE_STATIC_PROP
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
- impl->Makefile->IssueMessage(
+ this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"MANUALLY_ADDED_DEPENDENCIES property is read-only\n");
return;
}
if (prop == propNAME) {
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
- "NAME property is read-only\n");
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "NAME property is read-only\n");
return;
}
if (prop == propTYPE) {
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
- "TYPE property is read-only\n");
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "TYPE property is read-only\n");
return;
}
if (prop == propEXPORT_NAME && this->IsImported()) {
std::ostringstream e;
e << "EXPORT_NAME property can't be set on imported targets (\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propSOURCES && this->IsImported()) {
std::ostringstream e;
- e << "SOURCES property can't be set on imported targets (\"" << impl->Name
- << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ e << "SOURCES property can't be set on imported targets (\""
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propIMPORTED_GLOBAL && !this->IsImported()) {
std::ostringstream e;
e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == propINCLUDE_DIRECTORIES) {
- impl->IncludeDirectoriesEntries.clear();
- impl->IncludeDirectoriesBacktraces.clear();
+ this->impl->IncludeDirectoriesEntries.clear();
+ this->impl->IncludeDirectoriesBacktraces.clear();
if (value) {
- impl->IncludeDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->IncludeDirectoriesBacktraces.push_back(lfbt);
+ this->impl->IncludeDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->IncludeDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == propCOMPILE_OPTIONS) {
- impl->CompileOptionsEntries.clear();
- impl->CompileOptionsBacktraces.clear();
+ this->impl->CompileOptionsEntries.clear();
+ this->impl->CompileOptionsBacktraces.clear();
if (value) {
- impl->CompileOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->CompileOptionsBacktraces.push_back(lfbt);
+ this->impl->CompileOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->CompileOptionsBacktraces.push_back(lfbt);
}
} else if (prop == propCOMPILE_FEATURES) {
- impl->CompileFeaturesEntries.clear();
- impl->CompileFeaturesBacktraces.clear();
+ this->impl->CompileFeaturesEntries.clear();
+ this->impl->CompileFeaturesBacktraces.clear();
if (value) {
- impl->CompileFeaturesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->CompileFeaturesBacktraces.push_back(lfbt);
+ this->impl->CompileFeaturesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->CompileFeaturesBacktraces.push_back(lfbt);
}
} else if (prop == propCOMPILE_DEFINITIONS) {
- impl->CompileDefinitionsEntries.clear();
- impl->CompileDefinitionsBacktraces.clear();
+ this->impl->CompileDefinitionsEntries.clear();
+ this->impl->CompileDefinitionsBacktraces.clear();
if (value) {
- impl->CompileDefinitionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->CompileDefinitionsBacktraces.push_back(lfbt);
+ this->impl->CompileDefinitionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->CompileDefinitionsBacktraces.push_back(lfbt);
}
} else if (prop == propLINK_OPTIONS) {
- impl->LinkOptionsEntries.clear();
- impl->LinkOptionsBacktraces.clear();
+ this->impl->LinkOptionsEntries.clear();
+ this->impl->LinkOptionsBacktraces.clear();
if (value) {
- impl->LinkOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->LinkOptionsBacktraces.push_back(lfbt);
+ this->impl->LinkOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkOptionsBacktraces.push_back(lfbt);
}
} else if (prop == propLINK_DIRECTORIES) {
- impl->LinkDirectoriesEntries.clear();
- impl->LinkDirectoriesBacktraces.clear();
+ this->impl->LinkDirectoriesEntries.clear();
+ this->impl->LinkDirectoriesBacktraces.clear();
if (value) {
- impl->LinkDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->LinkDirectoriesBacktraces.push_back(lfbt);
+ this->impl->LinkDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == propPRECOMPILE_HEADERS) {
- impl->PrecompileHeadersEntries.clear();
- impl->PrecompileHeadersBacktraces.clear();
+ this->impl->PrecompileHeadersEntries.clear();
+ this->impl->PrecompileHeadersBacktraces.clear();
if (value) {
- impl->PrecompileHeadersEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->PrecompileHeadersBacktraces.push_back(lfbt);
+ this->impl->PrecompileHeadersEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->PrecompileHeadersBacktraces.push_back(lfbt);
}
} else if (prop == propLINK_LIBRARIES) {
- impl->LinkImplementationPropertyEntries.clear();
- impl->LinkImplementationPropertyBacktraces.clear();
+ this->impl->LinkImplementationPropertyEntries.clear();
+ this->impl->LinkImplementationPropertyBacktraces.clear();
if (value) {
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->LinkImplementationPropertyEntries.emplace_back(value);
- impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkImplementationPropertyEntries.emplace_back(value);
+ this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
} else if (prop == propSOURCES) {
- impl->SourceEntries.clear();
- impl->SourceBacktraces.clear();
+ this->impl->SourceEntries.clear();
+ this->impl->SourceBacktraces.clear();
if (value) {
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->SourceEntries.emplace_back(value);
- impl->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->SourceEntries.emplace_back(value);
+ this->impl->SourceBacktraces.push_back(lfbt);
}
} else if (prop == propIMPORTED_GLOBAL) {
if (!cmIsOn(value)) {
std::ostringstream e;
e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
/* no need to change anything if value does not change */
- if (!impl->ImportedGloballyVisible) {
- impl->ImportedGloballyVisible = true;
+ if (!this->impl->ImportedGloballyVisible) {
+ this->impl->ImportedGloballyVisible = true;
this->GetGlobalGenerator()->IndexTarget(this);
}
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
- !impl->CheckImportedLibName(prop, value ? value : "")) {
+ !this->impl->CheckImportedLibName(prop, value ? value : "")) {
/* error was reported by check method */
} else if (prop == propCUDA_PTX_COMPILATION &&
this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT "
"targets (\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
} else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) {
if (this->GetProperty("PRECOMPILE_HEADERS")) {
std::ostringstream e;
e << "PRECOMPILE_HEADERS property is already set on target (\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
- auto reusedTarget =
- impl->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
- value);
+ auto* reusedTarget = this->impl->Makefile->GetCMakeInstance()
+ ->GetGlobalGenerator()
+ ->FindTarget(value);
if (!reusedTarget) {
const std::string e(
"PRECOMPILE_HEADERS_REUSE_FROM set with non existing target");
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
return;
}
@@ -1327,7 +1342,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
reusedFrom = value;
}
- impl->Properties.SetProperty(prop, reusedFrom.c_str());
+ this->impl->Properties.SetProperty(prop, reusedFrom.c_str());
reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom);
reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
@@ -1335,18 +1350,18 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME");
this->SetProperty("COMPILE_PDB_NAME", cmToCStr(tmp));
- this->AddUtility(reusedFrom, false, impl->Makefile);
+ this->AddUtility(reusedFrom, false, this->impl->Makefile);
} else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
prop == propCUDA_STANDARD || prop == propOBJC_STANDARD ||
prop == propOBJCXX_STANDARD) {
if (value) {
- impl->LanguageStandardProperties[prop] =
- BTs<std::string>(value, impl->Makefile->GetBacktrace());
+ this->impl->LanguageStandardProperties[prop] =
+ BTs<std::string>(value, this->impl->Makefile->GetBacktrace());
} else {
- impl->LanguageStandardProperties.erase(prop);
+ this->impl->LanguageStandardProperties.erase(prop);
}
} else {
- impl->Properties.SetProperty(prop, value);
+ this->impl->Properties.SetProperty(prop, value);
}
}
@@ -1354,102 +1369,102 @@ void cmTarget::AppendProperty(const std::string& prop,
const std::string& value, bool asString)
{
if (prop == "NAME") {
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
- "NAME property is read-only\n");
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "NAME property is read-only\n");
return;
}
if (prop == "EXPORT_NAME" && this->IsImported()) {
std::ostringstream e;
e << "EXPORT_NAME property can't be set on imported targets (\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "SOURCES" && this->IsImported()) {
std::ostringstream e;
- e << "SOURCES property can't be set on imported targets (\"" << impl->Name
- << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ e << "SOURCES property can't be set on imported targets (\""
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "IMPORTED_GLOBAL") {
std::ostringstream e;
e << "IMPORTED_GLOBAL property can't be appended, only set on imported "
"targets (\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "INCLUDE_DIRECTORIES") {
if (!value.empty()) {
- impl->IncludeDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->IncludeDirectoriesBacktraces.push_back(lfbt);
+ this->impl->IncludeDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->IncludeDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_OPTIONS") {
if (!value.empty()) {
- impl->CompileOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->CompileOptionsBacktraces.push_back(lfbt);
+ this->impl->CompileOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->CompileOptionsBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_FEATURES") {
if (!value.empty()) {
- impl->CompileFeaturesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->CompileFeaturesBacktraces.push_back(lfbt);
+ this->impl->CompileFeaturesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->CompileFeaturesBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_DEFINITIONS") {
if (!value.empty()) {
- impl->CompileDefinitionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->CompileDefinitionsBacktraces.push_back(lfbt);
+ this->impl->CompileDefinitionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->CompileDefinitionsBacktraces.push_back(lfbt);
}
} else if (prop == "LINK_OPTIONS") {
if (!value.empty()) {
- impl->LinkOptionsEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->LinkOptionsBacktraces.push_back(lfbt);
+ this->impl->LinkOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkOptionsBacktraces.push_back(lfbt);
}
} else if (prop == "LINK_DIRECTORIES") {
if (!value.empty()) {
- impl->LinkDirectoriesEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->LinkDirectoriesBacktraces.push_back(lfbt);
+ this->impl->LinkDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == "PRECOMPILE_HEADERS") {
if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
std::ostringstream e;
e << "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target "
"(\""
- << impl->Name << "\")\n";
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ << this->impl->Name << "\")\n";
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (!value.empty()) {
- impl->PrecompileHeadersEntries.emplace_back(value);
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->PrecompileHeadersBacktraces.push_back(lfbt);
+ this->impl->PrecompileHeadersEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->PrecompileHeadersBacktraces.push_back(lfbt);
}
} else if (prop == "LINK_LIBRARIES") {
if (!value.empty()) {
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->LinkImplementationPropertyEntries.emplace_back(value);
- impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkImplementationPropertyEntries.emplace_back(value);
+ this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
} else if (prop == "SOURCES") {
- cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
- impl->SourceEntries.emplace_back(value);
- impl->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->SourceEntries.emplace_back(value);
+ this->impl->SourceBacktraces.push_back(lfbt);
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
- prop + " property may not be APPENDed.");
+ 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") {
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
- prop + " property may not be appended.");
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR, prop + " property may not be appended.");
} else {
- impl->Properties.AppendProperty(prop, value, asString);
+ this->impl->Properties.AppendProperty(prop, value, asString);
}
}
@@ -1462,17 +1477,17 @@ void cmTarget::AppendBuildInterfaceIncludes()
!this->IsExecutableWithExports()) {
return;
}
- if (impl->BuildInterfaceIncludesAppended) {
+ if (this->impl->BuildInterfaceIncludesAppended) {
return;
}
- impl->BuildInterfaceIncludesAppended = true;
+ this->impl->BuildInterfaceIncludesAppended = true;
- if (impl->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
- std::string dirs = impl->Makefile->GetCurrentBinaryDirectory();
+ if (this->impl->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
+ std::string dirs = this->impl->Makefile->GetCurrentBinaryDirectory();
if (!dirs.empty()) {
dirs += ';';
}
- dirs += impl->Makefile->GetCurrentSourceDirectory();
+ dirs += this->impl->Makefile->GetCurrentSourceDirectory();
if (!dirs.empty()) {
this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
("$<BUILD_INTERFACE:" + dirs + ">"));
@@ -1483,67 +1498,67 @@ void cmTarget::AppendBuildInterfaceIncludes()
void cmTarget::InsertInclude(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
- auto position = before ? impl->IncludeDirectoriesEntries.begin()
- : impl->IncludeDirectoriesEntries.end();
+ auto position = before ? this->impl->IncludeDirectoriesEntries.begin()
+ : this->impl->IncludeDirectoriesEntries.end();
- auto btPosition = before ? impl->IncludeDirectoriesBacktraces.begin()
- : impl->IncludeDirectoriesBacktraces.end();
+ auto btPosition = before ? this->impl->IncludeDirectoriesBacktraces.begin()
+ : this->impl->IncludeDirectoriesBacktraces.end();
- impl->IncludeDirectoriesEntries.insert(position, entry);
- impl->IncludeDirectoriesBacktraces.insert(btPosition, bt);
+ this->impl->IncludeDirectoriesEntries.insert(position, entry);
+ this->impl->IncludeDirectoriesBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertCompileOption(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
- auto position = before ? impl->CompileOptionsEntries.begin()
- : impl->CompileOptionsEntries.end();
+ auto position = before ? this->impl->CompileOptionsEntries.begin()
+ : this->impl->CompileOptionsEntries.end();
- auto btPosition = before ? impl->CompileOptionsBacktraces.begin()
- : impl->CompileOptionsBacktraces.end();
+ auto btPosition = before ? this->impl->CompileOptionsBacktraces.begin()
+ : this->impl->CompileOptionsBacktraces.end();
- impl->CompileOptionsEntries.insert(position, entry);
- impl->CompileOptionsBacktraces.insert(btPosition, bt);
+ this->impl->CompileOptionsEntries.insert(position, entry);
+ this->impl->CompileOptionsBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertCompileDefinition(std::string const& entry,
cmListFileBacktrace const& bt)
{
- impl->CompileDefinitionsEntries.push_back(entry);
- impl->CompileDefinitionsBacktraces.push_back(bt);
+ this->impl->CompileDefinitionsEntries.push_back(entry);
+ this->impl->CompileDefinitionsBacktraces.push_back(bt);
}
void cmTarget::InsertLinkOption(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
- auto position =
- before ? impl->LinkOptionsEntries.begin() : impl->LinkOptionsEntries.end();
+ auto position = before ? this->impl->LinkOptionsEntries.begin()
+ : this->impl->LinkOptionsEntries.end();
- auto btPosition = before ? impl->LinkOptionsBacktraces.begin()
- : impl->LinkOptionsBacktraces.end();
+ auto btPosition = before ? this->impl->LinkOptionsBacktraces.begin()
+ : this->impl->LinkOptionsBacktraces.end();
- impl->LinkOptionsEntries.insert(position, entry);
- impl->LinkOptionsBacktraces.insert(btPosition, bt);
+ this->impl->LinkOptionsEntries.insert(position, entry);
+ this->impl->LinkOptionsBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertLinkDirectory(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
- auto position = before ? impl->LinkDirectoriesEntries.begin()
- : impl->LinkDirectoriesEntries.end();
+ auto position = before ? this->impl->LinkDirectoriesEntries.begin()
+ : this->impl->LinkDirectoriesEntries.end();
- auto btPosition = before ? impl->LinkDirectoriesBacktraces.begin()
- : impl->LinkDirectoriesBacktraces.end();
+ auto btPosition = before ? this->impl->LinkDirectoriesBacktraces.begin()
+ : this->impl->LinkDirectoriesBacktraces.end();
- impl->LinkDirectoriesEntries.insert(position, entry);
- impl->LinkDirectoriesBacktraces.insert(btPosition, bt);
+ this->impl->LinkDirectoriesEntries.insert(position, entry);
+ this->impl->LinkDirectoriesBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertPrecompileHeader(std::string const& entry,
cmListFileBacktrace const& bt)
{
- impl->PrecompileHeadersEntries.push_back(entry);
- impl->PrecompileHeadersBacktraces.push_back(bt);
+ this->impl->PrecompileHeadersEntries.push_back(entry);
+ this->impl->PrecompileHeadersBacktraces.push_back(bt);
}
static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
@@ -1712,19 +1727,19 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
prop == propCUDA_STANDARD || prop == propOBJC_STANDARD ||
prop == propOBJCXX_STANDARD) {
- auto propertyIter = impl->LanguageStandardProperties.find(prop);
- if (propertyIter == impl->LanguageStandardProperties.end()) {
+ auto propertyIter = this->impl->LanguageStandardProperties.find(prop);
+ if (propertyIter == this->impl->LanguageStandardProperties.end()) {
return nullptr;
}
return &(propertyIter->second.Value);
}
if (prop == propLINK_LIBRARIES) {
- if (impl->LinkImplementationPropertyEntries.empty()) {
+ if (this->impl->LinkImplementationPropertyEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->LinkImplementationPropertyEntries, ";");
+ output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";");
return &output;
}
// the type property returns what type the target is
@@ -1732,70 +1747,71 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
return &cmState::GetTargetTypeName(this->GetType());
}
if (prop == propINCLUDE_DIRECTORIES) {
- if (impl->IncludeDirectoriesEntries.empty()) {
+ if (this->impl->IncludeDirectoriesEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->IncludeDirectoriesEntries, ";");
+ output = cmJoin(this->impl->IncludeDirectoriesEntries, ";");
return &output;
}
if (prop == propCOMPILE_FEATURES) {
- if (impl->CompileFeaturesEntries.empty()) {
+ if (this->impl->CompileFeaturesEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->CompileFeaturesEntries, ";");
+ output = cmJoin(this->impl->CompileFeaturesEntries, ";");
return &output;
}
if (prop == propCOMPILE_OPTIONS) {
- if (impl->CompileOptionsEntries.empty()) {
+ if (this->impl->CompileOptionsEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->CompileOptionsEntries, ";");
+ output = cmJoin(this->impl->CompileOptionsEntries, ";");
return &output;
}
if (prop == propCOMPILE_DEFINITIONS) {
- if (impl->CompileDefinitionsEntries.empty()) {
+ if (this->impl->CompileDefinitionsEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->CompileDefinitionsEntries, ";");
+ output = cmJoin(this->impl->CompileDefinitionsEntries, ";");
return &output;
}
if (prop == propLINK_OPTIONS) {
- if (impl->LinkOptionsEntries.empty()) {
+ if (this->impl->LinkOptionsEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->LinkOptionsEntries, ";");
+ output = cmJoin(this->impl->LinkOptionsEntries, ";");
return &output;
}
if (prop == propLINK_DIRECTORIES) {
- if (impl->LinkDirectoriesEntries.empty()) {
+ if (this->impl->LinkDirectoriesEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->LinkDirectoriesEntries, ";");
+ output = cmJoin(this->impl->LinkDirectoriesEntries, ";");
return &output;
}
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
- if (impl->Utilities.empty()) {
+ if (this->impl->Utilities.empty()) {
return nullptr;
}
static std::string output;
static std::vector<std::string> utilities;
- utilities.resize(impl->Utilities.size());
+ utilities.resize(this->impl->Utilities.size());
std::transform(
- impl->Utilities.cbegin(), impl->Utilities.cend(), utilities.begin(),
+ this->impl->Utilities.cbegin(), this->impl->Utilities.cend(),
+ utilities.begin(),
[](const BT<std::pair<std::string, bool>>& item) -> std::string {
return item.Value.first;
});
@@ -1803,12 +1819,12 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
return &output;
}
if (prop == propPRECOMPILE_HEADERS) {
- if (impl->PrecompileHeadersEntries.empty()) {
+ if (this->impl->PrecompileHeadersEntries.empty()) {
return nullptr;
}
static std::string output;
- output = cmJoin(impl->PrecompileHeadersEntries, ";");
+ output = cmJoin(this->impl->PrecompileHeadersEntries, ";");
return &output;
}
if (prop == propIMPORTED) {
@@ -1821,24 +1837,25 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
return &this->GetName();
}
if (prop == propBINARY_DIR) {
- return &impl->Makefile->GetStateSnapshot()
+ return &this->impl->Makefile->GetStateSnapshot()
.GetDirectory()
.GetCurrentBinary();
}
if (prop == propSOURCE_DIR) {
- return &impl->Makefile->GetStateSnapshot()
+ return &this->impl->Makefile->GetStateSnapshot()
.GetDirectory()
.GetCurrentSource();
}
}
- cmProp retVal = impl->Properties.GetPropertyValue(prop);
+ cmProp retVal = this->impl->Properties.GetPropertyValue(prop);
if (!retVal) {
- const bool chain =
- impl->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TARGET);
+ const bool chain = this->impl->Makefile->GetState()->IsPropertyChained(
+ prop, cmProperty::TARGET);
if (chain) {
- return impl->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
- prop, chain);
+ return this->impl->Makefile->GetStateSnapshot()
+ .GetDirectory()
+ .GetProperty(prop, chain);
}
return nullptr;
}
@@ -1863,32 +1880,32 @@ bool cmTarget::GetPropertyAsBool(const std::string& prop) const
cmPropertyMap const& cmTarget::GetProperties() const
{
- return impl->Properties;
+ return this->impl->Properties;
}
bool cmTarget::IsDLLPlatform() const
{
- return impl->IsDLLPlatform;
+ return this->impl->IsDLLPlatform;
}
bool cmTarget::IsAIX() const
{
- return impl->IsAIX;
+ return this->impl->IsAIX;
}
bool cmTarget::IsImported() const
{
- return impl->IsImportedTarget;
+ return this->impl->IsImportedTarget;
}
bool cmTarget::IsImportedGloballyVisible() const
{
- return impl->ImportedGloballyVisible;
+ return this->impl->ImportedGloballyVisible;
}
bool cmTarget::IsPerConfig() const
{
- return impl->PerConfig;
+ return this->impl->PerConfig;
}
bool cmTarget::CanCompileSources() const
@@ -1943,8 +1960,8 @@ const char* cmTarget::GetSuffixVariableInternal(
? "CMAKE_SHARED_LIBRARY_SUFFIX"
: "CMAKE_EXECUTABLE_SUFFIX");
case cmStateEnums::ImportLibraryArtifact:
- return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_SUFFIX"
- : "CMAKE_IMPORT_LIBRARY_SUFFIX");
+ return (this->impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_SUFFIX"
+ : "CMAKE_IMPORT_LIBRARY_SUFFIX");
}
break;
default:
@@ -1984,8 +2001,8 @@ const char* cmTarget::GetPrefixVariableInternal(
? "CMAKE_SHARED_LIBRARY_PREFIX"
: "");
case cmStateEnums::ImportLibraryArtifact:
- return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_PREFIX"
- : "CMAKE_IMPORT_LIBRARY_PREFIX");
+ return (this->impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_PREFIX"
+ : "CMAKE_IMPORT_LIBRARY_PREFIX");
}
break;
default:
@@ -2067,7 +2084,7 @@ std::string cmTarget::ImportedGetFullPath(
switch (this->GetPolicyStatus(cmPolicies::CMP0111)) {
case cmPolicies::WARN:
- impl->Makefile->IssueMessage(
+ this->impl->Makefile->IssueMessage(
MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0111) + "\n" +
message());
@@ -2075,7 +2092,8 @@ std::string cmTarget::ImportedGetFullPath(
case cmPolicies::OLD:
break;
default:
- impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, message());
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ message());
}
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index d8f66bcf1..30d9f5d06 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -114,7 +114,7 @@ public:
LinkLibraryVectorType const& GetOriginalLinkLibraries() const;
//! Clear the dependency information recorded for this target, if any.
- void ClearDependencyInformation(cmMakefile& mf);
+ void ClearDependencyInformation(cmMakefile& mf) const;
void AddLinkLibrary(cmMakefile& mf, std::string const& lib,
cmTargetLinkLibraryType llt);
@@ -164,6 +164,7 @@ public:
*/
void AddUtility(std::string const& name, bool cross,
cmMakefile* mf = nullptr);
+ void AddUtility(BT<std::pair<std::string, bool>> util);
//! Get the utilities used by this target
std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
@@ -171,7 +172,7 @@ public:
void SetProperty(const std::string& prop, const char* value);
void SetProperty(const std::string& prop, const std::string& value)
{
- SetProperty(prop, value.c_str());
+ this->SetProperty(prop, value.c_str());
}
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
@@ -287,6 +288,5 @@ private:
const char* GetPrefixVariableInternal(
cmStateEnums::ArtifactType artifact) const;
-private:
std::unique_ptr<cmTargetInternals> impl;
};
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index 35635b94b..3897499f3 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -84,8 +84,8 @@ void TargetIncludeDirectoriesImpl::HandleInterfaceContent(
cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
bool system)
{
- cmTargetPropCommandBase::HandleInterfaceContent(tgt, content, prepend,
- system);
+ this->cmTargetPropCommandBase::HandleInterfaceContent(tgt, content, prepend,
+ system);
if (system) {
std::string joined = this->Join(content);
tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined);
@@ -101,5 +101,6 @@ bool cmTargetIncludeDirectoriesCommand(std::vector<std::string> const& args,
args, "INCLUDE_DIRECTORIES",
TargetIncludeDirectoriesImpl::ArgumentFlags(
TargetIncludeDirectoriesImpl::PROCESS_BEFORE |
+ TargetIncludeDirectoriesImpl::PROCESS_AFTER |
TargetIncludeDirectoriesImpl::PROCESS_SYSTEM));
}
diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx
index 0670bd962..a5066cc2a 100644
--- a/Source/cmTargetPrecompileHeadersCommand.cxx
+++ b/Source/cmTargetPrecompileHeadersCommand.cxx
@@ -57,7 +57,7 @@ private:
bool prepend, bool system) override
{
std::string const& base = this->Makefile->GetCurrentSourceDirectory();
- cmTargetPropCommandBase::HandleInterfaceContent(
+ this->cmTargetPropCommandBase::HandleInterfaceContent(
tgt, ConvertToAbsoluteContent(content, base), prepend, system);
}
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 9e301360a..e41714aba 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -45,15 +45,26 @@ bool cmTargetPropCommandBase::HandleArguments(
this->HandleMissingTarget(args[0]);
return false;
}
- if ((this->Target->GetType() != cmStateEnums::EXECUTABLE) &&
- (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) &&
- (this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
- (this->Target->GetType() != cmStateEnums::MODULE_LIBRARY) &&
- (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
- (this->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
- (this->Target->GetType() != cmStateEnums::UNKNOWN_LIBRARY)) {
- this->SetError("called with non-compilable target type");
- return false;
+ const bool isRegularTarget =
+ (this->Target->GetType() == cmStateEnums::EXECUTABLE) ||
+ (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY);
+ const bool isCustomTarget = this->Target->GetType() == cmStateEnums::UTILITY;
+
+ if (prop == "SOURCES") {
+ if (!isRegularTarget && !isCustomTarget) {
+ this->SetError("called with non-compilable target type");
+ return false;
+ }
+ } else {
+ if (!isRegularTarget) {
+ this->SetError("called with non-compilable target type");
+ return false;
+ }
}
bool system = false;
@@ -76,6 +87,13 @@ bool cmTargetPropCommandBase::HandleArguments(
}
prepend = true;
++argIndex;
+ } else if ((flags & PROCESS_AFTER) && args[argIndex] == "AFTER") {
+ if (args.size() < 3) {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ prepend = false;
+ ++argIndex;
}
if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") {
@@ -131,6 +149,11 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
this->SetError("may only set INTERFACE properties on IMPORTED targets");
return false;
}
+ if (this->Target->GetType() == cmStateEnums::UTILITY &&
+ scope != "PRIVATE") {
+ this->SetError("may only set PRIVATE properties on custom targets");
+ return false;
+ }
}
return this->PopulateTargetProperies(scope, content, prepend, system);
}
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 50ac1aaa3..fc24fe8ee 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -23,8 +23,9 @@ public:
{
NO_FLAGS = 0x0,
PROCESS_BEFORE = 0x1,
- PROCESS_SYSTEM = 0x2,
- PROCESS_REUSE_FROM = 0x3
+ PROCESS_AFTER = 0x2,
+ PROCESS_SYSTEM = 0x3,
+ PROCESS_REUSE_FROM = 0x4
};
bool HandleArguments(std::vector<std::string> const& args,
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index a1fbc9b9b..26282effb 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -25,8 +25,9 @@ protected:
const std::vector<std::string>& content,
bool prepend, bool system) override
{
- cmTargetPropCommandBase::HandleInterfaceContent(
- tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system);
+ this->cmTargetPropCommandBase::HandleInterfaceContent(
+ tgt, this->ConvertToAbsoluteContent(tgt, content, true), prepend,
+ system);
}
private:
@@ -43,7 +44,8 @@ private:
bool /*prepend*/, bool /*system*/) override
{
tgt->AppendProperty(
- "SOURCES", this->Join(ConvertToAbsoluteContent(tgt, content, false)));
+ "SOURCES",
+ this->Join(this->ConvertToAbsoluteContent(tgt, content, false)));
return true; // Successfully handled.
}
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index da4593f67..7022c4eb1 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -147,7 +147,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Evaluate command line arguments
std::vector<std::string> argv =
- EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config);
+ this->EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config);
// Expand arguments if COMMAND_EXPAND_LISTS is set
if (this->Test->GetCommandExpandLists()) {
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 67f7e1146..b01653009 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -3,11 +3,13 @@
#if !defined(_WIN32) && !defined(__sun)
// POSIX APIs are needed
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _POSIX_C_SOURCE 200809L
#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__QNX__)
// For isascii
+// NOLINTNEXTLINE(bugprone-reserved-identifier)
# define _XOPEN_SOURCE 700
#endif
@@ -21,7 +23,7 @@
#include "cmSystemTools.h"
std::string cmTimestamp::CurrentTime(const std::string& formatString,
- bool utcFlag)
+ bool utcFlag) const
{
time_t currentTimeT = time(nullptr);
std::string source_date_epoch;
@@ -38,12 +40,12 @@ std::string cmTimestamp::CurrentTime(const std::string& formatString,
return std::string();
}
- return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
+ return this->CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
}
std::string cmTimestamp::FileModificationTime(const char* path,
const std::string& formatString,
- bool utcFlag)
+ bool utcFlag) const
{
std::string real_path =
cmSystemTools::GetRealPathResolvingWindowsSubst(path);
@@ -53,7 +55,7 @@ std::string cmTimestamp::FileModificationTime(const char* path,
}
time_t mtime = cmsys::SystemTools::ModifiedTime(real_path);
- return CreateTimestampFromTimeT(mtime, formatString, utcFlag);
+ return this->CreateTimestampFromTimeT(mtime, formatString, utcFlag);
}
std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
@@ -90,7 +92,7 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
: static_cast<char>(0);
if (c1 == '%' && c2 != 0) {
- result += AddTimestampComponent(c2, timeStruct, timeT);
+ result += this->AddTimestampComponent(c2, timeStruct, timeT);
++i;
} else {
result += c1;
diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h
index 8941abe1c..0e2c20006 100644
--- a/Source/cmTimestamp.h
+++ b/Source/cmTimestamp.h
@@ -14,11 +14,11 @@
class cmTimestamp
{
public:
- std::string CurrentTime(const std::string& formatString, bool utcFlag);
+ std::string CurrentTime(const std::string& formatString, bool utcFlag) const;
std::string FileModificationTime(const char* path,
const std::string& formatString,
- bool utcFlag);
+ bool utcFlag) const;
std::string CreateTimestampFromTimeT(time_t timeT, std::string formatString,
bool utcFlag) const;
diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx
new file mode 100644
index 000000000..78aa4b2df
--- /dev/null
+++ b/Source/cmTransformDepfile.cxx
@@ -0,0 +1,122 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTransformDepfile.h"
+
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include <cm/optional>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmGccDepfileReader.h"
+#include "cmGccDepfileReaderTypes.h"
+#include "cmLocalGenerator.h"
+#include "cmSystemTools.h"
+
+namespace {
+void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
+{
+ for (auto c : filename) {
+ switch (c) {
+ case ' ':
+ fout << "\\ ";
+ break;
+ case '\\':
+ fout << "\\\\";
+ break;
+ default:
+ fout << c;
+ break;
+ }
+ }
+}
+
+void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg,
+ const cmGccDepfileContent& content)
+{
+ const auto& binDir = lg.GetBinaryDirectory();
+
+ for (auto const& dep : content) {
+ bool first = true;
+ for (auto const& rule : dep.rules) {
+ if (!first) {
+ fout << " \\\n ";
+ }
+ first = false;
+ WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, rule));
+ }
+ fout << ':';
+ for (auto const& path : dep.paths) {
+ fout << " \\\n ";
+ WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, 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
+}
+
+void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg,
+ const cmGccDepfileContent& content)
+{
+ const auto& binDir = lg.GetBinaryDirectory();
+
+ 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";
+ }
+ }
+}
+}
+
+bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg,
+ const std::string& infile, const std::string& outfile)
+{
+ cmGccDepfileContent content;
+ if (cmSystemTools::FileExists(infile)) {
+ auto result =
+ cmReadGccDepfile(infile.c_str(), lg.GetCurrentBinaryDirectory());
+ if (!result) {
+ return false;
+ }
+ content = *std::move(result);
+ }
+
+ cmsys::ofstream fout(outfile.c_str());
+ if (!fout) {
+ return false;
+ }
+ switch (format) {
+ case cmDepfileFormat::GccDepfile:
+ WriteGccDepfile(fout, lg, content);
+ break;
+ case cmDepfileFormat::VsTlog:
+ WriteVsTlog(fout, lg, content);
+ break;
+ }
+ return true;
+}
diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h
new file mode 100644
index 000000000..c43a45f27
--- /dev/null
+++ b/Source/cmTransformDepfile.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <string>
+
+enum class cmDepfileFormat
+{
+ GccDepfile,
+ VsTlog,
+};
+
+class cmLocalGenerator;
+
+bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg,
+ const std::string& infile, const std::string& outfile);
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 3f89641e1..8cac74d34 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -84,6 +84,14 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
}
i++;
this->CompileOutputVariable = argv[i];
+ } else if (argv[i] == "WORKING_DIRECTORY") {
+ if (argv.size() <= (i + 1)) {
+ cmSystemTools::Error(
+ "WORKING_DIRECTORY specified but there is no variable");
+ return false;
+ }
+ i++;
+ this->WorkingDirectory = argv[i];
} else {
tryCompile.push_back(argv[i]);
}
@@ -102,6 +110,14 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
return false;
}
+ if (!this->WorkingDirectory.empty()) {
+ if (!cmSystemTools::MakeDirectory(this->WorkingDirectory)) {
+ cmSystemTools::Error(cmStrCat("Error creating working directory \"",
+ this->WorkingDirectory, "\"."));
+ return false;
+ }
+ }
+
bool captureRunOutput = false;
if (!this->OutputVariable.empty()) {
captureRunOutput = true;
@@ -188,8 +204,9 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
finalCommand += runArgs;
}
bool worked = cmSystemTools::RunSingleCommand(
- finalCommand, out, out, &retVal, nullptr, cmSystemTools::OUTPUT_NONE,
- cmDuration::zero());
+ finalCommand, out, out, &retVal,
+ this->WorkingDirectory.empty() ? nullptr : this->WorkingDirectory.c_str(),
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero());
// set the run var
char retChar[16];
const char* retStr;
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index 070c63cc8..d45acd85e 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -49,4 +49,5 @@ private:
std::string OutputVariable;
std::string RunOutputVariable;
std::string CompileOutputVariable;
+ std::string WorkingDirectory;
};
diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx
index df2f64ec5..8ea19423d 100644
--- a/Source/cmUVHandlePtr.cxx
+++ b/Source/cmUVHandlePtr.cxx
@@ -59,7 +59,7 @@ uv_loop_t* uv_loop_ptr::get() const
template <typename T>
static void handle_default_delete(T* type_handle)
{
- auto handle = reinterpret_cast<uv_handle_t*>(type_handle);
+ auto* handle = reinterpret_cast<uv_handle_t*>(type_handle);
if (handle) {
assert(!uv_is_closing(handle));
if (!uv_is_closing(handle)) {
@@ -80,7 +80,7 @@ struct uv_handle_deleter
template <typename T>
void uv_handle_ptr_base_<T>::allocate(void* data)
{
- reset();
+ this->reset();
/*
We use calloc since we know all these types are c structs
@@ -88,32 +88,33 @@ void uv_handle_ptr_base_<T>::allocate(void* data)
but casting from uv_handle_t to certain other types -- namely
uv_timer_t -- triggers a cast_align warning on certain systems.
*/
- handle.reset(static_cast<T*>(calloc(1, sizeof(T))), uv_handle_deleter<T>());
- handle->data = data;
+ this->handle.reset(static_cast<T*>(calloc(1, sizeof(T))),
+ uv_handle_deleter<T>());
+ this->handle->data = data;
}
template <typename T>
void uv_handle_ptr_base_<T>::reset()
{
- handle.reset();
+ this->handle.reset();
}
template <typename T>
uv_handle_ptr_base_<T>::operator uv_handle_t*()
{
- return reinterpret_cast<uv_handle_t*>(handle.get());
+ return reinterpret_cast<uv_handle_t*>(this->handle.get());
}
template <typename T>
T* uv_handle_ptr_base_<T>::operator->() const noexcept
{
- return handle.get();
+ return this->handle.get();
}
template <typename T>
T* uv_handle_ptr_base_<T>::get() const
{
- return handle.get();
+ return this->handle.get();
}
template <typename T>
@@ -146,14 +147,15 @@ struct uv_handle_deleter<uv_async_t>
void operator()(uv_async_t* handle)
{
- std::lock_guard<std::mutex> lock(*handleMutex);
+ std::lock_guard<std::mutex> lock(*this->handleMutex);
handle_default_delete(handle);
}
};
void uv_async_ptr::send()
{
- auto deleter = std::get_deleter<uv_handle_deleter<uv_async_t>>(this->handle);
+ auto* deleter =
+ std::get_deleter<uv_handle_deleter<uv_async_t>>(this->handle);
assert(deleter);
std::lock_guard<std::mutex> lock(*deleter->handleMutex);
@@ -164,8 +166,8 @@ void uv_async_ptr::send()
int uv_async_ptr::init(uv_loop_t& loop, uv_async_cb async_cb, void* data)
{
- allocate(data);
- return uv_async_init(&loop, handle.get(), async_cb);
+ this->allocate(data);
+ return uv_async_init(&loop, this->handle.get(), async_cb);
}
#endif
@@ -183,62 +185,62 @@ struct uv_handle_deleter<uv_signal_t>
int uv_signal_ptr::init(uv_loop_t& loop, void* data)
{
- allocate(data);
- return uv_signal_init(&loop, handle.get());
+ this->allocate(data);
+ return uv_signal_init(&loop, this->handle.get());
}
int uv_signal_ptr::start(uv_signal_cb cb, int signum)
{
- assert(handle);
+ assert(this->handle);
return uv_signal_start(*this, cb, signum);
}
void uv_signal_ptr::stop()
{
- if (handle) {
+ if (this->handle) {
uv_signal_stop(*this);
}
}
int uv_pipe_ptr::init(uv_loop_t& loop, int ipc, void* data)
{
- allocate(data);
+ this->allocate(data);
return uv_pipe_init(&loop, *this, ipc);
}
uv_pipe_ptr::operator uv_stream_t*() const
{
- return reinterpret_cast<uv_stream_t*>(handle.get());
+ return reinterpret_cast<uv_stream_t*>(this->handle.get());
}
int uv_process_ptr::spawn(uv_loop_t& loop, uv_process_options_t const& options,
void* data)
{
- allocate(data);
+ this->allocate(data);
return uv_spawn(&loop, *this, &options);
}
int uv_timer_ptr::init(uv_loop_t& loop, void* data)
{
- allocate(data);
+ this->allocate(data);
return uv_timer_init(&loop, *this);
}
int uv_timer_ptr::start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
{
- assert(handle);
+ assert(this->handle);
return uv_timer_start(*this, cb, timeout, repeat);
}
#ifndef CMAKE_BOOTSTRAP
uv_tty_ptr::operator uv_stream_t*() const
{
- return reinterpret_cast<uv_stream_t*>(handle.get());
+ return reinterpret_cast<uv_stream_t*>(this->handle.get());
}
int uv_tty_ptr::init(uv_loop_t& loop, int fd, int readable, void* data)
{
- allocate(data);
+ this->allocate(data);
return uv_tty_init(&loop, *this, fd, readable);
}
#endif
diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h
index d9de7f3da..8c5ad5983 100644
--- a/Source/cmUVHandlePtr.h
+++ b/Source/cmUVHandlePtr.h
@@ -78,7 +78,7 @@ template <typename T>
class uv_handle_ptr_base_
{
protected:
- template <typename _T>
+ template <typename U>
friend class uv_handle_ptr_base_;
/**
@@ -128,7 +128,7 @@ public:
// dtors to work. Some compilers do not like '= default' here.
uv_handle_ptr_base_() {} // NOLINT(modernize-use-equals-default)
uv_handle_ptr_base_(std::nullptr_t) {}
- ~uv_handle_ptr_base_() { reset(); }
+ ~uv_handle_ptr_base_() { this->reset(); }
/**
* Properly close the handle if needed and sets the inner handle to nullptr
@@ -160,7 +160,7 @@ inline uv_handle_ptr_base_<T>& uv_handle_ptr_base_<T>::operator=(
template <typename T>
class uv_handle_ptr_ : public uv_handle_ptr_base_<T>
{
- template <typename _T>
+ template <typename U>
friend class uv_handle_ptr_;
public:
diff --git a/Source/cmUuid.cxx b/Source/cmUuid.cxx
index cd52b3f30..2513303cd 100644
--- a/Source/cmUuid.cxx
+++ b/Source/cmUuid.cxx
@@ -82,7 +82,7 @@ bool cmUuid::StringToBinary(std::string const& input,
return false;
}
size_t digits = kUuidGroups[i] * 2;
- if (!StringToBinaryImpl(input.substr(index, digits), output)) {
+ if (!this->StringToBinaryImpl(input.substr(index, digits), output)) {
return false;
}
@@ -134,12 +134,12 @@ bool cmUuid::StringToBinaryImpl(std::string const& input,
for (size_t i = 0; i < input.size(); i += 2) {
char c1 = 0;
- if (!IntFromHexDigit(input[i], c1)) {
+ if (!this->IntFromHexDigit(input[i], c1)) {
return false;
}
char c2 = 0;
- if (!IntFromHexDigit(input[i + 1], c2)) {
+ if (!this->IntFromHexDigit(input[i + 1], c2)) {
return false;
}
diff --git a/Source/cmVersion.h b/Source/cmVersion.h
index 9072c9fb5..456428c5b 100644
--- a/Source/cmVersion.h
+++ b/Source/cmVersion.h
@@ -24,8 +24,8 @@ public:
/* Encode with room for up to 1000 minor releases between major releases
and to encode dates until the year 10000 in the patch level. */
-#define CMake_VERSION_ENCODE__BASE KWIML_INT_UINT64_C(100000000)
+#define CMake_VERSION_ENCODE_BASE KWIML_INT_UINT64_C(100000000)
#define CMake_VERSION_ENCODE(major, minor, patch) \
- ((((major)*1000u) * CMake_VERSION_ENCODE__BASE) + \
- (((minor) % 1000u) * CMake_VERSION_ENCODE__BASE) + \
- (((patch) % CMake_VERSION_ENCODE__BASE)))
+ ((((major)*1000u) * CMake_VERSION_ENCODE_BASE) + \
+ (((minor) % 1000u) * CMake_VERSION_ENCODE_BASE) + \
+ (((patch) % CMake_VERSION_ENCODE_BASE)))
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 489e42d8e..965ac3eee 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -676,7 +676,7 @@ void cmVisualStudio10TargetGenerator::Generate()
cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
ConvertToWindowsSlash(propsLocal);
this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
- true, true);
+ true);
Elem(e1, "Import").Attribute("Project", propsLocal);
}
}
@@ -1020,9 +1020,9 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
cm::string_view tagName =
cm::string_view(p).substr(propNamePrefix.length());
if (!tagName.empty()) {
- const std::string& value = *props.GetPropertyValue(p);
- if (!value.empty()) {
- e2.Element(tagName, value);
+ cmProp value = props.GetPropertyValue(p);
+ if (cmNonempty(value)) {
+ e2.Element(tagName, *value);
}
}
}
@@ -1897,8 +1897,15 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
// Figure out if there's any additional flags to use
if (cmProp saf = sf->GetProperty("VS_SHADER_FLAGS")) {
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*saf);
+
for (const std::string& config : this->Configurations) {
- toolSettings[config]["AdditionalOptions"] = *saf;
+ std::string evaluated = cge->Evaluate(this->LocalGenerator, config);
+
+ if (!evaluated.empty()) {
+ toolSettings[config]["AdditionalOptions"] = evaluated;
+ }
}
}
// Figure out if debug information should be generated
@@ -2402,27 +2409,30 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
configDefines += *ccdefs;
}
- // Add precompile headers compile options.
- std::string customAndPchOptions = options;
- const std::string pchSource =
+ // We have pch state in the following situation:
+ // 1. We have SKIP_PRECOMPILE_HEADERS == true
+ // 2. We are creating the pre-compiled header
+ // 3. We are a different language than the linker language AND pch is
+ // enabled.
+ std::string const& linkLanguage =
+ this->GeneratorTarget->GetLinkerLanguage(config);
+ std::string const& pchSource =
this->GeneratorTarget->GetPchSource(config, lang);
- if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
- std::string pchOptions;
- if (sf.GetFullPath() == pchSource) {
- pchOptions =
- this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
- } else {
- pchOptions =
- this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
- }
- customAndPchOptions = cmStrCat(customAndPchOptions, ';', pchOptions);
- }
+ const bool skipPCH =
+ pchSource.empty() || sf.GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS");
+ const bool makePCH = (sf.GetFullPath() == pchSource);
+ const bool useSharedPCH = !skipPCH && (lang == linkLanguage);
+ const bool useDifferentLangPCH = !skipPCH && (lang != linkLanguage);
+ const bool useNoPCH = skipPCH && (lang != linkLanguage) &&
+ !this->GeneratorTarget->GetPchHeader(config, linkLanguage).empty();
+ const bool needsPCHFlags =
+ (makePCH || useSharedPCH || useDifferentLangPCH || useNoPCH);
// if we have flags or defines for this config then
// use them
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
- !includes.empty() || compileAs || noWinRT ||
- !customAndPchOptions.empty()) {
+ !includes.empty() || compileAs || noWinRT || !options.empty() ||
+ needsPCHFlags) {
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmIDEFlagTable const* flagtable = nullptr;
const std::string& srclang = source->GetLanguage();
@@ -2455,15 +2465,37 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else {
clOptions.Parse(flags);
}
- if (!customAndPchOptions.empty()) {
+
+ if (needsPCHFlags) {
+ // Add precompile headers compile options.
+ std::string expandedOptions;
+ std::string pchOptions;
+ if (makePCH) {
+ pchOptions =
+ this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
+ } else if (useNoPCH) {
+ clOptions.AddFlag("PrecompiledHeader", "NotUsing");
+ } else if (useSharedPCH) {
+ std::string pchHeader =
+ this->GeneratorTarget->GetPchHeader(config, lang);
+ clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
+ } else if (useDifferentLangPCH) {
+ pchOptions =
+ this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
+ }
+ this->LocalGenerator->AppendCompileOptions(expandedOptions,
+ pchOptions);
+ clOptions.Parse(expandedOptions);
+ }
+
+ if (!options.empty()) {
std::string expandedOptions;
if (configDependentOptions) {
this->LocalGenerator->AppendCompileOptions(
expandedOptions,
- genexInterpreter.Evaluate(customAndPchOptions, "COMPILE_OPTIONS"));
+ genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
} else {
- this->LocalGenerator->AppendCompileOptions(expandedOptions,
- customAndPchOptions);
+ this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
}
clOptions.Parse(expandedOptions);
}
@@ -2786,6 +2818,13 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->GeneratorTarget->GetPchHeader(configName, linkLanguage);
if (this->MSTools && vcxproj == this->ProjectType && pchHeader.empty()) {
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
+ } else if (this->MSTools && vcxproj == this->ProjectType &&
+ !pchHeader.empty()) {
+ clOptions.AddFlag("PrecompiledHeader", "Use");
+ clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
+ std::string pchFile =
+ this->GeneratorTarget->GetPchFile(configName, linkLanguage);
+ clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
}
// Get preprocessor definitions for this directory.
@@ -4183,8 +4222,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
cmLocalGenerator* lg = dt->GetLocalGenerator();
std::string name = dt->GetName();
std::string path;
- cmProp p = dt->GetProperty("EXTERNAL_MSPROJECT");
- if (p) {
+ if (cmProp p = dt->GetProperty("EXTERNAL_MSPROJECT")) {
path = *p;
} else {
path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(),
@@ -4972,9 +5010,9 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
if (cmHasPrefix(p, propNamePrefix)) {
std::string tagName = p.substr(propNamePrefix.length());
if (!tagName.empty()) {
- const std::string& val = *props.GetPropertyValue(p);
- if (!val.empty()) {
- tags[tagName] = val;
+ cmProp val = props.GetPropertyValue(p);
+ if (cmNonempty(val)) {
+ tags[tagName] = *val;
} else {
tags.erase(tagName);
}
diff --git a/Source/cmWorkerPool.cxx b/Source/cmWorkerPool.cxx
index 12aba4f96..1d15c27ad 100644
--- a/Source/cmWorkerPool.cxx
+++ b/Source/cmWorkerPool.cxx
@@ -31,7 +31,6 @@ public:
/// On error the ssize_t argument is a non zero libuv error code
using EndFunction = std::function<void(ssize_t)>;
-public:
/**
* Reset to construction state
*/
@@ -50,11 +49,14 @@ public:
bool startRead(DataFunction dataFunction, EndFunction endFunction);
//! libuv pipe
- uv_pipe_t* uv_pipe() const { return UVPipe_.get(); }
+ uv_pipe_t* uv_pipe() const { return this->UVPipe_.get(); }
//! uv_pipe() casted to libuv stream
- uv_stream_t* uv_stream() const { return static_cast<uv_stream_t*>(UVPipe_); }
+ uv_stream_t* uv_stream() const
+ {
+ return static_cast<uv_stream_t*>(this->UVPipe_);
+ }
//! uv_pipe() casted to libuv handle
- uv_handle_t* uv_handle() { return static_cast<uv_handle_t*>(UVPipe_); }
+ uv_handle_t* uv_handle() { return static_cast<uv_handle_t*>(this->UVPipe_); }
private:
// -- Libuv callbacks
@@ -62,7 +64,6 @@ private:
uv_buf_t* buf);
static void UVData(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
-private:
cm::uv_pipe_ptr UVPipe_;
std::vector<char> Buffer_;
DataFunction DataFunction_;
@@ -71,37 +72,37 @@ private:
void cmUVPipeBuffer::reset()
{
- if (UVPipe_.get() != nullptr) {
- EndFunction_ = nullptr;
- DataFunction_ = nullptr;
- Buffer_.clear();
- Buffer_.shrink_to_fit();
- UVPipe_.reset();
+ if (this->UVPipe_.get() != nullptr) {
+ this->EndFunction_ = nullptr;
+ this->DataFunction_ = nullptr;
+ this->Buffer_.clear();
+ this->Buffer_.shrink_to_fit();
+ this->UVPipe_.reset();
}
}
bool cmUVPipeBuffer::init(uv_loop_t* uv_loop)
{
- reset();
+ this->reset();
if (uv_loop == nullptr) {
return false;
}
- int ret = UVPipe_.init(*uv_loop, 0, this);
+ int ret = this->UVPipe_.init(*uv_loop, 0, this);
return (ret == 0);
}
bool cmUVPipeBuffer::startRead(DataFunction dataFunction,
EndFunction endFunction)
{
- if (UVPipe_.get() == nullptr) {
+ if (this->UVPipe_.get() == nullptr) {
return false;
}
if (!dataFunction || !endFunction) {
return false;
}
- DataFunction_ = std::move(dataFunction);
- EndFunction_ = std::move(endFunction);
- int ret = uv_read_start(uv_stream(), &cmUVPipeBuffer::UVAlloc,
+ this->DataFunction_ = std::move(dataFunction);
+ this->EndFunction_ = std::move(endFunction);
+ int ret = uv_read_start(this->uv_stream(), &cmUVPipeBuffer::UVAlloc,
&cmUVPipeBuffer::UVData);
return (ret == 0);
}
@@ -151,12 +152,11 @@ public:
bool MergedOutput = false;
};
-public:
// -- Const accessors
- SetupT const& Setup() const { return Setup_; }
- cmWorkerPool::ProcessResultT* Result() const { return Setup_.Result; }
- bool IsStarted() const { return IsStarted_; }
- bool IsFinished() const { return IsFinished_; }
+ SetupT const& Setup() const { return this->Setup_; }
+ cmWorkerPool::ProcessResultT* Result() const { return this->Setup_.Result; }
+ bool IsStarted() const { return this->IsStarted_; }
+ bool IsFinished() const { return this->IsFinished_; }
// -- Runtime
void setup(cmWorkerPool::ProcessResultT* result, bool mergedOutput,
@@ -167,13 +167,12 @@ public:
private:
// -- Libuv callbacks
static void UVExit(uv_process_t* handle, int64_t exitStatus, int termSignal);
- void UVPipeOutData(cmUVPipeBuffer::DataRange data);
+ void UVPipeOutData(cmUVPipeBuffer::DataRange data) const;
void UVPipeOutEnd(ssize_t error);
- void UVPipeErrData(cmUVPipeBuffer::DataRange data);
+ void UVPipeErrData(cmUVPipeBuffer::DataRange data) const;
void UVPipeErrEnd(ssize_t error);
void UVTryFinish();
-private:
// -- Setup
SetupT Setup_;
// -- Runtime
@@ -193,109 +192,113 @@ void cmUVReadOnlyProcess::setup(cmWorkerPool::ProcessResultT* result,
std::vector<std::string> const& command,
std::string const& workingDirectory)
{
- Setup_.WorkingDirectory = workingDirectory;
- Setup_.Command = command;
- Setup_.Result = result;
- Setup_.MergedOutput = mergedOutput;
+ this->Setup_.WorkingDirectory = workingDirectory;
+ this->Setup_.Command = command;
+ this->Setup_.Result = result;
+ this->Setup_.MergedOutput = mergedOutput;
}
bool cmUVReadOnlyProcess::start(uv_loop_t* uv_loop,
std::function<void()> finishedCallback)
{
- if (IsStarted() || (Result() == nullptr)) {
+ if (this->IsStarted() || (this->Result() == nullptr)) {
return false;
}
// Reset result before the start
- Result()->reset();
+ this->Result()->reset();
// Fill command string pointers
- if (!Setup().Command.empty()) {
- CommandPtr_.reserve(Setup().Command.size() + 1);
- for (std::string const& arg : Setup().Command) {
- CommandPtr_.push_back(arg.c_str());
+ if (!this->Setup().Command.empty()) {
+ this->CommandPtr_.reserve(this->Setup().Command.size() + 1);
+ for (std::string const& arg : this->Setup().Command) {
+ this->CommandPtr_.push_back(arg.c_str());
}
- CommandPtr_.push_back(nullptr);
+ this->CommandPtr_.push_back(nullptr);
} else {
- Result()->ErrorMessage = "Empty command";
+ this->Result()->ErrorMessage = "Empty command";
}
- if (!Result()->error()) {
- if (!UVPipeOut_.init(uv_loop)) {
- Result()->ErrorMessage = "libuv stdout pipe initialization failed";
+ if (!this->Result()->error()) {
+ if (!this->UVPipeOut_.init(uv_loop)) {
+ this->Result()->ErrorMessage = "libuv stdout pipe initialization failed";
}
}
- if (!Result()->error()) {
- if (!UVPipeErr_.init(uv_loop)) {
- Result()->ErrorMessage = "libuv stderr pipe initialization failed";
+ if (!this->Result()->error()) {
+ if (!this->UVPipeErr_.init(uv_loop)) {
+ this->Result()->ErrorMessage = "libuv stderr pipe initialization failed";
}
}
- if (!Result()->error()) {
+ if (!this->Result()->error()) {
// -- Setup process stdio options
// stdin
- UVOptionsStdIO_[0].flags = UV_IGNORE;
- UVOptionsStdIO_[0].data.stream = nullptr;
+ this->UVOptionsStdIO_[0].flags = UV_IGNORE;
+ this->UVOptionsStdIO_[0].data.stream = nullptr;
// stdout
- UVOptionsStdIO_[1].flags =
+ this->UVOptionsStdIO_[1].flags =
static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- UVOptionsStdIO_[1].data.stream = UVPipeOut_.uv_stream();
+ this->UVOptionsStdIO_[1].data.stream = this->UVPipeOut_.uv_stream();
// stderr
- UVOptionsStdIO_[2].flags =
+ this->UVOptionsStdIO_[2].flags =
static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- UVOptionsStdIO_[2].data.stream = UVPipeErr_.uv_stream();
+ this->UVOptionsStdIO_[2].data.stream = this->UVPipeErr_.uv_stream();
// -- Setup process options
- std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
- UVOptions_.exit_cb = &cmUVReadOnlyProcess::UVExit;
- UVOptions_.file = CommandPtr_[0];
- UVOptions_.args = const_cast<char**>(CommandPtr_.data());
- UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
- UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
- UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
- UVOptions_.stdio = UVOptionsStdIO_.data();
+ std::fill_n(reinterpret_cast<char*>(&this->UVOptions_),
+ sizeof(this->UVOptions_), 0);
+ this->UVOptions_.exit_cb = &cmUVReadOnlyProcess::UVExit;
+ this->UVOptions_.file = this->CommandPtr_[0];
+ this->UVOptions_.args = const_cast<char**>(this->CommandPtr_.data());
+ this->UVOptions_.cwd = this->Setup_.WorkingDirectory.c_str();
+ this->UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
+ this->UVOptions_.stdio_count =
+ static_cast<int>(this->UVOptionsStdIO_.size());
+ this->UVOptions_.stdio = this->UVOptionsStdIO_.data();
// -- Spawn process
- int uvErrorCode = UVProcess_.spawn(*uv_loop, UVOptions_, this);
+ int uvErrorCode = this->UVProcess_.spawn(*uv_loop, this->UVOptions_, this);
if (uvErrorCode != 0) {
- Result()->ErrorMessage = "libuv process spawn failed";
+ this->Result()->ErrorMessage = "libuv process spawn failed";
if (const char* uvErr = uv_strerror(uvErrorCode)) {
- Result()->ErrorMessage += ": ";
- Result()->ErrorMessage += uvErr;
+ this->Result()->ErrorMessage += ": ";
+ this->Result()->ErrorMessage += uvErr;
}
}
}
// -- Start reading from stdio streams
- if (!Result()->error()) {
- if (!UVPipeOut_.startRead(
+ if (!this->Result()->error()) {
+ if (!this->UVPipeOut_.startRead(
[this](cmUVPipeBuffer::DataRange range) {
this->UVPipeOutData(range);
},
[this](ssize_t error) { this->UVPipeOutEnd(error); })) {
- Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
+ this->Result()->ErrorMessage =
+ "libuv start reading from stdout pipe failed";
}
}
- if (!Result()->error()) {
- if (!UVPipeErr_.startRead(
+ if (!this->Result()->error()) {
+ if (!this->UVPipeErr_.startRead(
[this](cmUVPipeBuffer::DataRange range) {
this->UVPipeErrData(range);
},
[this](ssize_t error) { this->UVPipeErrEnd(error); })) {
- Result()->ErrorMessage = "libuv start reading from stderr pipe failed";
+ this->Result()->ErrorMessage =
+ "libuv start reading from stderr pipe failed";
}
}
- if (!Result()->error()) {
- IsStarted_ = true;
- FinishedCallback_ = std::move(finishedCallback);
+ if (!this->Result()->error()) {
+ this->IsStarted_ = true;
+ this->FinishedCallback_ = std::move(finishedCallback);
} else {
// Clear libuv handles and finish
- UVProcess_.reset();
- UVPipeOut_.reset();
- UVPipeErr_.reset();
- CommandPtr_.clear();
+ this->UVProcess_.reset();
+ this->UVPipeOut_.reset();
+ this->UVPipeErr_.reset();
+ this->CommandPtr_.clear();
}
- return IsStarted();
+ return this->IsStarted();
}
void cmUVReadOnlyProcess::UVExit(uv_process_t* handle, int64_t exitStatus,
@@ -323,38 +326,38 @@ void cmUVReadOnlyProcess::UVExit(uv_process_t* handle, int64_t exitStatus,
}
}
-void cmUVReadOnlyProcess::UVPipeOutData(cmUVPipeBuffer::DataRange data)
+void cmUVReadOnlyProcess::UVPipeOutData(cmUVPipeBuffer::DataRange data) const
{
- Result()->StdOut.append(data.begin(), data.end());
+ this->Result()->StdOut.append(data.begin(), data.end());
}
void cmUVReadOnlyProcess::UVPipeOutEnd(ssize_t error)
{
// Process pipe error
- if ((error != 0) && !Result()->error()) {
- Result()->ErrorMessage = cmStrCat(
+ if ((error != 0) && !this->Result()->error()) {
+ this->Result()->ErrorMessage = cmStrCat(
"Reading from stdout pipe failed with libuv error code ", error);
}
// Try finish
- UVTryFinish();
+ this->UVTryFinish();
}
-void cmUVReadOnlyProcess::UVPipeErrData(cmUVPipeBuffer::DataRange data)
+void cmUVReadOnlyProcess::UVPipeErrData(cmUVPipeBuffer::DataRange data) const
{
- std::string* str =
- Setup_.MergedOutput ? &Result()->StdOut : &Result()->StdErr;
+ std::string* str = this->Setup_.MergedOutput ? &this->Result()->StdOut
+ : &this->Result()->StdErr;
str->append(data.begin(), data.end());
}
void cmUVReadOnlyProcess::UVPipeErrEnd(ssize_t error)
{
// Process pipe error
- if ((error != 0) && !Result()->error()) {
- Result()->ErrorMessage = cmStrCat(
+ if ((error != 0) && !this->Result()->error()) {
+ this->Result()->ErrorMessage = cmStrCat(
"Reading from stderr pipe failed with libuv error code ", error);
}
// Try finish
- UVTryFinish();
+ this->UVTryFinish();
}
void cmUVReadOnlyProcess::UVTryFinish()
@@ -362,12 +365,13 @@ void cmUVReadOnlyProcess::UVTryFinish()
// There still might be data in the pipes after the process has finished.
// Therefore check if the process is finished AND all pipes are closed
// before signaling the worker thread to continue.
- if ((UVProcess_.get() != nullptr) || (UVPipeOut_.uv_pipe() != nullptr) ||
- (UVPipeErr_.uv_pipe() != nullptr)) {
+ if ((this->UVProcess_.get() != nullptr) ||
+ (this->UVPipeOut_.uv_pipe() != nullptr) ||
+ (this->UVPipeErr_.uv_pipe() != nullptr)) {
return;
}
- IsFinished_ = true;
- FinishedCallback_();
+ this->IsFinished_ = true;
+ this->FinishedCallback_();
}
/**
@@ -385,7 +389,7 @@ public:
/**
* Set the internal thread
*/
- void SetThread(std::thread&& aThread) { Thread_ = std::move(aThread); }
+ void SetThread(std::thread&& aThread) { this->Thread_ = std::move(aThread); }
/**
* Run an external process
@@ -399,7 +403,6 @@ private:
static void UVProcessStart(uv_async_t* handle);
void UVProcessFinished();
-private:
// -- Process management
struct
{
@@ -414,13 +417,13 @@ private:
cmWorkerPoolWorker::cmWorkerPoolWorker(uv_loop_t& uvLoop)
{
- Proc_.Request.init(uvLoop, &cmWorkerPoolWorker::UVProcessStart, this);
+ this->Proc_.Request.init(uvLoop, &cmWorkerPoolWorker::UVProcessStart, this);
}
cmWorkerPoolWorker::~cmWorkerPoolWorker()
{
- if (Thread_.joinable()) {
- Thread_.join();
+ if (this->Thread_.joinable()) {
+ this->Thread_.join();
}
}
@@ -433,17 +436,17 @@ bool cmWorkerPoolWorker::RunProcess(cmWorkerPool::ProcessResultT& result,
}
// Create process instance
{
- std::lock_guard<std::mutex> lock(Proc_.Mutex);
- Proc_.ROP = cm::make_unique<cmUVReadOnlyProcess>();
- Proc_.ROP->setup(&result, true, command, workingDirectory);
+ std::lock_guard<std::mutex> lock(this->Proc_.Mutex);
+ this->Proc_.ROP = cm::make_unique<cmUVReadOnlyProcess>();
+ this->Proc_.ROP->setup(&result, true, command, workingDirectory);
}
// Send asynchronous process start request to libuv loop
- Proc_.Request.send();
+ this->Proc_.Request.send();
// Wait until the process has been finished and destroyed
{
- std::unique_lock<std::mutex> ulock(Proc_.Mutex);
- while (Proc_.ROP) {
- Proc_.Condition.wait(ulock);
+ std::unique_lock<std::mutex> ulock(this->Proc_.Mutex);
+ while (this->Proc_.ROP) {
+ this->Proc_.Condition.wait(ulock);
}
}
return !result.error();
@@ -469,12 +472,13 @@ void cmWorkerPoolWorker::UVProcessStart(uv_async_t* handle)
void cmWorkerPoolWorker::UVProcessFinished()
{
- std::lock_guard<std::mutex> lock(Proc_.Mutex);
- if (Proc_.ROP && (Proc_.ROP->IsFinished() || !Proc_.ROP->IsStarted())) {
- Proc_.ROP.reset();
+ std::lock_guard<std::mutex> lock(this->Proc_.Mutex);
+ if (this->Proc_.ROP &&
+ (this->Proc_.ROP->IsFinished() || !this->Proc_.ROP->IsStarted())) {
+ this->Proc_.ROP.reset();
}
// Notify idling thread
- Proc_.Condition.notify_one();
+ this->Proc_.Condition.notify_one();
}
/**
@@ -511,7 +515,6 @@ public:
static void UVSlotBegin(uv_async_t* handle);
static void UVSlotEnd(uv_async_t* handle);
-public:
// -- UV loop
#ifdef CMAKE_UV_SIGNAL_HACK
std::unique_ptr<cmUVSignalHackRAII> UVHackRAII;
@@ -539,19 +542,19 @@ public:
void cmWorkerPool::ProcessResultT::reset()
{
- ExitStatus = 0;
- TermSignal = 0;
- if (!StdOut.empty()) {
- StdOut.clear();
- StdOut.shrink_to_fit();
+ this->ExitStatus = 0;
+ this->TermSignal = 0;
+ if (!this->StdOut.empty()) {
+ this->StdOut.clear();
+ this->StdOut.shrink_to_fit();
}
- if (!StdErr.empty()) {
- StdErr.clear();
- StdErr.shrink_to_fit();
+ if (!this->StdErr.empty()) {
+ this->StdErr.clear();
+ this->StdErr.shrink_to_fit();
}
- if (!ErrorMessage.empty()) {
- ErrorMessage.clear();
- ErrorMessage.shrink_to_fit();
+ if (!this->ErrorMessage.empty()) {
+ this->ErrorMessage.clear();
+ this->ErrorMessage.shrink_to_fit();
}
}
@@ -563,56 +566,58 @@ cmWorkerPoolInternal::cmWorkerPoolInternal(cmWorkerPool* pool)
#ifdef CMAKE_UV_SIGNAL_HACK
UVHackRAII = cm::make_unique<cmUVSignalHackRAII>();
#endif
- UVLoop = cm::make_unique<uv_loop_t>();
- uv_loop_init(UVLoop.get());
+ this->UVLoop = cm::make_unique<uv_loop_t>();
+ uv_loop_init(this->UVLoop.get());
}
cmWorkerPoolInternal::~cmWorkerPoolInternal()
{
- uv_loop_close(UVLoop.get());
+ uv_loop_close(this->UVLoop.get());
}
bool cmWorkerPoolInternal::Process()
{
// Reset state flags
- Processing = true;
- Aborting = false;
+ this->Processing = true;
+ this->Aborting = false;
// Initialize libuv asynchronous request
- UVRequestBegin.init(*UVLoop, &cmWorkerPoolInternal::UVSlotBegin, this);
- UVRequestEnd.init(*UVLoop, &cmWorkerPoolInternal::UVSlotEnd, this);
+ this->UVRequestBegin.init(*this->UVLoop, &cmWorkerPoolInternal::UVSlotBegin,
+ this);
+ this->UVRequestEnd.init(*this->UVLoop, &cmWorkerPoolInternal::UVSlotEnd,
+ this);
// Send begin request
- UVRequestBegin.send();
+ this->UVRequestBegin.send();
// Run libuv loop
- bool success = (uv_run(UVLoop.get(), UV_RUN_DEFAULT) == 0);
+ bool success = (uv_run(this->UVLoop.get(), UV_RUN_DEFAULT) == 0);
// Update state flags
- Processing = false;
- Aborting = false;
+ this->Processing = false;
+ this->Aborting = false;
return success;
}
void cmWorkerPoolInternal::Abort()
{
// Clear all jobs and set abort flag
- std::lock_guard<std::mutex> guard(Mutex);
- if (!Aborting) {
+ std::lock_guard<std::mutex> guard(this->Mutex);
+ if (!this->Aborting) {
// Register abort and clear queue
- Aborting = true;
- Queue.clear();
- Condition.notify_all();
+ this->Aborting = true;
+ this->Queue.clear();
+ this->Condition.notify_all();
}
}
inline bool cmWorkerPoolInternal::PushJob(cmWorkerPool::JobHandleT&& jobHandle)
{
- std::lock_guard<std::mutex> guard(Mutex);
- if (Aborting) {
+ std::lock_guard<std::mutex> guard(this->Mutex);
+ if (this->Aborting) {
return false;
}
// Append the job to the queue
- Queue.emplace_back(std::move(jobHandle));
+ this->Queue.emplace_back(std::move(jobHandle));
// Notify an idle worker if there's one
- if (WorkersIdle != 0) {
- Condition.notify_one();
+ if (this->WorkersIdle != 0) {
+ this->Condition.notify_one();
}
// Return success
return true;
@@ -652,79 +657,79 @@ void cmWorkerPoolInternal::UVSlotEnd(uv_async_t* handle)
void cmWorkerPoolInternal::Work(unsigned int workerIndex)
{
cmWorkerPool::JobHandleT jobHandle;
- std::unique_lock<std::mutex> uLock(Mutex);
+ std::unique_lock<std::mutex> uLock(this->Mutex);
// Increment running workers count
- ++WorkersRunning;
+ ++this->WorkersRunning;
// Enter worker main loop
while (true) {
// Abort on request
- if (Aborting) {
+ if (this->Aborting) {
break;
}
// Wait for new jobs on the main CV
- if (Queue.empty()) {
- ++WorkersIdle;
- Condition.wait(uLock);
- --WorkersIdle;
+ if (this->Queue.empty()) {
+ ++this->WorkersIdle;
+ this->Condition.wait(uLock);
+ --this->WorkersIdle;
continue;
}
// If there is a fence currently active or waiting,
// sleep on the main CV and try again.
- if (FenceProcessing) {
- Condition.wait(uLock);
+ if (this->FenceProcessing) {
+ this->Condition.wait(uLock);
continue;
}
// Pop next job from queue
- jobHandle = std::move(Queue.front());
- Queue.pop_front();
+ jobHandle = std::move(this->Queue.front());
+ this->Queue.pop_front();
// Check for fence jobs
bool raisedFence = false;
if (jobHandle->IsFence()) {
- FenceProcessing = true;
+ this->FenceProcessing = true;
raisedFence = true;
// Wait on the Fence CV until all pending jobs are done.
- while (JobsProcessing != 0 && !Aborting) {
- ConditionFence.wait(uLock);
+ while (this->JobsProcessing != 0 && !this->Aborting) {
+ this->ConditionFence.wait(uLock);
}
// When aborting, explicitly kick all threads alive once more.
- if (Aborting) {
- FenceProcessing = false;
- Condition.notify_all();
+ if (this->Aborting) {
+ this->FenceProcessing = false;
+ this->Condition.notify_all();
break;
}
}
// Unlocked scope for job processing
- ++JobsProcessing;
+ ++this->JobsProcessing;
{
uLock.unlock();
- jobHandle->Work(Pool, workerIndex); // Process job
- jobHandle.reset(); // Destroy job
+ jobHandle->Work(this->Pool, workerIndex); // Process job
+ jobHandle.reset(); // Destroy job
uLock.lock();
}
- --JobsProcessing;
+ --this->JobsProcessing;
// If this was the thread that entered fence processing
// originally, notify all idling workers that the fence
// is done.
if (raisedFence) {
- FenceProcessing = false;
- Condition.notify_all();
+ this->FenceProcessing = false;
+ this->Condition.notify_all();
}
// If fence processing is still not done, notify the
// the fencing worker when all active jobs are done.
- if (FenceProcessing && JobsProcessing == 0) {
- ConditionFence.notify_all();
+ if (this->FenceProcessing && this->JobsProcessing == 0) {
+ this->ConditionFence.notify_all();
}
}
// Decrement running workers count
- if (--WorkersRunning == 0) {
+ if (--this->WorkersRunning == 0) {
// Last worker thread about to finish. Send libuv event.
- UVRequestEnd.send();
+ this->UVRequestEnd.send();
}
}
@@ -735,7 +740,7 @@ bool cmWorkerPool::JobT::RunProcess(ProcessResultT& result,
std::string const& workingDirectory)
{
// Get worker by index
- auto* wrk = Pool_->Int_->Workers.at(WorkerIndex_).get();
+ auto* wrk = this->Pool_->Int_->Workers.at(this->WorkerIndex_).get();
return wrk->RunProcess(result, command, workingDirectory);
}
@@ -748,29 +753,29 @@ cmWorkerPool::~cmWorkerPool() = default;
void cmWorkerPool::SetThreadCount(unsigned int threadCount)
{
- if (!Int_->Processing) {
- ThreadCount_ = (threadCount > 0) ? threadCount : 1u;
+ if (!this->Int_->Processing) {
+ this->ThreadCount_ = (threadCount > 0) ? threadCount : 1u;
}
}
bool cmWorkerPool::Process(void* userData)
{
// Setup user data
- UserData_ = userData;
+ this->UserData_ = userData;
// Run libuv loop
- bool success = Int_->Process();
+ bool success = this->Int_->Process();
// Clear user data
- UserData_ = nullptr;
+ this->UserData_ = nullptr;
// Return
return success;
}
bool cmWorkerPool::PushJob(JobHandleT&& jobHandle)
{
- return Int_->PushJob(std::move(jobHandle));
+ return this->Int_->PushJob(std::move(jobHandle));
}
void cmWorkerPool::Abort()
{
- Int_->Abort();
+ this->Int_->Abort();
}
diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h
index 0fb670724..ff255261d 100644
--- a/Source/cmWorkerPool.h
+++ b/Source/cmWorkerPool.h
@@ -28,7 +28,8 @@ public:
void reset();
bool error() const
{
- return (ExitStatus != 0) || (TermSignal != 0) || !ErrorMessage.empty();
+ return (this->ExitStatus != 0) || (this->TermSignal != 0) ||
+ !this->ErrorMessage.empty();
}
std::int64_t ExitStatus = 0;
@@ -60,7 +61,7 @@ public:
* - no jobs later in the queue will be processed before this job was
* processed
*/
- bool IsFence() const { return Fence_; }
+ bool IsFence() const { return this->Fence_; }
protected:
/**
@@ -80,13 +81,13 @@ public:
* Get the worker pool.
* Only valid during the JobT::Process() call!
*/
- cmWorkerPool* Pool() const { return Pool_; }
+ cmWorkerPool* Pool() const { return this->Pool_; }
/**
* Get the user data.
* Only valid during the JobT::Process() call!
*/
- void* UserData() const { return Pool_->UserData(); };
+ void* UserData() const { return this->Pool_->UserData(); };
/**
* Get the worker index.
@@ -95,7 +96,7 @@ public:
* Concurrently processing jobs will never have the same WorkerIndex().
* Only valid during the JobT::Process() call!
*/
- unsigned int WorkerIndex() const { return WorkerIndex_; }
+ unsigned int WorkerIndex() const { return this->WorkerIndex_; }
/**
* Run an external read only process.
@@ -111,12 +112,11 @@ public:
//! Worker thread entry method.
void Work(cmWorkerPool* pool, unsigned int workerIndex)
{
- Pool_ = pool;
- WorkerIndex_ = workerIndex;
+ this->Pool_ = pool;
+ this->WorkerIndex_ = workerIndex;
this->Process();
}
- private:
cmWorkerPool* Pool_ = nullptr;
unsigned int WorkerIndex_ = 0;
bool Fence_ = false;
@@ -150,10 +150,9 @@ public:
{
public:
//! Does nothing
- void Process() override { Pool()->Abort(); }
+ void Process() override { this->Pool()->Abort(); }
};
-public:
// -- Methods
cmWorkerPool();
~cmWorkerPool();
@@ -161,7 +160,7 @@ public:
/**
* Number of worker threads.
*/
- unsigned int ThreadCount() const { return ThreadCount_; }
+ unsigned int ThreadCount() const { return this->ThreadCount_; }
/**
* Set the number of worker threads.
@@ -184,7 +183,7 @@ public:
*
* Only valid during Process().
*/
- void* UserData() const { return UserData_; }
+ void* UserData() const { return this->UserData_; }
// -- Job processing interface
@@ -212,7 +211,7 @@ public:
template <class T, typename... Args>
bool EmplaceJob(Args&&... args)
{
- return PushJob(cm::make_unique<T>(std::forward<Args>(args)...));
+ return this->PushJob(cm::make_unique<T>(std::forward<Args>(args)...));
}
private:
diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h
index c8adea980..e59362147 100644
--- a/Source/cmWorkingDirectory.h
+++ b/Source/cmWorkingDirectory.h
@@ -26,7 +26,7 @@ public:
bool SetDirectory(std::string const& newdir);
void Pop();
- bool Failed() const { return ResultCode != 0; }
+ bool Failed() const { return this->ResultCode != 0; }
/** \return 0 if the last attempt to set the working directory was
* successful. If it failed, the value returned will be the
@@ -34,7 +34,7 @@ public:
* of the error code can be obtained by passing the result
* to \c std::strerror().
*/
- int GetLastResult() const { return ResultCode; }
+ int GetLastResult() const { return this->ResultCode; }
std::string const& GetOldDirectory() const { return this->OldDir; }
diff --git a/Source/cmXCOFF.cxx b/Source/cmXCOFF.cxx
new file mode 100644
index 000000000..890636e06
--- /dev/null
+++ b/Source/cmXCOFF.cxx
@@ -0,0 +1,356 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmXCOFF.h"
+
+#include <algorithm>
+#include <cstddef>
+
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmStringAlgorithms.h"
+
+// Include the XCOFF format information system header.
+#ifdef _AIX
+# define __XCOFF32__
+# define __XCOFF64__
+# include <xcoff.h>
+#else
+# error "This source may be compiled only on AIX."
+#endif
+
+class cmXCOFFInternal
+{
+public:
+ // Construct and take ownership of the file stream object.
+ cmXCOFFInternal(cmXCOFF* external, std::unique_ptr<std::iostream> fin,
+ cmXCOFF::Mode mode)
+ : External(external)
+ , Stream(std::move(fin))
+ , Mode(mode)
+ {
+ }
+
+ // Destruct and delete the file stream object.
+ virtual ~cmXCOFFInternal() = default;
+
+ cmXCOFF::Mode GetMode() const { return this->Mode; }
+
+ virtual cm::optional<cm::string_view> GetLibPath() = 0;
+
+ virtual bool SetLibPath(cm::string_view libPath) = 0;
+ virtual bool RemoveLibPath() = 0;
+
+protected:
+ // Data common to all ELF class implementations.
+
+ // The external cmXCOFF object.
+ cmXCOFF* External;
+
+ // The stream from which to read.
+ std::unique_ptr<std::iostream> Stream;
+
+ cmXCOFF::Mode Mode;
+
+ // Helper methods for subclasses.
+ void SetErrorMessage(const char* msg) { this->External->ErrorMessage = msg; }
+};
+
+namespace {
+
+struct XCOFF32
+{
+ typedef struct filehdr filehdr;
+ typedef struct aouthdr aouthdr;
+ typedef struct scnhdr scnhdr;
+ typedef struct ldhdr ldhdr;
+ static const std::size_t aouthdr_size = _AOUTHSZ_EXEC;
+};
+const unsigned char xcoff32_magic[] = { 0x01, 0xDF };
+
+struct XCOFF64
+{
+ typedef struct filehdr_64 filehdr;
+ typedef struct aouthdr_64 aouthdr;
+ typedef struct scnhdr_64 scnhdr;
+ typedef struct ldhdr_64 ldhdr;
+ static const std::size_t aouthdr_size = _AOUTHSZ_EXEC_64;
+};
+const unsigned char xcoff64_magic[] = { 0x01, 0xF7 };
+
+template <typename XCOFF>
+class Impl : public cmXCOFFInternal
+{
+ static_assert(sizeof(typename XCOFF::aouthdr) == XCOFF::aouthdr_size,
+ "aouthdr structure size matches _AOUTHSZ_EXEC macro");
+
+ typename XCOFF::filehdr FileHeader;
+ typename XCOFF::aouthdr AuxHeader;
+ typename XCOFF::scnhdr LoaderSectionHeader;
+ typename XCOFF::ldhdr LoaderHeader;
+
+ std::streamoff LoaderImportFileTablePos = 0;
+ std::vector<char> LoaderImportFileTable;
+
+ bool Read(typename XCOFF::filehdr& x)
+ {
+ // FIXME: Add byte swapping if needed.
+ return static_cast<bool>(
+ this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)));
+ }
+
+ bool Read(typename XCOFF::aouthdr& x)
+ {
+ // FIXME: Add byte swapping if needed.
+ return static_cast<bool>(
+ this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)));
+ }
+
+ bool Read(typename XCOFF::scnhdr& x)
+ {
+ // FIXME: Add byte swapping if needed.
+ return static_cast<bool>(
+ this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)));
+ }
+
+ bool Read(typename XCOFF::ldhdr& x)
+ {
+ // FIXME: Add byte swapping if needed.
+ return static_cast<bool>(
+ this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)));
+ }
+
+ bool WriteLoaderImportFileTableLength(decltype(XCOFF::ldhdr::l_istlen) x)
+ {
+ // FIXME: Add byte swapping if needed.
+ return static_cast<bool>(
+ this->Stream->write(reinterpret_cast<char const*>(&x), sizeof(x)));
+ }
+
+public:
+ Impl(cmXCOFF* external, std::unique_ptr<std::iostream> fin,
+ cmXCOFF::Mode mode);
+
+ cm::optional<cm::string_view> GetLibPath() override;
+ bool SetLibPath(cm::string_view libPath) override;
+ bool RemoveLibPath() override;
+};
+
+template <typename XCOFF>
+Impl<XCOFF>::Impl(cmXCOFF* external, std::unique_ptr<std::iostream> fin,
+ cmXCOFF::Mode mode)
+ : cmXCOFFInternal(external, std::move(fin), mode)
+{
+ if (!this->Read(this->FileHeader)) {
+ this->SetErrorMessage("Failed to read XCOFF file header.");
+ return;
+ }
+ if (this->FileHeader.f_opthdr != XCOFF::aouthdr_size) {
+ this->SetErrorMessage("XCOFF auxiliary header missing.");
+ return;
+ }
+ if (!this->Read(this->AuxHeader)) {
+ this->SetErrorMessage("Failed to read XCOFF auxiliary header.");
+ return;
+ }
+ if (this->AuxHeader.o_snloader == 0) {
+ this->SetErrorMessage("XCOFF loader section missing.");
+ return;
+ }
+ if (!this->Stream->seekg((this->AuxHeader.o_snloader - 1) *
+ sizeof(typename XCOFF::scnhdr),
+ std::ios::cur)) {
+ this->SetErrorMessage("Failed to seek to XCOFF loader section header.");
+ return;
+ }
+ if (!this->Read(this->LoaderSectionHeader)) {
+ this->SetErrorMessage("Failed to read XCOFF loader section header.");
+ return;
+ }
+ if ((this->LoaderSectionHeader.s_flags & STYP_LOADER) == 0) {
+ this->SetErrorMessage("XCOFF loader section header missing STYP_LOADER.");
+ return;
+ }
+ if (!this->Stream->seekg(this->LoaderSectionHeader.s_scnptr,
+ std::ios::beg)) {
+ this->SetErrorMessage("Failed to seek to XCOFF loader header.");
+ return;
+ }
+ if (!this->Read(this->LoaderHeader)) {
+ this->SetErrorMessage("Failed to read XCOFF loader header.");
+ return;
+ }
+ this->LoaderImportFileTablePos =
+ this->LoaderSectionHeader.s_scnptr + this->LoaderHeader.l_impoff;
+ if (!this->Stream->seekg(this->LoaderImportFileTablePos)) {
+ this->SetErrorMessage(
+ "Failed to seek to XCOFF loader import file id table.");
+ return;
+ }
+ this->LoaderImportFileTable.resize(this->LoaderHeader.l_istlen);
+ if (!this->Stream->read(this->LoaderImportFileTable.data(),
+ this->LoaderImportFileTable.size())) {
+ this->SetErrorMessage("Failed to read XCOFF loader import file id table.");
+ return;
+ }
+}
+
+template <typename XCOFF>
+cm::optional<cm::string_view> Impl<XCOFF>::GetLibPath()
+{
+ cm::optional<cm::string_view> result;
+ auto end = std::find(this->LoaderImportFileTable.begin(),
+ this->LoaderImportFileTable.end(), '\0');
+ if (end != this->LoaderImportFileTable.end()) {
+ result = cm::string_view(this->LoaderImportFileTable.data(),
+ end - this->LoaderImportFileTable.begin());
+ }
+ return result;
+}
+
+template <typename XCOFF>
+bool Impl<XCOFF>::SetLibPath(cm::string_view libPath)
+{
+ // The new LIBPATH must end in the standard AIX LIBPATH.
+#define CM_AIX_LIBPATH "/usr/lib:/lib"
+ std::string libPathBuf;
+ if (libPath != CM_AIX_LIBPATH &&
+ !cmHasLiteralSuffix(libPath, ":" CM_AIX_LIBPATH)) {
+ libPathBuf = std::string(libPath);
+ if (!libPathBuf.empty() && libPathBuf.back() != ':') {
+ libPathBuf.push_back(':');
+ }
+ libPathBuf += CM_AIX_LIBPATH;
+ libPath = libPathBuf;
+ }
+#undef CM_AIX_LIBPATH
+
+ auto oldEnd = std::find(this->LoaderImportFileTable.begin(),
+ this->LoaderImportFileTable.end(), '\0');
+ if (oldEnd == this->LoaderImportFileTable.end()) {
+ this->SetErrorMessage("XCOFF loader import file id table is invalid.");
+ return false;
+ }
+ if ((this->LoaderImportFileTable.begin() + libPath.size()) > oldEnd) {
+ this->SetErrorMessage("XCOFF loader import file id table is too small.");
+ return false;
+ }
+
+ {
+ std::vector<char> ift;
+ ift.reserve(this->LoaderImportFileTable.size());
+ // Start with the new LIBPATH.
+ ift.insert(ift.end(), libPath.begin(), libPath.end());
+ // Add the rest of the original table.
+ ift.insert(ift.end(), oldEnd, this->LoaderImportFileTable.end());
+ // If the new table is shorter, zero out the leftover space.
+ ift.resize(this->LoaderImportFileTable.size(), 0);
+ this->LoaderHeader.l_istlen =
+ static_cast<decltype(XCOFF::ldhdr::l_istlen)>(ift.size());
+ this->LoaderImportFileTable = std::move(ift);
+ }
+
+ if (!this->Stream->seekp(this->LoaderSectionHeader.s_scnptr +
+ offsetof(typename XCOFF::ldhdr, l_istlen),
+ std::ios::beg)) {
+ this->SetErrorMessage(
+ "Failed to seek to XCOFF loader header import file id table length.");
+ return false;
+ }
+ if (!this->WriteLoaderImportFileTableLength(this->LoaderHeader.l_istlen)) {
+ this->SetErrorMessage(
+ "Failed to write XCOFF loader header import file id table length.");
+ return false;
+ }
+ if (!this->Stream->seekp(this->LoaderImportFileTablePos, std::ios::beg)) {
+ this->SetErrorMessage(
+ "Failed to seek to XCOFF loader import file id table.");
+ return false;
+ }
+ if (!this->Stream->write(this->LoaderImportFileTable.data(),
+ this->LoaderImportFileTable.size())) {
+ this->SetErrorMessage(
+ "Failed to write XCOFF loader import file id table.");
+ return false;
+ }
+
+ return true;
+}
+
+template <typename XCOFF>
+bool Impl<XCOFF>::RemoveLibPath()
+{
+ return this->SetLibPath({});
+}
+}
+
+//============================================================================
+// External class implementation.
+
+cmXCOFF::cmXCOFF(const char* fname, Mode mode)
+{
+ // Try to open the file.
+ std::ios::openmode fmode = std::ios::in | std::ios::binary;
+ if (mode == Mode::ReadWrite) {
+ fmode |= std::ios::out;
+ }
+ auto f = cm::make_unique<cmsys::fstream>(fname, fmode);
+
+ // Quit now if the file could not be opened.
+ if (!f || !*f) {
+ this->ErrorMessage = "Error opening input file.";
+ return;
+ }
+
+ // Read the XCOFF magic number.
+ unsigned char magic[2];
+ if (!f->read(reinterpret_cast<char*>(magic), sizeof(magic))) {
+ this->ErrorMessage = "Error reading XCOFF magic number.";
+ return;
+ }
+ if (!f->seekg(0)) {
+ this->ErrorMessage = "Error seeking to beginning of file.";
+ return;
+ }
+
+ // Check the XCOFF type.
+ if (magic[0] == xcoff32_magic[0] && magic[1] == xcoff32_magic[1]) {
+ this->Internal = cm::make_unique<Impl<XCOFF32>>(this, std::move(f), mode);
+ } else if (magic[0] == xcoff64_magic[0] && magic[1] == xcoff64_magic[1]) {
+ this->Internal = cm::make_unique<Impl<XCOFF64>>(this, std::move(f), mode);
+ } else {
+ this->ErrorMessage = "File is not a XCOFF32 or XCOFF64 binary.";
+ }
+}
+
+cmXCOFF::~cmXCOFF() = default;
+
+cmXCOFF::cmXCOFF(cmXCOFF&&) = default;
+cmXCOFF& cmXCOFF::operator=(cmXCOFF&&) = default;
+
+bool cmXCOFF::Valid() const
+{
+ return this->Internal && this->ErrorMessage.empty();
+}
+
+cm::optional<cm::string_view> cmXCOFF::GetLibPath() const
+{
+ cm::optional<cm::string_view> result;
+ if (this->Valid()) {
+ result = this->Internal->GetLibPath();
+ }
+ return result;
+}
+
+bool cmXCOFF::SetLibPath(cm::string_view libPath)
+{
+ return this->Valid() && this->Internal->GetMode() == Mode::ReadWrite &&
+ this->Internal->SetLibPath(libPath);
+}
+
+bool cmXCOFF::RemoveLibPath()
+{
+ return this->Valid() && this->Internal->GetMode() == Mode::ReadWrite &&
+ this->Internal->RemoveLibPath();
+}
diff --git a/Source/cmXCOFF.h b/Source/cmXCOFF.h
new file mode 100644
index 000000000..16cda9daf
--- /dev/null
+++ b/Source/cmXCOFF.h
@@ -0,0 +1,65 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <memory>
+#include <string>
+
+#include <cm/optional>
+#include <cm/string_view>
+
+#if !defined(CMake_USE_XCOFF_PARSER)
+# error "This file may be included only if CMake_USE_XCOFF_PARSER is enabled."
+#endif
+
+class cmXCOFFInternal;
+
+/** \class cmXCOFF
+ * \brief XCOFF parser.
+ */
+class cmXCOFF
+{
+public:
+ enum class Mode
+ {
+ ReadOnly,
+ ReadWrite
+ };
+
+ /** Construct with the name of the XCOFF input file to parse. */
+ cmXCOFF(const char* fname, Mode = Mode::ReadOnly);
+
+ /** Destruct. */
+ ~cmXCOFF();
+
+ cmXCOFF(cmXCOFF&&);
+ cmXCOFF(cmXCOFF const&) = delete;
+ cmXCOFF& operator=(cmXCOFF&&);
+ cmXCOFF& operator=(cmXCOFF const&) = delete;
+
+ /** Get the error message if any. */
+ std::string const& GetErrorMessage() const { return this->ErrorMessage; }
+
+ /** Boolean conversion. True if the XCOFF file is valid. */
+ explicit operator bool() const { return this->Valid(); }
+
+ /** Get the LIBPATH (RPATH) parsed from the file, if any. */
+ cm::optional<cm::string_view> GetLibPath() const;
+
+ /** Set the LIBPATH (RPATH).
+ Works only if cmXCOFF was constructed with Mode::ReadWrite. */
+ bool SetLibPath(cm::string_view libPath);
+
+ /** Remove the LIBPATH (RPATH).
+ Works only if cmXCOFF was constructed with Mode::ReadWrite. */
+ bool RemoveLibPath();
+
+private:
+ friend class cmXCOFFInternal;
+ bool Valid() const;
+ std::unique_ptr<cmXCOFFInternal> Internal;
+ std::string ErrorMessage;
+};
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index ac5be3f9e..dd5e86ea3 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -81,6 +81,13 @@ public:
void SetObject(cmXCodeObject* value) { this->Object = value; }
cmXCodeObject* GetObject() { return this->Object; }
void AddObject(cmXCodeObject* value) { this->List.push_back(value); }
+ size_t GetObjectCount() { return this->List.size(); }
+ void InsertObject(size_t position, cmXCodeObject* value)
+ {
+ if (position < GetObjectCount()) {
+ this->List.insert(this->List.begin() + position, value);
+ }
+ }
void PrependObject(cmXCodeObject* value)
{
this->List.insert(this->List.begin(), value);
diff --git a/Source/cmXMLSafe.cxx b/Source/cmXMLSafe.cxx
index 8cd5f6e0d..d31a239c7 100644
--- a/Source/cmXMLSafe.cxx
+++ b/Source/cmXMLSafe.cxx
@@ -28,7 +28,7 @@ cmXMLSafe& cmXMLSafe::Quotes(bool b)
return *this;
}
-std::string cmXMLSafe::str()
+std::string cmXMLSafe::str() const
{
std::ostringstream ss;
ss << *this;
diff --git a/Source/cmXMLSafe.h b/Source/cmXMLSafe.h
index 9b4c539e5..21bd19aee 100644
--- a/Source/cmXMLSafe.h
+++ b/Source/cmXMLSafe.h
@@ -24,7 +24,7 @@ public:
cmXMLSafe& Quotes(bool b = true);
/** Get the escaped data as a string. */
- std::string str();
+ std::string str() const;
private:
char const* Data;
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index a16c4c871..6e8eeb730 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -75,7 +75,6 @@ private:
void CloseStartElement();
-private:
static cmXMLSafe SafeAttribute(const char* value) { return { value }; }
static cmXMLSafe SafeAttribute(std::string const& value)
@@ -121,7 +120,6 @@ private:
return value;
}
-private:
std::ostream& Output;
std::stack<std::string, std::vector<std::string>> Elements;
std::string IndentationElement;
@@ -140,9 +138,9 @@ public:
cmXMLDocument(cmXMLWriter& xml)
: xmlwr(xml)
{
- xmlwr.StartDocument();
+ this->xmlwr.StartDocument();
}
- ~cmXMLDocument() { xmlwr.EndDocument(); }
+ ~cmXMLDocument() { this->xmlwr.EndDocument(); }
cmXMLDocument(const cmXMLDocument&) = delete;
cmXMLDocument& operator=(const cmXMLDocument&) = delete;
@@ -157,19 +155,19 @@ public:
cmXMLElement(cmXMLWriter& xml, const char* tag)
: xmlwr(xml)
{
- xmlwr.StartElement(tag);
+ this->xmlwr.StartElement(tag);
}
cmXMLElement(cmXMLElement& par, const char* tag)
: xmlwr(par.xmlwr)
{
- xmlwr.StartElement(tag);
+ this->xmlwr.StartElement(tag);
}
cmXMLElement(cmXMLDocument& doc, const char* tag)
: xmlwr(doc.xmlwr)
{
- xmlwr.StartElement(tag);
+ this->xmlwr.StartElement(tag);
}
- ~cmXMLElement() { xmlwr.EndElement(); }
+ ~cmXMLElement() { this->xmlwr.EndElement(); }
cmXMLElement(const cmXMLElement&) = delete;
cmXMLElement& operator=(const cmXMLElement&) = delete;
@@ -177,20 +175,20 @@ public:
template <typename T>
cmXMLElement& Attribute(const char* name, T const& value)
{
- xmlwr.Attribute(name, value);
+ this->xmlwr.Attribute(name, value);
return *this;
}
template <typename T>
void Content(T const& content)
{
- xmlwr.Content(content);
+ this->xmlwr.Content(content);
}
template <typename T>
void Element(std::string const& name, T const& value)
{
- xmlwr.Element(name, value);
+ this->xmlwr.Element(name, value);
}
- void Comment(const char* comment) { xmlwr.Comment(comment); }
+ void Comment(const char* comment) { this->xmlwr.Comment(comment); }
private:
cmXMLWriter& xmlwr;
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index 122e02283..15f83e0f7 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -35,7 +35,7 @@ codecvt::codecvt(Encoding e)
case codecvt::None:
// No encoding
default:
- m_noconv = true;
+ this->m_noconv = true;
}
}
@@ -43,7 +43,7 @@ codecvt::~codecvt() = default;
bool codecvt::do_always_noconv() const throw()
{
- return m_noconv;
+ return this->m_noconv;
}
std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
@@ -53,7 +53,7 @@ std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
{
from_next = from;
to_next = to;
- if (m_noconv) {
+ if (this->m_noconv) {
return std::codecvt_base::noconv;
}
#if defined(_WIN32)
@@ -130,7 +130,7 @@ std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to,
char*& to_next) const
{
to_next = to;
- if (m_noconv) {
+ if (this->m_noconv) {
return std::codecvt_base::noconv;
}
#if defined(_WIN32)
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index e655634ef..4b5739572 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -29,6 +29,7 @@
#include "cm_sys_stat.h"
#include "cmCMakePresetsFile.h"
+#include "cmCommandLineArgument.h"
#include "cmCommands.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
@@ -132,6 +133,13 @@ namespace {
using JsonValueMapType = std::unordered_map<std::string, Json::Value>;
#endif
+auto IgnoreAndTrueLambda = [](std::string const&, cmake*) -> bool {
+ return true;
+};
+
+using CommandArgument =
+ cmCommandLineArgument<bool(std::string const& value, cmake* state)>;
+
} // namespace
static bool cmakeCheckStampFile(const std::string& stampName);
@@ -200,8 +208,9 @@ 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", "m", "M", "mm" });
+ setupExts(
+ this->CLikeSourceFileExtensions,
+ { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "mpp", "m", "M", "mm" });
setupExts(this->HeaderFileExtensions,
{ "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" });
setupExts(this->CudaFileExtensions, { "cu" });
@@ -263,7 +272,7 @@ Json::Value cmake::ReportCapabilitiesJson() const
}
obj["generators"] = generators;
obj["fileApi"] = cmFileAPI::ReportCapabilities();
- obj["serverMode"] = true;
+ obj["serverMode"] = false;
return obj;
}
@@ -386,152 +395,145 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
{
auto findPackageMode = false;
auto seenScriptOption = false;
- for (unsigned int i = 1; i < args.size(); ++i) {
- std::string const& arg = args[i];
- if (cmHasLiteralPrefix(arg, "-D")) {
- std::string entry = arg.substr(2);
- if (entry.empty()) {
- ++i;
- if (i < args.size()) {
- entry = args[i];
- } else {
- cmSystemTools::Error("-D must be followed with VAR=VALUE.");
- return false;
- }
- }
- std::string var;
- std::string value;
- cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
- if (cmState::ParseCacheEntry(entry, var, value, type)) {
+
+ auto DefineLambda = [](std::string const& entry, cmake* state) -> bool {
+ std::string var;
+ std::string value;
+ cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
+ if (cmState::ParseCacheEntry(entry, var, value, type)) {
#ifndef CMAKE_BOOTSTRAP
- this->UnprocessedPresetVariables.erase(var);
+ state->UnprocessedPresetVariables.erase(var);
#endif
- this->ProcessCacheArg(var, value, type);
- } else {
- cmSystemTools::Error("Parse error in command line argument: " + arg +
- "\n" + "Should be: VAR:type=value\n");
- return false;
- }
- } else if (cmHasLiteralPrefix(arg, "-W")) {
- std::string entry = arg.substr(2);
- if (entry.empty()) {
- ++i;
- if (i < args.size()) {
- entry = args[i];
- } else {
- cmSystemTools::Error("-W must be followed with [no-]<name>.");
- return false;
- }
- }
+ state->ProcessCacheArg(var, value, type);
+ } else {
+ cmSystemTools::Error(cmStrCat("Parse error in command line argument: ",
+ entry, "\n Should be: VAR:type=value\n"));
+ return false;
+ }
+ return true;
+ };
- std::string name;
- bool foundNo = false;
- bool foundError = false;
- unsigned int nameStartPosition = 0;
+ auto WarningLambda = [](cm::string_view entry, cmake* state) -> bool {
+ bool foundNo = false;
+ bool foundError = false;
- if (entry.find("no-", nameStartPosition) == 0) {
- foundNo = true;
- nameStartPosition += 3;
- }
+ if (cmHasLiteralPrefix(entry, "no-")) {
+ foundNo = true;
+ entry.remove_prefix(3);
+ }
- if (entry.find("error=", nameStartPosition) == 0) {
- foundError = true;
- nameStartPosition += 6;
- }
+ if (cmHasLiteralPrefix(entry, "error=")) {
+ foundError = true;
+ entry.remove_prefix(6);
+ }
- name = entry.substr(nameStartPosition);
- if (name.empty()) {
- cmSystemTools::Error("No warning name provided.");
- return false;
- }
+ if (entry.empty()) {
+ cmSystemTools::Error("No warning name provided.");
+ return false;
+ }
- if (!foundNo && !foundError) {
- // -W<name>
- this->DiagLevels[name] = std::max(this->DiagLevels[name], DIAG_WARN);
- } else if (foundNo && !foundError) {
- // -Wno<name>
- this->DiagLevels[name] = DIAG_IGNORE;
- } else if (!foundNo && foundError) {
- // -Werror=<name>
- this->DiagLevels[name] = DIAG_ERROR;
- } else {
- // -Wno-error=<name>
- this->DiagLevels[name] = std::min(this->DiagLevels[name], DIAG_WARN);
- }
- } else if (cmHasLiteralPrefix(arg, "-U")) {
- std::string entryPattern = arg.substr(2);
- if (entryPattern.empty()) {
- ++i;
- if (i < args.size()) {
- entryPattern = args[i];
- } else {
- cmSystemTools::Error("-U must be followed with VAR.");
- return false;
- }
+ std::string const name = std::string(entry);
+ if (!foundNo && !foundError) {
+ // -W<name>
+ state->DiagLevels[name] = std::max(state->DiagLevels[name], DIAG_WARN);
+ } else if (foundNo && !foundError) {
+ // -Wno<name>
+ state->DiagLevels[name] = DIAG_IGNORE;
+ } else if (!foundNo && foundError) {
+ // -Werror=<name>
+ state->DiagLevels[name] = DIAG_ERROR;
+ } else {
+ // -Wno-error=<name>
+ // This can downgrade an error to a warning, but should not enable
+ // or disable a warning in the first place.
+ auto dli = state->DiagLevels.find(name);
+ if (dli != state->DiagLevels.end()) {
+ dli->second = std::min(dli->second, DIAG_WARN);
}
- cmsys::RegularExpression regex(
- cmsys::Glob::PatternToRegex(entryPattern, true, true));
- // go through all cache entries and collect the vars which will be
- // removed
- std::vector<std::string> entriesToDelete;
- std::vector<std::string> cacheKeys = this->State->GetCacheEntryKeys();
- for (std::string const& ck : cacheKeys) {
- cmStateEnums::CacheEntryType t = this->State->GetCacheEntryType(ck);
- if (t != cmStateEnums::STATIC) {
- if (regex.find(ck)) {
- entriesToDelete.push_back(ck);
- }
+ }
+ return true;
+ };
+
+ auto UnSetLambda = [](std::string const& entryPattern,
+ cmake* state) -> bool {
+ cmsys::RegularExpression regex(
+ cmsys::Glob::PatternToRegex(entryPattern, true, true));
+ // go through all cache entries and collect the vars which will be
+ // removed
+ std::vector<std::string> entriesToDelete;
+ std::vector<std::string> cacheKeys = state->State->GetCacheEntryKeys();
+ for (std::string const& ck : cacheKeys) {
+ cmStateEnums::CacheEntryType t = state->State->GetCacheEntryType(ck);
+ if (t != cmStateEnums::STATIC) {
+ if (regex.find(ck)) {
+ entriesToDelete.push_back(ck);
}
}
+ }
- // now remove them from the cache
- for (std::string const& currentEntry : entriesToDelete) {
+ // now remove them from the cache
+ for (std::string const& currentEntry : entriesToDelete) {
#ifndef CMAKE_BOOTSTRAP
- this->UnprocessedPresetVariables.erase(currentEntry);
+ state->UnprocessedPresetVariables.erase(currentEntry);
#endif
- this->State->RemoveCacheEntry(currentEntry);
- }
- } else if (cmHasLiteralPrefix(arg, "-C")) {
- std::string path = arg.substr(2);
- if (path.empty()) {
- ++i;
- if (i < args.size()) {
- path = args[i];
- } else {
- cmSystemTools::Error("-C must be followed by a file name.");
- return false;
- }
- }
- cmSystemTools::Stdout("loading initial cache file " + path + "\n");
- // Resolve script path specified on command line relative to $PWD.
- path = cmSystemTools::CollapseFullPath(path);
- this->ReadListFile(args, path);
- } else if (cmHasLiteralPrefix(arg, "-P")) {
- i++;
- if (i >= args.size()) {
- cmSystemTools::Error("-P must be followed by a file name.");
- return false;
- }
- std::string path = args[i];
- if (path.empty()) {
- cmSystemTools::Error("No cmake script provided.");
- return false;
- }
- // Register fake project commands that hint misuse in script mode.
- GetProjectCommandsInScriptMode(this->GetState());
- // Documented behaviour of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be
- // set to $PWD for -P mode.
- this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
- this->SetHomeOutputDirectory(
- cmSystemTools::GetCurrentWorkingDirectory());
- this->ReadListFile(args, path);
- seenScriptOption = true;
- } else if (arg == "--" && seenScriptOption) {
+ state->State->RemoveCacheEntry(currentEntry);
+ }
+ return true;
+ };
+
+ 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
+ // set to $PWD for -P mode.
+ state->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ state->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ state->ReadListFile(args, path);
+ seenScriptOption = true;
+ return true;
+ };
+
+ std::vector<CommandArgument> arguments = {
+ CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
+ CommandArgument::Values::One, DefineLambda },
+ CommandArgument{ "-W", "-W must be followed with [no-]<name>.",
+ CommandArgument::Values::One, 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{ "-P", "-P must be followed by a file name.",
+ CommandArgument::Values::One, ScriptLambda },
+ CommandArgument{ "--find-package", CommandArgument::Values::Zero,
+ [&](std::string const&, cmake*) -> bool {
+ findPackageMode = true;
+ return true;
+ } },
+ };
+ for (decltype(args.size()) i = 1; i < args.size(); ++i) {
+ std::string const& arg = args[i];
+
+ if (arg == "--" && seenScriptOption) {
// Stop processing CMake args and avoid possible errors
// when arbitrary args are given to CMake script.
break;
- } else if (cmHasLiteralPrefix(arg, "--find-package")) {
- findPackageMode = true;
+ }
+ for (auto const& m : arguments) {
+ if (m.matches(arg)) {
+ const bool parsedCorrectly = m.parse(arg, i, args, this);
+ if (!parsedCorrectly) {
+ return false;
+ }
+ }
}
}
@@ -724,261 +726,375 @@ void cmake::LoadEnvironmentPresets()
readGeneratorVar("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset);
}
+namespace {
+enum class ListPresets
+{
+ None,
+ Configure,
+ Build,
+ Test,
+ All,
+};
+}
+
// Parse the args
void cmake::SetArgs(const std::vector<std::string>& args)
{
bool haveToolset = false;
bool havePlatform = false;
bool haveBArg = false;
+ bool scriptMode = false;
+ std::string possibleUnknownArg;
#if !defined(CMAKE_BOOTSTRAP)
std::string profilingFormat;
std::string profilingOutput;
std::string presetName;
- bool listPresets = false;
+
+ ListPresets listPresets = ListPresets::None;
#endif
- for (unsigned int i = 1; i < args.size(); ++i) {
- std::string const& arg = args[i];
- if (cmHasLiteralPrefix(arg, "-H") || cmHasLiteralPrefix(arg, "-S")) {
- std::string path = arg.substr(2);
- if (path.empty()) {
- ++i;
- if (i >= args.size()) {
- cmSystemTools::Error("No source directory specified for -S");
- return;
- }
- path = args[i];
- if (path[0] == '-') {
- cmSystemTools::Error("No source directory specified for -S");
- return;
- }
- }
- path = cmSystemTools::CollapseFullPath(path);
- cmSystemTools::ConvertToUnixSlashes(path);
- this->SetHomeDirectory(path);
- // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
- // NOLINTNEXTLINE(bugprone-branch-clone)
- } else if (cmHasLiteralPrefix(arg, "-O")) {
- // There is no local generate anymore. Ignore -O option.
- } else if (cmHasLiteralPrefix(arg, "-B")) {
- std::string path = arg.substr(2);
- if (path.empty()) {
- ++i;
- if (i >= args.size()) {
- cmSystemTools::Error("No build directory specified for -B");
- return;
- }
- path = args[i];
- if (path[0] == '-') {
- cmSystemTools::Error("No build directory specified for -B");
- return;
- }
- }
+ auto SourceArgLambda = [](std::string const& value, cmake* state) -> bool {
+ std::string path = cmSystemTools::CollapseFullPath(value);
+ cmSystemTools::ConvertToUnixSlashes(path);
+ state->SetHomeDirectory(path);
+ return true;
+ };
+
+ auto BuildArgLambda = [&](std::string const& value, cmake* state) -> bool {
+ std::string path = cmSystemTools::CollapseFullPath(value);
+ cmSystemTools::ConvertToUnixSlashes(path);
+ state->SetHomeOutputDirectory(path);
+ haveBArg = true;
+ return true;
+ };
- path = cmSystemTools::CollapseFullPath(path);
- cmSystemTools::ConvertToUnixSlashes(path);
- this->SetHomeOutputDirectory(path);
- haveBArg = true;
- } else if ((i < args.size() - 2) &&
- cmHasLiteralPrefix(arg, "--check-build-system")) {
- this->CheckBuildSystemArgument = args[++i];
- this->ClearBuildSystem = (atoi(args[++i].c_str()) > 0);
- } else if ((i < args.size() - 1) &&
- cmHasLiteralPrefix(arg, "--check-stamp-file")) {
- this->CheckStampFile = args[++i];
- } else if ((i < args.size() - 1) &&
- cmHasLiteralPrefix(arg, "--check-stamp-list")) {
- this->CheckStampList = args[++i];
- } else if (arg == "--regenerate-during-build"_s) {
- this->RegenerateDuringBuild = true;
+ auto PlatformLambda = [&](std::string const& value, cmake* state) -> bool {
+ if (havePlatform) {
+ cmSystemTools::Error("Multiple -A options not allowed");
+ return false;
}
-#if defined(CMAKE_HAVE_VS_GENERATORS)
- else if ((i < args.size() - 1) &&
- cmHasLiteralPrefix(arg, "--vs-solution-file")) {
- this->VSSolutionFile = args[++i];
+ state->SetGeneratorPlatform(value);
+ havePlatform = true;
+ return true;
+ };
+
+ auto ToolsetLamda = [&](std::string const& value, cmake* state) -> bool {
+ if (haveToolset) {
+ cmSystemTools::Error("Multiple -T options not allowed");
+ return false;
}
+ state->SetGeneratorToolset(value);
+ haveToolset = true;
+ return true;
+ };
+
+ std::vector<CommandArgument> arguments = {
+ CommandArgument{ "-S", "No source directory specified for -S",
+ CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument{ "-H", "No source directory specified for -H",
+ CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument{ "-O", CommandArgument::Values::Zero,
+ IgnoreAndTrueLambda },
+ CommandArgument{ "-B", "No build directory specified for -B",
+ CommandArgument::Values::One, BuildArgLambda },
+ CommandArgument{ "-P", "-P must be followed by a file name.",
+ CommandArgument::Values::One,
+ [&](std::string const&, cmake*) -> bool {
+ scriptMode = true;
+ return true;
+ } },
+ CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
+ CommandArgument::Values::One, 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{ "-W", "-W must be followed with [no-]<name>.",
+ CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument{ "-A", "No platform specified for -A",
+ CommandArgument::Values::One, PlatformLambda },
+ CommandArgument{ "-T", "No toolset specified for -T",
+ CommandArgument::Values::One, ToolsetLamda },
+
+ CommandArgument{ "--check-build-system", CommandArgument::Values::Two,
+ [](std::string const& value, cmake* state) -> bool {
+ std::vector<std::string> values = cmExpandedList(value);
+ state->CheckBuildSystemArgument = values[0];
+ state->ClearBuildSystem = (atoi(values[1].c_str()) > 0);
+ return true;
+ } },
+ CommandArgument{ "--check-stamp-file", CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ state->CheckStampFile = value;
+ return true;
+ } },
+ CommandArgument{ "--check-stamp-list", CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ state->CheckStampList = value;
+ return true;
+ } },
+ CommandArgument{ "--regenerate-during-build",
+ CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ state->RegenerateDuringBuild = true;
+ return true;
+ } },
+
+ CommandArgument{ "--find-package", CommandArgument::Values::Zero,
+ IgnoreAndTrueLambda },
+
+ CommandArgument{ "--graphviz", "No file specified for --graphviz",
+ CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ std::string path =
+ cmSystemTools::CollapseFullPath(value);
+ cmSystemTools::ConvertToUnixSlashes(path);
+ state->GraphVizFile = path;
+ return true;
+ } },
+
+ CommandArgument{ "--debug-trycompile", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout << "debug trycompile on\n";
+ state->DebugTryCompileOn();
+ return true;
+ } },
+ CommandArgument{ "--debug-output", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout << "Running with debug output on.\n";
+ state->SetDebugOutputOn(true);
+ return true;
+ } },
+
+ CommandArgument{ "--log-level", "Invalid level specified for --log-level",
+ CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ const auto logLevel = StringToLogLevel(value);
+ if (logLevel == LogLevel::LOG_UNDEFINED) {
+ cmSystemTools::Error(
+ "Invalid level specified for --log-level");
+ return false;
+ }
+ state->SetLogLevel(logLevel);
+ state->LogLevelWasSetViaCLI = true;
+ return true;
+ } },
+ // This is supported for backward compatibility. This option only
+ // appeared in the 3.15.x release series and was renamed to
+ // --log-level in 3.16.0
+ CommandArgument{ "--loglevel", "Invalid level specified for --loglevel",
+ CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ const auto logLevel = StringToLogLevel(value);
+ if (logLevel == LogLevel::LOG_UNDEFINED) {
+ cmSystemTools::Error(
+ "Invalid level specified for --loglevel");
+ return false;
+ }
+ state->SetLogLevel(logLevel);
+ state->LogLevelWasSetViaCLI = true;
+ return true;
+ } },
+
+ CommandArgument{ "--log-context", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ state->SetShowLogContext(true);
+ return true;
+ } },
+ CommandArgument{
+ "--debug-find", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout << "Running with debug output on for the `find` commands.\n";
+ state->SetDebugFindOutputOn(true);
+ return true;
+ } },
+ CommandArgument{ "--trace-expand", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout << "Running with expanded trace output on.\n";
+ state->SetTrace(true);
+ state->SetTraceExpand(true);
+ return true;
+ } },
+ CommandArgument{ "--trace-format", CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ state->SetTrace(true);
+ const auto traceFormat = StringToTraceFormat(value);
+ if (traceFormat == TraceFormat::TRACE_UNDEFINED) {
+ cmSystemTools::Error(
+ "Invalid format specified for --trace-format. "
+ "Valid formats are human, json-v1.");
+ return false;
+ }
+ state->SetTraceFormat(traceFormat);
+ return true;
+ } },
+ CommandArgument{ "--trace-source", CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ std::string file(value);
+ cmSystemTools::ConvertToUnixSlashes(file);
+ state->AddTraceSource(file);
+ state->SetTrace(true);
+ return true;
+ } },
+ CommandArgument{ "--trace-redirect", CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ std::string file(value);
+ cmSystemTools::ConvertToUnixSlashes(file);
+ state->SetTraceFile(file);
+ state->SetTrace(true);
+ return true;
+ } },
+ CommandArgument{ "--trace", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout << "Running with trace output on.\n";
+ state->SetTrace(true);
+ state->SetTraceExpand(false);
+ return true;
+ } },
+ CommandArgument{ "--warn-uninitialized", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout << "Warn about uninitialized values.\n";
+ state->SetWarnUninitialized(true);
+ return true;
+ } },
+ CommandArgument{ "--warn-unused-vars", CommandArgument::Values::Zero,
+ IgnoreAndTrueLambda }, // Option was removed.
+ CommandArgument{ "--no-warn-unused-cli", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout
+ << "Not searching for unused variables given on the "
+ << "command line.\n";
+ state->SetWarnUnusedCli(false);
+ return true;
+ } },
+ CommandArgument{
+ "--check-system-vars", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+ std::cout << "Also check system files when warning about unused and "
+ << "uninitialized variables.\n";
+ state->SetCheckSystemVars(true);
+ return true;
+ } }
+ };
+
+#if defined(CMAKE_HAVE_VS_GENERATORS)
+ arguments.emplace_back("--vs-solution-file", CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+ state->VSSolutionFile = value;
+ return true;
+ });
#endif
- else if (cmHasLiteralPrefix(arg, "-D") || cmHasLiteralPrefix(arg, "-U") ||
- cmHasLiteralPrefix(arg, "-C")) {
- // skip for now
- // in case '-[DUC] argval' var' is given, also skip the next
- // in case '-[DUC]argval' is given, don't skip the next
- if (arg.size() == 2) {
- ++i;
- }
- // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
- // NOLINTNEXTLINE(bugprone-branch-clone)
- } else if (cmHasLiteralPrefix(arg, "-P")) {
- // skip for now
- i++;
- } else if (cmHasLiteralPrefix(arg, "--find-package")) {
- // skip for now
- i++;
- } else if (cmHasLiteralPrefix(arg, "-W")) {
- // skip for now
- } else if (cmHasLiteralPrefix(arg, "--graphviz=")) {
- std::string path = arg.substr(strlen("--graphviz="));
- path = cmSystemTools::CollapseFullPath(path);
- cmSystemTools::ConvertToUnixSlashes(path);
- this->GraphVizFile = path;
- if (this->GraphVizFile.empty()) {
- cmSystemTools::Error("No file specified for --graphviz");
- return;
- }
- } else if (cmHasLiteralPrefix(arg, "--debug-trycompile")) {
- std::cout << "debug trycompile on\n";
- this->DebugTryCompileOn();
- } else if (cmHasLiteralPrefix(arg, "--debug-output")) {
- std::cout << "Running with debug output on.\n";
- this->SetDebugOutputOn(true);
- } else if (cmHasLiteralPrefix(arg, "--log-level=")) {
- const auto logLevel =
- StringToLogLevel(arg.substr(sizeof("--log-level=") - 1));
- if (logLevel == LogLevel::LOG_UNDEFINED) {
- cmSystemTools::Error("Invalid level specified for --log-level");
- return;
- }
- this->SetLogLevel(logLevel);
- this->LogLevelWasSetViaCLI = true;
- } else if (cmHasLiteralPrefix(arg, "--loglevel=")) {
- // This is supported for backward compatibility. This option only
- // appeared in the 3.15.x release series and was renamed to
- // --log-level in 3.16.0
- const auto logLevel =
- StringToLogLevel(arg.substr(sizeof("--loglevel=") - 1));
- if (logLevel == LogLevel::LOG_UNDEFINED) {
- cmSystemTools::Error("Invalid level specified for --loglevel");
- return;
- }
- this->SetLogLevel(logLevel);
- this->LogLevelWasSetViaCLI = true;
- } else if (arg == "--log-context"_s) {
- this->SetShowLogContext(true);
- } else if (cmHasLiteralPrefix(arg, "--debug-find")) {
- std::cout << "Running with debug output on for the `find` commands.\n";
- this->SetDebugFindOutputOn(true);
- } else if (cmHasLiteralPrefix(arg, "--trace-expand")) {
- std::cout << "Running with expanded trace output on.\n";
- this->SetTrace(true);
- this->SetTraceExpand(true);
- } else if (cmHasLiteralPrefix(arg, "--trace-format=")) {
- this->SetTrace(true);
- const auto traceFormat =
- StringToTraceFormat(arg.substr(strlen("--trace-format=")));
- if (traceFormat == TraceFormat::TRACE_UNDEFINED) {
- cmSystemTools::Error("Invalid format specified for --trace-format. "
- "Valid formats are human, json-v1.");
- return;
- }
- this->SetTraceFormat(traceFormat);
- } else if (cmHasLiteralPrefix(arg, "--trace-source=")) {
- std::string file = arg.substr(strlen("--trace-source="));
- cmSystemTools::ConvertToUnixSlashes(file);
- this->AddTraceSource(file);
- this->SetTrace(true);
- } else if (cmHasLiteralPrefix(arg, "--trace-redirect=")) {
- std::string file = arg.substr(strlen("--trace-redirect="));
- cmSystemTools::ConvertToUnixSlashes(file);
- this->SetTraceFile(file);
- this->SetTrace(true);
- } else if (cmHasLiteralPrefix(arg, "--trace")) {
- std::cout << "Running with trace output on.\n";
- this->SetTrace(true);
- this->SetTraceExpand(false);
- } else if (cmHasLiteralPrefix(arg, "--warn-uninitialized")) {
- std::cout << "Warn about uninitialized values.\n";
- this->SetWarnUninitialized(true);
- } else if (cmHasLiteralPrefix(arg, "--warn-unused-vars")) {
- // Option was removed.
- } else if (cmHasLiteralPrefix(arg, "--no-warn-unused-cli")) {
- std::cout << "Not searching for unused variables given on the "
- << "command line.\n";
- this->SetWarnUnusedCli(false);
- } else if (cmHasLiteralPrefix(arg, "--check-system-vars")) {
- std::cout << "Also check system files when warning about unused and "
- << "uninitialized variables.\n";
- this->SetCheckSystemVars(true);
- } else if (cmHasLiteralPrefix(arg, "-A")) {
- std::string value = arg.substr(2);
- if (value.empty()) {
- ++i;
- if (i >= args.size()) {
- cmSystemTools::Error("No platform specified for -A");
- return;
- }
- value = args[i];
- }
- if (havePlatform) {
- cmSystemTools::Error("Multiple -A options not allowed");
- return;
- }
- this->SetGeneratorPlatform(value);
- havePlatform = true;
- } else if (cmHasLiteralPrefix(arg, "-T")) {
- std::string value = arg.substr(2);
- if (value.empty()) {
- ++i;
- if (i >= args.size()) {
- cmSystemTools::Error("No toolset specified for -T");
- return;
- }
- value = args[i];
- }
- if (haveToolset) {
- cmSystemTools::Error("Multiple -T options not allowed");
- return;
- }
- this->SetGeneratorToolset(value);
- haveToolset = true;
- } else if (cmHasLiteralPrefix(arg, "-G")) {
- std::string value = arg.substr(2);
- if (value.empty()) {
- ++i;
- if (i >= args.size()) {
- cmSystemTools::Error("No generator specified for -G");
- this->PrintGeneratorList();
- return;
- }
- value = args[i];
- }
- if (!this->CreateAndSetGlobalGenerator(value, true)) {
- return;
- }
+
#if !defined(CMAKE_BOOTSTRAP)
- } else if (cmHasLiteralPrefix(arg, "--profiling-format=")) {
- profilingFormat = arg.substr(strlen("--profiling-format="));
- if (profilingFormat.empty()) {
- cmSystemTools::Error("No format specified for --profiling-format");
- }
- } else if (cmHasLiteralPrefix(arg, "--profiling-output=")) {
- profilingOutput = arg.substr(strlen("--profiling-output="));
- profilingOutput = cmSystemTools::CollapseFullPath(profilingOutput);
+ arguments.emplace_back("--profiling-format",
+ "No format specified for --profiling-format",
+ CommandArgument::Values::One,
+ [&](std::string const& value, cmake*) -> bool {
+ profilingFormat = value;
+ return true;
+ });
+ arguments.emplace_back(
+ "--profiling-output", "No path specified for --profiling-output",
+ CommandArgument::Values::One,
+ [&](std::string const& value, cmake*) -> bool {
+ profilingOutput = cmSystemTools::CollapseFullPath(value);
cmSystemTools::ConvertToUnixSlashes(profilingOutput);
- if (profilingOutput.empty()) {
- cmSystemTools::Error("No path specified for --profiling-output");
- }
- } else if (cmHasLiteralPrefix(arg, "--preset=")) {
- presetName = arg.substr(strlen("--preset="));
- if (presetName.empty()) {
- cmSystemTools::Error("No preset specified for --preset");
+ return true;
+ });
+ arguments.emplace_back("--preset", "No preset specified for --preset",
+ CommandArgument::Values::One,
+ [&](std::string const& value, cmake*) -> bool {
+ presetName = value;
+ return true;
+ });
+ arguments.emplace_back(
+ "--list-presets", CommandArgument::Values::ZeroOrOne,
+ [&](std::string const& value, cmake*) -> bool {
+ if (value.empty() || value == "configure") {
+ listPresets = ListPresets::Configure;
+ } else if (value == "build") {
+ listPresets = ListPresets::Build;
+ } else if (value == "test") {
+ listPresets = ListPresets::Test;
+ } else if (value == "all") {
+ listPresets = ListPresets::All;
+ } else {
+ cmSystemTools::Error(
+ "Invalid value specified for --list-presets.\n"
+ "Valid values are configure, build, test, or all. "
+ "When no value is passed the default is configure.");
+ return false;
}
- } else if (cmHasLiteralPrefix(arg, "--list-presets")) {
- listPresets = true;
+
+ return true;
+ });
+
#endif
+
+ bool badGeneratorName = false;
+ CommandArgument generatorCommand(
+ "-G", "No generator specified for -G", CommandArgument::Values::One,
+ [&](std::string const& value, cmake* state) -> bool {
+ bool valid = state->CreateAndSetGlobalGenerator(value, true);
+ badGeneratorName = !valid;
+ return valid;
+ });
+
+ for (decltype(args.size()) i = 1; i < args.size(); ++i) {
+ // iterate each argument
+ std::string const& arg = args[i];
+
+ // Generator flag has special handling for when to print help
+ // so it becomes the exception
+ if (generatorCommand.matches(arg)) {
+ bool parsed = generatorCommand.parse(arg, i, args, this);
+ if (!parsed && !badGeneratorName) {
+ this->PrintGeneratorList();
+ return;
+ }
+ continue;
}
- // no option assume it is the path to the source or an existing build
- else {
+
+ bool matched = false;
+ bool parsedCorrectly = true; // needs to be true so we can ignore
+ // arguments so as -E
+ for (auto const& m : arguments) {
+ if (m.matches(arg)) {
+ matched = true;
+ parsedCorrectly = m.parse(arg, i, args, this);
+ break;
+ }
+ }
+
+ // We have an issue where arguments to a "-P" script mode
+ // can be provided before the "-P" argument. This means
+ // that we need to lazily check this argument after checking
+ // all args.
+ // Additionally it can't be the source/binary tree location
+ if (!parsedCorrectly) {
+ cmSystemTools::Error("Run 'cmake --help' for all supported options.");
+ exit(1);
+ } else if (!matched && cmHasLiteralPrefix(arg, "-")) {
+ possibleUnknownArg = arg;
+ } else if (!matched) {
this->SetDirectoriesFromFile(arg);
}
- // Empty instance, platform and toolset if only a generator is specified
- if (this->GlobalGenerator) {
- this->GeneratorInstance = "";
- if (!this->GeneratorPlatformSet) {
- this->GeneratorPlatform = "";
- }
- if (!this->GeneratorToolsetSet) {
- this->GeneratorToolset = "";
- }
+ }
+
+ if (!possibleUnknownArg.empty() && !scriptMode) {
+ cmSystemTools::Error(cmStrCat("Unknown argument ", possibleUnknownArg));
+ cmSystemTools::Error("Run 'cmake --help' for all supported options.");
+ exit(1);
+ }
+
+ // Empty instance, platform and toolset if only a generator is specified
+ if (this->GlobalGenerator) {
+ this->GeneratorInstance = "";
+ if (!this->GeneratorPlatformSet) {
+ this->GeneratorPlatform = "";
+ }
+ if (!this->GeneratorToolsetSet) {
+ this->GeneratorToolset = "";
}
}
@@ -1031,7 +1147,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
}
#if !defined(CMAKE_BOOTSTRAP)
- if (listPresets || !presetName.empty()) {
+ if (listPresets != ListPresets::None || !presetName.empty()) {
cmCMakePresetsFile settingsFile;
auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
@@ -1040,12 +1156,24 @@ void cmake::SetArgs(const std::vector<std::string>& args)
": ", cmCMakePresetsFile::ResultToString(result)));
return;
}
- if (listPresets) {
- this->PrintPresetList(settingsFile);
+
+ if (listPresets != ListPresets::None) {
+ if (listPresets == ListPresets::Configure) {
+ this->PrintPresetList(settingsFile);
+ } else if (listPresets == ListPresets::Build) {
+ settingsFile.PrintBuildPresetList();
+ } else if (listPresets == ListPresets::Test) {
+ settingsFile.PrintTestPresetList();
+ } else if (listPresets == ListPresets::All) {
+ settingsFile.PrintAllPresets();
+ }
+
+ this->SetWorkingMode(WorkingMode::HELP_MODE);
return;
}
- auto preset = settingsFile.Presets.find(presetName);
- if (preset == settingsFile.Presets.end()) {
+
+ auto preset = settingsFile.ConfigurePresets.find(presetName);
+ if (preset == settingsFile.ConfigurePresets.end()) {
cmSystemTools::Error(cmStrCat("No such preset in ",
this->GetHomeDirectory(), ": \"",
presetName, '"'));
@@ -1474,44 +1602,16 @@ void cmake::PrintPresetList(const cmCMakePresetsFile& file) const
{
std::vector<GeneratorInfo> generators;
this->GetRegisteredGenerators(generators, false);
+ auto filter =
+ [&generators](const cmCMakePresetsFile::ConfigurePreset& preset) -> bool {
+ auto condition = [&preset](const GeneratorInfo& info) -> bool {
+ return info.name == preset.Generator;
+ };
+ auto it = std::find_if(generators.begin(), generators.end(), condition);
+ return it != generators.end();
+ };
- std::vector<cmCMakePresetsFile::UnexpandedPreset> presets;
- for (auto const& p : file.PresetOrder) {
- auto const& preset = file.Presets.at(p);
- if (!preset.Unexpanded.Hidden && preset.Expanded &&
- std::find_if(generators.begin(), generators.end(),
- [&preset](const GeneratorInfo& info) {
- return info.name == preset.Unexpanded.Generator;
- }) != generators.end()) {
- presets.push_back(preset.Unexpanded);
- }
- }
-
- if (presets.empty()) {
- return;
- }
-
- std::cout << "Available presets:\n\n";
-
- auto longestPresetName =
- std::max_element(presets.begin(), presets.end(),
- [](const cmCMakePresetsFile::UnexpandedPreset& a,
- const cmCMakePresetsFile::UnexpandedPreset& b) {
- return a.Name.length() < b.Name.length();
- });
- auto longestLength = longestPresetName->Name.length();
-
- for (auto const& preset : presets) {
- std::cout << " \"" << preset.Name << '"';
- auto const& description = preset.DisplayName;
- if (!description.empty()) {
- for (std::size_t i = 0; i < longestLength - preset.Name.length(); ++i) {
- std::cout << ' ';
- }
- std::cout << " - " << description;
- }
- std::cout << '\n';
- }
+ file.PrintConfigurePresetList(filter);
}
#endif
@@ -1951,7 +2051,7 @@ int cmake::ActualConfigure()
}
}
- auto& mf = this->GlobalGenerator->GetMakefiles()[0];
+ const auto& mf = this->GlobalGenerator->GetMakefiles()[0];
if (mf->IsOn("CTEST_USE_LAUNCHERS") &&
!this->State->GetGlobalProperty("RULE_LAUNCH_COMPILE")) {
cmSystemTools::Error(
@@ -2115,7 +2215,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
#endif
// Add any cache args
if (!this->SetCacheArgs(args)) {
- cmSystemTools::Error("Problem processing arguments. Aborting.\n");
+ cmSystemTools::Error("Run 'cmake --help' for all supported options.");
return -1;
}
#ifndef CMAKE_BOOTSTRAP
@@ -2293,12 +2393,12 @@ cmProp cmake::GetCacheDefinition(const std::string& name) const
return this->State->GetInitializedCacheValue(name);
}
-void cmake::AddScriptingCommands()
+void cmake::AddScriptingCommands() const
{
GetScriptingCommands(this->GetState());
}
-void cmake::AddProjectCommands()
+void cmake::AddProjectCommands() const
{
GetProjectCommands(this->GetState());
}
@@ -2573,8 +2673,7 @@ int cmake::CheckBuildSystem()
if (this->ClearBuildSystem) {
// Get the generator used for this build system.
- const char* genName =
- cmToCStr(mf.GetDefinition("CMAKE_DEPENDS_GENERATOR"));
+ std::string genName = mf.GetSafeDefinition("CMAKE_DEPENDS_GENERATOR");
if (!cmNonempty(genName)) {
genName = "Unix Makefiles";
}
@@ -2981,15 +3080,119 @@ std::vector<std::string> cmake::GetDebugConfigs()
return configs;
}
-int cmake::Build(int jobs, const std::string& dir,
- const std::vector<std::string>& targets,
- const std::string& config,
- const std::vector<std::string>& nativeOptions, bool clean,
- bool verbose)
+int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
+ std::string config, std::vector<std::string> nativeOptions,
+ bool clean, bool verbose, const std::string& presetName,
+ bool listPresets)
{
-
this->SetHomeDirectory("");
this->SetHomeOutputDirectory("");
+
+#if !defined(CMAKE_BOOTSTRAP)
+ if (!presetName.empty() || listPresets) {
+ this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+
+ cmCMakePresetsFile settingsFile;
+ auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
+ if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+ cmSystemTools::Error(
+ cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
+ ": ", cmCMakePresetsFile::ResultToString(result)));
+ return 1;
+ }
+
+ if (listPresets) {
+ settingsFile.PrintBuildPresetList();
+ return 0;
+ }
+
+ auto presetPair = settingsFile.BuildPresets.find(presetName);
+ if (presetPair == settingsFile.BuildPresets.end()) {
+ cmSystemTools::Error(cmStrCat("No such build preset in ",
+ this->GetHomeDirectory(), ": \"",
+ presetName, '"'));
+ settingsFile.PrintBuildPresetList();
+ return 1;
+ }
+
+ if (presetPair->second.Unexpanded.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden build preset in ",
+ this->GetHomeDirectory(), ": \"",
+ presetName, '"'));
+ settingsFile.PrintBuildPresetList();
+ return 1;
+ }
+
+ auto const& expandedPreset = presetPair->second.Expanded;
+ if (!expandedPreset) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate build preset \"",
+ presetName,
+ "\": Invalid macro expansion"));
+ settingsFile.PrintBuildPresetList();
+ return 1;
+ }
+
+ auto configurePresetPair =
+ settingsFile.ConfigurePresets.find(expandedPreset->ConfigurePreset);
+ if (configurePresetPair == settingsFile.ConfigurePresets.end()) {
+ cmSystemTools::Error(cmStrCat("No such configure preset in ",
+ this->GetHomeDirectory(), ": \"",
+ expandedPreset->ConfigurePreset, '"'));
+ this->PrintPresetList(settingsFile);
+ return 1;
+ }
+
+ if (configurePresetPair->second.Unexpanded.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden configure preset in ",
+ this->GetHomeDirectory(), ": \"",
+ expandedPreset->ConfigurePreset, '"'));
+ this->PrintPresetList(settingsFile);
+ return 1;
+ }
+
+ auto const& expandedConfigurePreset = configurePresetPair->second.Expanded;
+ if (!expandedConfigurePreset) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate configure preset \"",
+ expandedPreset->ConfigurePreset,
+ "\": Invalid macro expansion"));
+ return 1;
+ }
+
+ dir = expandedConfigurePreset->BinaryDir;
+
+ this->UnprocessedPresetEnvironment = expandedPreset->Environment;
+ this->ProcessPresetEnvironment();
+
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL && expandedPreset->Jobs) {
+ jobs = *expandedPreset->Jobs;
+ }
+
+ if (targets.empty()) {
+ targets.insert(targets.begin(), expandedPreset->Targets.begin(),
+ expandedPreset->Targets.end());
+ }
+
+ if (config.empty()) {
+ config = expandedPreset->Configuration;
+ }
+
+ if (!clean && expandedPreset->CleanFirst) {
+ clean = *expandedPreset->CleanFirst;
+ }
+
+ if (!verbose && expandedPreset->Verbose) {
+ verbose = *expandedPreset->Verbose;
+ }
+
+ if (nativeOptions.empty()) {
+ nativeOptions.insert(nativeOptions.begin(),
+ expandedPreset->NativeToolOptions.begin(),
+ expandedPreset->NativeToolOptions.end());
+ }
+ }
+#endif
+
if (!cmSystemTools::FileIsDirectory(dir)) {
std::cerr << "Error: " << dir << " is not a directory\n";
return 1;
diff --git a/Source/cmake.h b/Source/cmake.h
index 1ecf2c283..82e028c31 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -238,7 +238,7 @@ public:
bool CreateAndSetGlobalGenerator(const std::string& name, bool allowArch);
#ifndef CMAKE_BOOTSTRAP
- //! Print list of presets
+ //! Print list of configure presets
void PrintPresetList(const cmCMakePresetsFile& file) const;
#endif
@@ -411,7 +411,7 @@ public:
WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; }
//! Debug the try compile stuff by not deleting the files
- bool GetDebugTryCompile() { return this->DebugTryCompile; }
+ bool GetDebugTryCompile() const { return this->DebugTryCompile; }
void DebugTryCompileOn() { this->DebugTryCompile = true; }
/**
@@ -456,11 +456,11 @@ public:
void SetShowLogContext(bool b) { this->LogContext = b; }
//! Do we want debug output during the cmake run.
- bool GetDebugOutput() { return this->DebugOutput; }
+ bool GetDebugOutput() const { return this->DebugOutput; }
void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
//! Do we want debug output from the find commands during the cmake run.
- bool GetDebugFindOutput() { return this->DebugFindOutput; }
+ bool GetDebugFindOutput() const { return this->DebugFindOutput; }
void SetDebugFindOutputOn(bool b) { this->DebugFindOutput = b; }
//! Do we want trace output during the cmake run.
@@ -482,11 +482,11 @@ public:
void SetTraceFile(std::string const& file);
void PrintTraceFormatVersion();
- bool GetWarnUninitialized() { return this->WarnUninitialized; }
+ bool GetWarnUninitialized() const { return this->WarnUninitialized; }
void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
- bool GetWarnUnusedCli() { return this->WarnUnusedCli; }
+ bool GetWarnUnusedCli() const { return this->WarnUnusedCli; }
void SetWarnUnusedCli(bool b) { this->WarnUnusedCli = b; }
- bool GetCheckSystemVars() { return this->CheckSystemVars; }
+ bool GetCheckSystemVars() const { return this->CheckSystemVars; }
void SetCheckSystemVars(bool b) { this->CheckSystemVars = b; }
void MarkCliAsUsed(const std::string& variable);
@@ -556,10 +556,10 @@ public:
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
//! run the --build option
- int Build(int jobs, const std::string& dir,
- const std::vector<std::string>& targets, const std::string& config,
- const std::vector<std::string>& nativeOptions, bool clean,
- bool verbose);
+ int Build(int jobs, std::string dir, std::vector<std::string> targets,
+ std::string config, std::vector<std::string> nativeOptions,
+ bool clean, bool verbose, const std::string& presetName,
+ bool listPresets);
//! run the --open option
bool Open(const std::string& dir, bool dryRun);
@@ -591,8 +591,8 @@ protected:
using RegisteredExtraGeneratorsVector =
std::vector<cmExternalMakefileProjectGeneratorFactory*>;
RegisteredExtraGeneratorsVector ExtraGenerators;
- void AddScriptingCommands();
- void AddProjectCommands();
+ void AddScriptingCommands() const;
+ void AddProjectCommands() const;
void AddDefaultGenerators();
void AddDefaultExtraGenerators();
@@ -811,6 +811,7 @@ private:
F(cxx_std_14) \
F(cxx_std_17) \
F(cxx_std_20) \
+ F(cxx_std_23) \
FOR_EACH_CXX98_FEATURE(F) \
FOR_EACH_CXX11_FEATURE(F) \
FOR_EACH_CXX14_FEATURE(F)
@@ -820,4 +821,5 @@ private:
F(cuda_std_11) \
F(cuda_std_14) \
F(cuda_std_17) \
- F(cuda_std_20)
+ F(cuda_std_20) \
+ F(cuda_std_23)
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index f7734a6e9..88ba0116c 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -5,7 +5,6 @@
#include <algorithm>
#include <cassert>
-#include <cctype>
#include <climits>
#include <cstring>
#include <iostream>
@@ -19,6 +18,7 @@
#include <cm3p/uv.h>
+#include "cmCommandLineArgument.h"
#include "cmConsoleBuf.h"
#include "cmDocumentationEntry.h" // IWYU pragma: keep
#include "cmGlobalGenerator.h"
@@ -64,7 +64,7 @@ const char* cmDocumentationUsageNote[][2] = {
const char* cmDocumentationOptions[][2] = {
CMAKE_STANDARD_OPTIONS_TABLE,
- { "--preset=<preset>", "Specify a configure preset." },
+ { "--preset <preset>,--preset=<preset>", "Specify a configure preset." },
{ "--list-presets", "List available presets." },
{ "-E", "CMake command mode." },
{ "-L[A][H]", "List non-advanced cached variables." },
@@ -213,61 +213,114 @@ int do_cmake(int ac, char const* const* av)
}
#endif
+ bool wizard_mode = false;
bool sysinfo = false;
bool list_cached = false;
bool list_all_cached = false;
bool list_help = false;
bool view_only = false;
cmake::WorkingMode workingMode = cmake::NORMAL_MODE;
- std::vector<std::string> args;
- for (int i = 0; i < ac; ++i) {
- if (strcmp(av[i], "-i") == 0) {
- /* clang-format off */
- std::cerr <<
- "The \"cmake -i\" wizard mode is no longer supported.\n"
- "Use the -D option to set cache values on the command line.\n"
- "Use cmake-gui or ccmake for an interactive dialog.\n";
- /* clang-format on */
- return 1;
- }
- if (strcmp(av[i], "--system-information") == 0) {
- sysinfo = true;
- } else if (strcmp(av[i], "-N") == 0) {
- view_only = true;
- } else if (strcmp(av[i], "-L") == 0) {
- list_cached = true;
- } else if (strcmp(av[i], "-LA") == 0) {
- list_all_cached = true;
- } else if (strcmp(av[i], "-LH") == 0) {
- list_cached = true;
- list_help = true;
- } else if (strcmp(av[i], "-LAH") == 0) {
- list_all_cached = true;
- list_help = true;
- } else if (cmHasLiteralPrefix(av[i], "-P")) {
- if (i == ac - 1) {
- cmSystemTools::Error("No script specified for argument -P");
- return 1;
+ std::vector<std::string> parsedArgs;
+
+ using CommandArgument =
+ cmCommandLineArgument<bool(std::string const& value)>;
+ std::vector<CommandArgument> arguments = {
+ CommandArgument{
+ "-i", CommandArgument::Values::Zero,
+ [&wizard_mode](std::string const&) -> bool {
+ /* clang-format off */
+ std::cerr <<
+ "The \"cmake -i\" wizard mode is no longer supported.\n"
+ "Use the -D option to set cache values on the command line.\n"
+ "Use cmake-gui or ccmake for an interactive dialog.\n";
+ /* clang-format on */
+ wizard_mode = true;
+ return true;
+ } },
+ CommandArgument{ "--system-information", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ sysinfo = true;
+ return true;
+ } },
+ CommandArgument{ "-N", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ view_only = true;
+ return true;
+ } },
+ CommandArgument{ "-LAH", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ list_all_cached = true;
+ list_help = true;
+ return true;
+ } },
+ CommandArgument{ "-LA", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ list_all_cached = true;
+ return true;
+ } },
+ CommandArgument{ "-LH", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ list_cached = true;
+ list_help = true;
+ return true;
+ } },
+ CommandArgument{ "-L", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ list_cached = true;
+ return true;
+ } },
+ CommandArgument{ "-P", "No script specified for argument -P",
+ CommandArgument::Values::One,
+ [&](std::string const& value) -> bool {
+ workingMode = cmake::SCRIPT_MODE;
+ parsedArgs.emplace_back("-P");
+ parsedArgs.push_back(value);
+ return true;
+ } },
+ CommandArgument{ "--find-package", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ workingMode = cmake::FIND_PACKAGE_MODE;
+ parsedArgs.emplace_back("--find-package");
+ return true;
+ } },
+ CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ workingMode = cmake::HELP_MODE;
+ parsedArgs.emplace_back("--list-presets");
+ return true;
+ } },
+ };
+
+ std::vector<std::string> inputArgs;
+ inputArgs.reserve(ac);
+ cm::append(inputArgs, av, av + ac);
+
+ for (decltype(inputArgs.size()) i = 0; i < inputArgs.size(); ++i) {
+ std::string const& arg = inputArgs[i];
+ bool matched = false;
+ for (auto const& m : arguments) {
+ if (m.matches(arg)) {
+ matched = true;
+ if (m.parse(arg, i, inputArgs)) {
+ break;
+ }
+ return 1; // failed to parse
}
- workingMode = cmake::SCRIPT_MODE;
- args.emplace_back(av[i]);
- i++;
- args.emplace_back(av[i]);
- } else if (cmHasLiteralPrefix(av[i], "--find-package")) {
- workingMode = cmake::FIND_PACKAGE_MODE;
- args.emplace_back(av[i]);
- } else if (strcmp(av[i], "--list-presets") == 0) {
- workingMode = cmake::HELP_MODE;
- args.emplace_back(av[i]);
- } else {
- args.emplace_back(av[i]);
+ }
+ if (!matched) {
+ parsedArgs.emplace_back(av[i]);
}
}
+
+ if (wizard_mode) {
+ return 1;
+ }
+
if (sysinfo) {
cmake cm(cmake::RoleProject, cmState::Project);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
- int ret = cm.GetSystemInformation(args);
+ int ret = cm.GetSystemInformation(parsedArgs);
return ret;
}
cmake::Role const role =
@@ -297,7 +350,7 @@ int do_cmake(int ac, char const* const* av)
});
cm.SetWorkingMode(workingMode);
- int res = cm.Run(args, view_only);
+ int res = cm.Run(parsedArgs, view_only);
if (list_cached || list_all_cached) {
std::cout << "-- Cache values" << std::endl;
std::vector<std::string> keys = cm.GetState()->GetCacheEntryKeys();
@@ -332,16 +385,9 @@ int do_cmake(int ac, char const* const* av)
}
#ifndef CMAKE_BOOTSTRAP
-int extract_job_number(int& index, char const* current, char const* next,
- int len_of_flag)
+int extract_job_number(std::string const& command,
+ std::string const& jobString)
{
- std::string command(current);
- std::string jobString = command.substr(len_of_flag);
- if (jobString.empty() && next && isdigit(next[0])) {
- ++index; // skip parsing the job number
- jobString = std::string(next);
- }
-
int jobs = -1;
unsigned long numJobs = 0;
if (jobString.empty()) {
@@ -356,8 +402,8 @@ int extract_job_number(int& index, char const* current, char const* next,
jobs = int(numJobs);
}
} else {
- std::cerr << "'" << command.substr(0, len_of_flag) << "' invalid number '"
- << jobString << "' given.\n\n";
+ std::cerr << "'" << command << "' invalid number '" << jobString
+ << "' given.\n\n";
}
return jobs;
}
@@ -374,88 +420,135 @@ int do_build(int ac, char const* const* av)
std::string config;
std::string dir;
std::vector<std::string> nativeOptions;
+ bool nativeOptionsPassed = false;
bool cleanFirst = false;
bool foundClean = false;
bool foundNonClean = false;
bool verbose = cmSystemTools::HasEnv("VERBOSE");
+ std::string presetName;
+ bool listPresets = false;
- enum Doing
- {
- DoingNone,
- DoingDir,
- DoingTarget,
- DoingConfig,
- DoingNative
+ auto jLambda = [&](std::string const& value) -> bool {
+ jobs = extract_job_number("-j", value);
+ if (jobs < 0) {
+ dir.clear();
+ }
+ return true;
};
- Doing doing = DoingDir;
- for (int i = 2; i < ac; ++i) {
- if (doing == DoingNative) {
- nativeOptions.emplace_back(av[i]);
- } else if (cmHasLiteralPrefix(av[i], "-j")) {
- const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr);
- jobs = extract_job_number(i, av[i], nextArg, sizeof("-j") - 1);
- if (jobs < 0) {
- dir.clear();
+ auto parallelLambda = [&](std::string const& value) -> bool {
+ jobs = extract_job_number("--parallel", value);
+ if (jobs < 0) {
+ dir.clear();
+ }
+ return true;
+ };
+ auto targetLambda = [&](std::string const& value) -> bool {
+ if (!value.empty()) {
+ std::vector<std::string> values = cmExpandedList(value);
+ for (auto const& v : values) {
+ targets.emplace_back(v);
+ if (v == "clean") {
+ foundClean = true;
+ } else {
+ foundNonClean = true;
+ }
}
- doing = DoingNone;
- } else if (cmHasLiteralPrefix(av[i], "--parallel")) {
- const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr);
- jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1);
- if (jobs < 0) {
- dir.clear();
+ return true;
+ }
+ return false;
+ };
+ auto verboseLambda = [&](std::string const&) -> bool {
+ verbose = true;
+ return true;
+ };
+
+ using CommandArgument =
+ cmCommandLineArgument<bool(std::string const& value)>;
+
+ std::vector<CommandArgument> arguments = {
+ CommandArgument{ "--preset", CommandArgument::Values::One,
+ [&](std::string const& value) -> bool {
+ presetName = value;
+ return true;
+ } },
+ CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ listPresets = true;
+ return true;
+ } },
+ CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, jLambda },
+ CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne,
+ parallelLambda },
+ CommandArgument{ "-t", CommandArgument::Values::OneOrMore, targetLambda },
+ CommandArgument{ "--target", CommandArgument::Values::OneOrMore,
+ targetLambda },
+ CommandArgument{ "--config", CommandArgument::Values::One,
+ [&](std::string const& value) -> bool {
+ config = value;
+ return true;
+ } },
+ CommandArgument{ "--clean-first", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ cleanFirst = true;
+ return true;
+ } },
+ CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda },
+ CommandArgument{ "--verbose", CommandArgument::Values::Zero,
+ verboseLambda },
+ /* legacy option no-op*/
+ CommandArgument{ "--use-stderr", CommandArgument::Values::Zero,
+ [](std::string const&) -> bool { return true; } },
+ CommandArgument{ "--", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ nativeOptionsPassed = true;
+ return true;
+ } },
+ };
+
+ if (ac >= 3) {
+ std::vector<std::string> inputArgs;
+
+ bool hasPreset = false;
+ for (int i = 2; i < ac; ++i) {
+ if (strcmp(av[i], "--list-presets") == 0 ||
+ cmHasLiteralPrefix(av[i], "--preset=") ||
+ strcmp(av[i], "--preset") == 0) {
+ hasPreset = true;
+ break;
}
- doing = DoingNone;
- } else if ((strcmp(av[i], "--target") == 0) ||
- (strcmp(av[i], "-t") == 0)) {
- doing = DoingTarget;
- } else if (strcmp(av[i], "--config") == 0) {
- doing = DoingConfig;
- } else if (strcmp(av[i], "--clean-first") == 0) {
- cleanFirst = true;
- doing = DoingNone;
- } else if ((strcmp(av[i], "--verbose") == 0) ||
- (strcmp(av[i], "-v") == 0)) {
- verbose = true;
- doing = DoingNone;
- } else if (strcmp(av[i], "--use-stderr") == 0) {
- /* tolerate legacy option */
- } else if (strcmp(av[i], "--") == 0) {
- doing = DoingNative;
+ }
+
+ if (hasPreset) {
+ inputArgs.reserve(ac - 2);
+ cm::append(inputArgs, av + 2, av + ac);
} else {
- switch (doing) {
- case DoingDir:
- dir = cmSystemTools::CollapseFullPath(av[i]);
- doing = DoingNone;
- break;
- case DoingTarget:
- if (strlen(av[i]) == 0) {
- std::cerr << "Warning: Argument number " << i
- << " after --target option is empty." << std::endl;
- } else {
- targets.emplace_back(av[i]);
- if (strcmp(av[i], "clean") == 0) {
- foundClean = true;
- } else {
- foundNonClean = true;
- }
- }
- if (foundClean && foundNonClean) {
- std::cerr << "Error: Building 'clean' and other targets together "
- "is not supported."
- << std::endl;
- dir.clear();
- }
- break;
- case DoingConfig:
- config = av[i];
- doing = DoingNone;
- break;
- default:
- std::cerr << "Unknown argument " << av[i] << std::endl;
- dir.clear();
+ dir = cmSystemTools::CollapseFullPath(av[2]);
+
+ inputArgs.reserve(ac - 3);
+ cm::append(inputArgs, av + 3, av + ac);
+ }
+
+ decltype(inputArgs.size()) i = 0;
+ for (; i < inputArgs.size() && !nativeOptionsPassed; ++i) {
+
+ std::string const& arg = inputArgs[i];
+ for (auto const& m : arguments) {
+ if (m.matches(arg) && m.parse(arg, i, inputArgs)) {
break;
+ }
}
}
+
+ if (nativeOptionsPassed) {
+ cm::append(nativeOptions, inputArgs.begin() + i, inputArgs.end());
+ }
+ }
+
+ if (foundClean && foundNonClean) {
+ std::cerr << "Error: Building 'clean' and other targets together "
+ "is not supported."
+ << std::endl;
+ dir.clear();
}
if (jobs == cmake::NO_BUILD_PARALLEL_LEVEL) {
@@ -486,12 +579,16 @@ int do_build(int ac, char const* const* av)
}
}
- if (dir.empty()) {
+ if (dir.empty() && presetName.empty() && !listPresets) {
/* clang-format off */
std::cerr <<
- "Usage: cmake --build <dir> [options] [-- [native-options]]\n"
+ "Usage: cmake --build [<dir> | --preset <preset>] [options] [-- [native-options]]\n"
"Options:\n"
" <dir> = Project binary directory to be built.\n"
+ " --preset <preset>, --preset=<preset>\n"
+ " = Specify a build preset.\n"
+ " --list-presets\n"
+ " = List available build presets.\n"
" --parallel [<jobs>], -j [<jobs>]\n"
" = Build in parallel using the given number of jobs. \n"
" If <jobs> is omitted the native build tool's \n"
@@ -522,8 +619,10 @@ int do_build(int ac, char const* const* av)
cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
cmakemainProgressCallback(msg, prog, &cm);
});
- return cm.Build(jobs, dir, targets, config, nativeOptions, cleanFirst,
- verbose);
+
+ return cm.Build(jobs, std::move(dir), std::move(targets), std::move(config),
+ std::move(nativeOptions), cleanFirst, verbose, presetName,
+ listPresets);
#endif
}
@@ -658,60 +757,59 @@ int do_install(int ac, char const* const* av)
bool strip = false;
bool verbose = cmSystemTools::HasEnv("VERBOSE");
- enum Doing
- {
- DoingNone,
- DoingDir,
- DoingConfig,
- DoingComponent,
- DoingPrefix,
- DoingDefaultDirectoryPermissions,
+ auto verboseLambda = [&](std::string const&) -> bool {
+ verbose = true;
+ return true;
};
- Doing doing = DoingDir;
+ using CommandArgument =
+ cmCommandLineArgument<bool(std::string const& value)>;
+
+ std::vector<CommandArgument> arguments = {
+ CommandArgument{ "--config", CommandArgument::Values::One,
+ [&](std::string const& value) -> bool {
+ config = value;
+ return true;
+ } },
+ CommandArgument{ "--component", CommandArgument::Values::One,
+ [&](std::string const& value) -> bool {
+ component = value;
+ return true;
+ } },
+ CommandArgument{ "--default-directory-permissions",
+ CommandArgument::Values::One,
+ [&](std::string const& value) -> bool {
+ defaultDirectoryPermissions = value;
+ return true;
+ } },
+ CommandArgument{ "--prefix", CommandArgument::Values::One,
+ [&](std::string const& value) -> bool {
+ prefix = value;
+ return true;
+ } },
+ CommandArgument{ "--strip", CommandArgument::Values::Zero,
+ [&](std::string const&) -> bool {
+ strip = true;
+ return true;
+ } },
+ CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda },
+ CommandArgument{ "--verbose", CommandArgument::Values::Zero,
+ verboseLambda }
+ };
- for (int i = 2; i < ac; ++i) {
- if (strcmp(av[i], "--config") == 0) {
- doing = DoingConfig;
- } else if (strcmp(av[i], "--component") == 0) {
- doing = DoingComponent;
- } else if (strcmp(av[i], "--prefix") == 0) {
- doing = DoingPrefix;
- } else if (strcmp(av[i], "--strip") == 0) {
- strip = true;
- doing = DoingNone;
- } else if ((strcmp(av[i], "--verbose") == 0) ||
- (strcmp(av[i], "-v") == 0)) {
- verbose = true;
- doing = DoingNone;
- } else if (strcmp(av[i], "--default-directory-permissions") == 0) {
- doing = DoingDefaultDirectoryPermissions;
- } else {
- switch (doing) {
- case DoingDir:
- dir = cmSystemTools::CollapseFullPath(av[i]);
- doing = DoingNone;
- break;
- case DoingConfig:
- config = av[i];
- doing = DoingNone;
- break;
- case DoingComponent:
- component = av[i];
- doing = DoingNone;
- break;
- case DoingPrefix:
- prefix = av[i];
- doing = DoingNone;
- break;
- case DoingDefaultDirectoryPermissions:
- defaultDirectoryPermissions = av[i];
- doing = DoingNone;
- break;
- default:
- std::cerr << "Unknown argument " << av[i] << std::endl;
- dir.clear();
+ if (ac >= 3) {
+ dir = cmSystemTools::CollapseFullPath(av[2]);
+
+ std::vector<std::string> inputArgs;
+ inputArgs.reserve(ac - 3);
+ cm::append(inputArgs, av + 3, av + ac);
+ for (decltype(inputArgs.size()) i = 0; i < inputArgs.size(); ++i) {
+
+ std::string const& arg = inputArgs[i];
+ for (auto const& m : arguments) {
+ if (m.matches(arg) && m.parse(arg, i, inputArgs)) {
break;
+ }
}
}
}
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index e2ff8b753..6713cc358 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -20,6 +20,7 @@
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTransformDepfile.h"
#include "cmUVProcessChain.h"
#include "cmUtils.hxx"
#include "cmVersion.h"
@@ -28,12 +29,17 @@
#if !defined(CMAKE_BOOTSTRAP)
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
# include "cmFileTime.h"
-# include "cmServer.h"
-# include "cmServerConnection.h"
# include "bindexplib.h"
#endif
+#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
+# include <algorithm>
+
+# include "cmCMakePath.h"
+# include "cmProcessTools.h"
+#endif
+
#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__)
# include "cmVisualStudioWCEPlatformParser.h"
#endif
@@ -59,15 +65,15 @@
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/Process.h"
+#include "cmsys/RegularExpression.hxx"
#include "cmsys/Terminal.h"
-class cmConnection;
-
int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd);
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)
{
std::ostringstream errorStream;
@@ -121,7 +127,6 @@ void CMakeCommandUsage(const char* program)
"(on one volume)\n"
<< " rm [-rRf] <file/dir>... - remove files or directories, use -f to "
"force it, r or R to remove directories and their contents recursively\n"
- << " server - start cmake in server mode\n"
<< " sleep <number>... - sleep for given number of seconds\n"
<< " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n"
<< " - create or extract a tar or zip archive\n"
@@ -147,8 +152,7 @@ void CMakeCommandUsage(const char* program)
cmSystemTools::Error(errorStream.str());
}
-static bool cmTarFilesFrom(std::string const& file,
- std::vector<std::string>& files)
+bool cmTarFilesFrom(std::string const& file, std::vector<std::string>& files)
{
if (cmSystemTools::FileIsDirectory(file)) {
std::ostringstream e;
@@ -183,7 +187,7 @@ static bool cmTarFilesFrom(std::string const& file,
return true;
}
-static void cmCatFile(const std::string& fileToAppend)
+void cmCatFile(const std::string& fileToAppend)
{
#ifdef _WIN32
_setmode(fileno(stdout), _O_BINARY);
@@ -193,7 +197,7 @@ static void cmCatFile(const std::string& fileToAppend)
std::cout << source.rdbuf();
}
-static bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
+bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
{
if (cmSystemTools::FileIsSymlink(dir)) {
if (!cmSystemTools::RemoveFile(dir)) {
@@ -211,9 +215,122 @@ static bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
return true;
}
-static int HandleIWYU(const std::string& runCmd,
- const std::string& /* sourceFile */,
- const std::vector<std::string>& orig_cmd)
+#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
+class CLIncludeParser : public cmProcessTools::LineParser
+{
+public:
+ CLIncludeParser(cm::string_view includePrefix, cmsys::ofstream& depFile,
+ std::ostream& output)
+ : IncludePrefix(includePrefix)
+ , DepFile(depFile)
+ , Output(output)
+ {
+ }
+
+private:
+ bool ProcessLine() override
+ {
+ if (cmHasPrefix(this->Line, this->IncludePrefix)) {
+ auto path =
+ cmTrimWhitespace(this->Line.c_str() + this->IncludePrefix.size());
+ cmSystemTools::ConvertToLongPath(path);
+ this->DepFile << cmCMakePath(path).GenericString() << std::endl;
+ } else {
+ this->Output << this->Line << std::endl << std::flush;
+ }
+
+ return true;
+ }
+
+ cm::string_view IncludePrefix;
+ cmsys::ofstream& DepFile;
+ std::ostream& Output;
+};
+
+class CLOutputLogger : public cmProcessTools::OutputLogger
+{
+public:
+ CLOutputLogger(std::ostream& log)
+ : cmProcessTools::OutputLogger(log)
+ {
+ }
+
+ bool ProcessLine() override
+ {
+ *this->Log << std::flush;
+ return true;
+ }
+};
+
+int CLCompileAndDependencies(const std::vector<std::string>& args)
+{
+ std::string depFile;
+ std::string currentBinaryDir;
+ std::string filterPrefix;
+ std::vector<std::string> command;
+ for (auto it = args.cbegin() + 2; it != args.cend(); it++) {
+ if (cmHasLiteralPrefix(*it, "--dep-file=")) {
+ depFile = it->substr(11);
+ } else if (cmHasLiteralPrefix(*it, "--working-dir=")) {
+ currentBinaryDir = it->substr(14);
+ } else if (cmHasLiteralPrefix(*it, "--filter-prefix=")) {
+ filterPrefix = it->substr(16);
+ } else if (*it == "--") {
+ command.insert(command.begin(), ++it, args.cend());
+ break;
+ } else {
+ return 1;
+ }
+ }
+
+ std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp(
+ cmsysProcess_New(), cmsysProcess_Delete);
+ std::vector<const char*> argv(command.size() + 1);
+ std::transform(command.begin(), command.end(), argv.begin(),
+ [](std::string const& s) { return s.c_str(); });
+ argv.back() = nullptr;
+ cmsysProcess_SetCommand(cp.get(), argv.data());
+ cmsysProcess_SetWorkingDirectory(cp.get(), currentBinaryDir.c_str());
+
+ cmsys::ofstream fout(depFile.c_str());
+ if (!fout) {
+ return 3;
+ }
+
+ CLIncludeParser includeParser(filterPrefix, fout, std::cout);
+ CLOutputLogger errLogger(std::cerr);
+
+ // Start the process.
+ cmProcessTools::RunProcess(cp.get(), &includeParser, &errLogger);
+
+ int status = 0;
+ // handle status of process
+ switch (cmsysProcess_GetState(cp.get())) {
+ case cmsysProcess_State_Exited:
+ status = cmsysProcess_GetExitValue(cp.get());
+ break;
+ case cmsysProcess_State_Exception:
+ status = 1;
+ break;
+ case cmsysProcess_State_Error:
+ status = 2;
+ break;
+ default:
+ break;
+ }
+
+ if (status != 0) {
+ // remove the dependencies file because potentially invalid
+ fout.close();
+ cmSystemTools::RemoveFile(depFile);
+ }
+
+ return status;
+}
+#endif
+
+int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */,
+ const std::vector<std::string>& orig_cmd)
{
// Construct the iwyu command line by taking what was given
// and adding all the arguments we give to the compiler.
@@ -238,8 +355,8 @@ static int HandleIWYU(const std::string& runCmd,
return 0;
}
-static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
- const std::vector<std::string>& orig_cmd)
+int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
{
// Construct the clang-tidy command line by taking what was given
// and adding our compiler command line. The clang-tidy tool will
@@ -268,9 +385,8 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
return ret;
}
-static int HandleLWYU(const std::string& runCmd,
- const std::string& /* sourceFile */,
- const std::vector<std::string>&)
+int HandleLWYU(const std::string& runCmd, const std::string& /* sourceFile */,
+ const std::vector<std::string>&)
{
// Construct the ldd -r -u (link what you use lwyu) command line
// ldd -u -r lwuy target
@@ -301,9 +417,8 @@ static int HandleLWYU(const std::string& runCmd,
return 0;
}
-static int HandleCppLint(const std::string& runCmd,
- const std::string& sourceFile,
- const std::vector<std::string>&)
+int HandleCppLint(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>&)
{
// Construct the cpplint command line.
std::vector<std::string> cpplint_cmd = cmExpandedList(runCmd, true);
@@ -329,9 +444,8 @@ static int HandleCppLint(const std::string& runCmd,
return 0;
}
-static int HandleCppCheck(const std::string& runCmd,
- const std::string& sourceFile,
- const std::vector<std::string>& orig_cmd)
+int HandleCppCheck(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
{
// Construct the cpplint command line.
std::vector<std::string> cppcheck_cmd = cmExpandedList(runCmd, true);
@@ -394,7 +508,7 @@ struct CoCompiler
bool NoOriginalCommand;
};
-static const std::array<CoCompiler, 5> CoCompilers = {
+const std::array<CoCompiler, 5> CoCompilers = {
{ // Table of options and handlers.
{ "--cppcheck=", HandleCppCheck, false },
{ "--cpplint=", HandleCppLint, false },
@@ -408,6 +522,7 @@ struct CoCompileJob
std::string Command;
CoCompileHandler Handler;
};
+}
// called when args[0] == "__run_co_compile"
int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args)
@@ -589,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].c_str());
return 2;
}
@@ -624,8 +739,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
}
if (outValid) {
- // The def file already exists and all input files are older than the
- // existing def file.
+ // The def file already exists and all input files are older than
+ // the existing def file.
return 0;
}
}
@@ -639,7 +754,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
std::string const& a = args[4];
if (cmHasLiteralPrefix(a, "--nm=")) {
deffile.SetNmPath(a.substr(5));
- std::cerr << a.substr(5) << "\n";
} else {
std::cerr << "unknown argument: " << a << "\n";
}
@@ -1156,6 +1270,8 @@ 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);
@@ -1165,12 +1281,19 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
return 1;
}
+#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
+ // Internal CMake compiler dependencies filtering
+ if (args[1] == "cmake_cl_compile_depends") {
+ return CLCompileAndDependencies(args);
+ }
+#endif
+
// Internal CMake link script support.
if (args[1] == "cmake_link_script" && args.size() >= 3) {
return cmcmd::ExecuteLinkScript(args);
}
-#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_NINJA)
+#if !defined(CMAKE_BOOTSTRAP)
// Internal CMake ninja dependency scanning support.
if (args[1] == "cmake_ninja_depends") {
return cmcmd_cmake_ninja_depends(args.begin() + 2, args.end());
@@ -1359,47 +1482,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
if (args[1] == "server") {
- const std::string pipePrefix = "--pipe=";
- bool supportExperimental = false;
- bool isDebug = false;
- std::string pipe;
-
- for (auto const& arg : cmMakeRange(args).advance(2)) {
- if (arg == "--experimental") {
- supportExperimental = true;
- } else if (arg == "--debug") {
- pipe.clear();
- isDebug = true;
- } else if (cmHasPrefix(arg, pipePrefix)) {
- isDebug = false;
- pipe = arg.substr(pipePrefix.size());
- if (pipe.empty()) {
- cmSystemTools::Error("No pipe given after --pipe=");
- return 2;
- }
- } else {
- cmSystemTools::Error("Unknown argument for server mode");
- return 1;
- }
- }
-#if !defined(CMAKE_BOOTSTRAP)
- cmConnection* conn;
- if (isDebug) {
- conn = new cmServerStdIoConnection;
- } else {
- conn = new cmServerPipeConnection(pipe);
- }
- cmServer server(conn, supportExperimental);
- std::string errorMessage;
- if (server.Serve(&errorMessage)) {
- return 0;
- }
- cmSystemTools::Error(errorMessage);
-#else
- static_cast<void>(supportExperimental);
- static_cast<void>(isDebug);
- cmSystemTools::Error("CMake was not built with server mode enabled");
-#endif
+ cmSystemTools::Error(
+ "CMake server mode has been removed in favor of the file-api.");
return 1;
}
@@ -1435,9 +1519,48 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
return cmcmd::WindowsCEEnvironment("9.0", args[2]);
}
#endif
+
+ // Internal depfile transformation
+ if (args[1] == "cmake_transform_depfile" && args.size() == 10) {
+ auto format = cmDepfileFormat::GccDepfile;
+ if (args[3] == "gccdepfile") {
+ format = cmDepfileFormat::GccDepfile;
+ } else if (args[3] == "vstlog") {
+ format = cmDepfileFormat::VsTlog;
+ } else {
+ return 1;
+ }
+ // Create a cmake object instance to process dependencies.
+ // All we need is the `set` command.
+ cmake cm(cmake::RoleScript, cmState::Unknown);
+ std::string homeDir;
+ std::string startDir;
+ std::string homeOutDir;
+ std::string startOutDir;
+ homeDir = cmSystemTools::CollapseFullPath(args[4]);
+ startDir = cmSystemTools::CollapseFullPath(args[5]);
+ homeOutDir = cmSystemTools::CollapseFullPath(args[6]);
+ startOutDir = cmSystemTools::CollapseFullPath(args[7]);
+ cm.SetHomeDirectory(homeDir);
+ cm.SetHomeOutputDirectory(homeOutDir);
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
+ if (auto ggd = cm.CreateGlobalGenerator(args[2])) {
+ cm.SetGlobalGenerator(std::move(ggd));
+ 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);
+
+ return cmTransformDepfile(format, *lgd, args[8], args[9]) ? 0 : 2;
+ }
+ return 1;
+ }
}
- ::CMakeCommandUsage(args[0].c_str());
+ CMakeCommandUsage(args[0].c_str());
return 1;
}
@@ -1737,7 +1860,6 @@ int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name)
int cmcmd::RunPreprocessor(const std::vector<std::string>& command,
const std::string& intermediate_file)
{
-
cmUVProcessChainBuilder builder;
uv_fs_t fs_req;
@@ -1762,14 +1884,13 @@ int cmcmd::RunPreprocessor(const std::vector<std::string>& command,
}
auto status = process.GetStatus();
if (!status[0] || status[0]->ExitStatus != 0) {
- auto errorStream = process.ErrorStream();
+ auto* errorStream = process.ErrorStream();
if (errorStream) {
std::cerr << errorStream->rdbuf();
}
return 1;
}
-
return 0;
}
@@ -1787,19 +1908,56 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
std::cerr << "Invalid cmake_llvm_rc arguments";
return 1;
}
+
const std::string& intermediate_file = args[3];
const std::string& source_file = args[2];
std::vector<std::string> preprocess;
std::vector<std::string> resource_compile;
std::vector<std::string>* pArgTgt = &preprocess;
+
+ static const cmsys::RegularExpression llvm_rc_only_single_arg("^[-/](N|Y)");
+ static const cmsys::RegularExpression llvm_rc_only_double_arg(
+ "^[-/](C|LN|L)(.)?");
+ static const cmsys::RegularExpression common_double_arg(
+ "^[-/](D|U|I|FO|fo|Fo)(.)?");
+ bool acceptNextArg = false;
+ bool skipNextArg = false;
for (std::string const& arg : cmMakeRange(args).advance(4)) {
- // We use ++ as seperator between the preprocessing step definition and the
- // rc compilation step becase we need to prepend a -- to seperate the
+ if (skipNextArg) {
+ 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
// source file properly from other options when using clang-cl for
// preprocessing.
if (arg == "++") {
pArgTgt = &resource_compile;
+ skipNextArg = false;
+ acceptNextArg = true;
} else {
+ cmsys::RegularExpressionMatch match;
+ if (!acceptNextArg) {
+ if (common_double_arg.find(arg.c_str(), match)) {
+ acceptNextArg = match.match(2).empty();
+ } else {
+ if (llvm_rc_only_single_arg.find(arg.c_str(), match)) {
+ if (pArgTgt == &preprocess) {
+ continue;
+ }
+ } else if (llvm_rc_only_double_arg.find(arg.c_str(), match)) {
+ if (pArgTgt == &preprocess) {
+ skipNextArg = match.match(2).empty();
+ continue;
+ }
+ acceptNextArg = match.match(2).empty();
+ } else if (pArgTgt == &resource_compile) {
+ continue;
+ }
+ }
+ } else {
+ acceptNextArg = false;
+ }
if (arg.find("SOURCE_DIR") != std::string::npos) {
std::string sourceDirArg = arg;
cmSystemTools::ReplaceString(
@@ -1819,10 +1977,15 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
std::cerr << "Empty resource compilation command";
return 1;
}
+ // Since we might have skipped the last argument to llvm-rc
+ // we need to make sure the llvm-rc source file is present in the
+ // commandline
+ if (resource_compile.back() != intermediate_file) {
+ resource_compile.push_back(intermediate_file);
+ }
auto result = RunPreprocessor(preprocess, intermediate_file);
if (result != 0) {
-
cmSystemTools::RemoveFile(intermediate_file);
return result;
}
@@ -1849,7 +2012,7 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
}
auto status = process.GetStatus();
if (!status[0] || status[0]->ExitStatus != 0) {
- auto errorStream = process.ErrorStream();
+ auto* errorStream = process.ErrorStream();
if (errorStream) {
std::cerr << errorStream->rdbuf();
}
@@ -1986,7 +2149,7 @@ static bool RunCommand(const char* comment,
<< NumberFormatter(exitFormat, retCode)
<< ") with the following output:\n"
<< output;
- } else {
+ } else if (verbose) {
// always print the output of the command, unless
// it is the dumb rc command banner
if (output.find("Resource Compiler Version") == std::string::npos) {
@@ -2084,7 +2247,7 @@ int cmVSLink::Link()
if (this->Verbose) {
std::cout << "Visual Studio Incremental Link with embedded manifests\n";
}
- return LinkIncremental();
+ return this->LinkIncremental();
}
if (this->Verbose) {
if (!this->Incremental) {
@@ -2093,7 +2256,7 @@ int cmVSLink::Link()
std::cout << "Visual Studio Incremental Link without manifests\n";
}
}
- return LinkNonIncremental();
+ return this->LinkNonIncremental();
}
static bool mtRetIsUpdate(int mtRet)
@@ -2109,8 +2272,8 @@ int cmVSLink::LinkIncremental()
// http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
// 1. Compiler compiles the application and generates the *.obj files.
- // 2. An empty manifest file is generated if this is a clean build and if
- // not the previous one is reused.
+ // 2. An empty manifest file is generated if this is a clean build and
+ // if not the previous one is reused.
// 3. The resource compiler (rc.exe) compiles the *.manifest file to a
// *.res file.
// 4. Linker generates the binary (EXE or DLL) with the /incremental
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index d0bc0611b..3c331d32b 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -26,6 +26,9 @@ static const char* cmDocumentationUsage[][2] = { { nullptr,
{ nullptr, nullptr } };
static const char* cmDocumentationOptions[][2] = {
+ { "--preset <preset>, --preset=<preset>",
+ "Read arguments from a test preset." },
+ { "--list-presets", "List available test presets." },
{ "-C <cfg>, --build-config <cfg>", "Choose configuration to test." },
{ "--progress", "Enable short progress output from tests." },
{ "-V,--verbose", "Enable verbose output from tests." },
@@ -111,6 +114,7 @@ static const char* cmDocumentationOptions[][2] = {
{ "--no-subproject-summary",
"Disable timing summary information for "
"subprojects." },
+ { "--test-dir <dir>", "Specify the directory in which to look for tests." },
{ "--build-and-test", "Configure, build and run a test." },
{ "--build-target", "Specify a specific target to build." },
{ "--build-nocmake", "Run the build without running cmake first." },
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index b42448892..55a7fb195 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -167,6 +167,50 @@ protected:
};
template <typename CharType, typename Traits = std::char_traits<CharType> >
+class basic_fstream
+ : public std::basic_iostream<CharType, Traits>
+ , public basic_efilebuf<CharType, Traits>
+{
+public:
+ typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
+ internal_buffer_type;
+ typedef std::basic_iostream<CharType, Traits> internal_stream_type;
+
+ basic_fstream()
+ : internal_stream_type(new internal_buffer_type())
+ {
+ this->buf_ =
+ static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
+ }
+ explicit basic_fstream(char const* file_name,
+ std::ios_base::openmode mode = std::ios_base::in |
+ std::ios_base::out)
+ : internal_stream_type(new internal_buffer_type())
+ {
+ this->buf_ =
+ static_cast<internal_buffer_type*>(internal_stream_type::rdbuf());
+ open(file_name, mode);
+ }
+
+ void open(char const* file_name,
+ std::ios_base::openmode mode = std::ios_base::in |
+ std::ios_base::out)
+ {
+ this->_set_state(this->_open(file_name, mode), this, this);
+ }
+
+ bool is_open() { return this->_is_open(); }
+
+ void close() { this->_set_state(this->_close(), this, this); }
+
+ using basic_efilebuf<CharType, Traits>::_is_open;
+
+ internal_buffer_type* rdbuf() const { return this->buf_; }
+
+ ~basic_fstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
+};
+
+template <typename CharType, typename Traits = std::char_traits<CharType> >
class basic_ifstream
: public std::basic_istream<CharType, Traits>
, public basic_efilebuf<CharType, Traits>
@@ -251,11 +295,13 @@ public:
~basic_ofstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); }
};
+typedef basic_fstream<char> fstream;
typedef basic_ifstream<char> ifstream;
typedef basic_ofstream<char> ofstream;
# undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
#else
+using std::fstream;
using std::ofstream;
using std::ifstream;
#endif
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 12670762d..8f01684a1 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -962,7 +962,10 @@ void kwsysProcess_Execute(kwsysProcess* cp)
kwsysProcessCleanup(cp, GetLastError());
return;
}
- SetCurrentDirectoryW(cp->WorkingDirectory);
+ if (!SetCurrentDirectoryW(cp->WorkingDirectory)) {
+ kwsysProcessCleanup(cp, GetLastError());
+ return;
+ }
}
/* Setup the stdin pipe for the first process. */
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 9c34a565a..7743eabe9 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -447,6 +447,8 @@ public:
Motorola,
HP,
Hygon,
+ Zhaoxin,
+ Apple,
UnknownManufacturer
};
@@ -1731,7 +1733,8 @@ const char* SystemInformationImplementation::GetVendorID()
case NexGen:
return "NexGen Inc., Advanced Micro Devices";
case IDT:
- return "IDT\\Centaur, Via Inc.";
+ return "IDT\\Centaur, Via Inc., Shanghai Zhaoxin Semiconductor Co., "
+ "Ltd.";
case UMC:
return "United Microelectronics Corp.";
case Rise:
@@ -1748,6 +1751,10 @@ const char* SystemInformationImplementation::GetVendorID()
return "Hewlett-Packard";
case Hygon:
return "Chengdu Haiguang IC Design Co., Ltd.";
+ case Zhaoxin:
+ return "Shanghai Zhaoxin Semiconductor Co., Ltd.";
+ case Apple:
+ return "Apple";
case UnknownManufacturer:
default:
return "Unknown Manufacturer";
@@ -2109,7 +2116,10 @@ void SystemInformationImplementation::FindManufacturer(
else if (this->ChipID.Vendor == "NexGenDriven")
this->ChipManufacturer = NexGen; // NexGen Inc. (now AMD)
else if (this->ChipID.Vendor == "CentaurHauls")
- this->ChipManufacturer = IDT; // IDT/Centaur (now VIA)
+ this->ChipManufacturer = IDT; // original IDT/Centaur/VIA (now Zhaoxin)
+ else if (this->ChipID.Vendor == " Shanghai ")
+ this->ChipManufacturer =
+ Zhaoxin; // Shanghai Zhaoxin Semiconductor Co., Ltd.
else if (this->ChipID.Vendor == "RiseRiseRise")
this->ChipManufacturer = Rise; // Rise
else if (this->ChipID.Vendor == "GenuineTMx86")
@@ -2128,6 +2138,8 @@ void SystemInformationImplementation::FindManufacturer(
this->ChipManufacturer = Motorola; // Motorola Microelectronics
else if (family.compare(0, 7, "PA-RISC") == 0)
this->ChipManufacturer = HP; // Hewlett-Packard
+ else if (this->ChipID.Vendor == "Apple")
+ this->ChipManufacturer = Apple; // Apple
else
this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
}
@@ -3223,7 +3235,8 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
this->ChipID.ProcessorName = "C3";
break;
default:
- this->ChipID.ProcessorName = "Unknown IDT\\Centaur family";
+ this->ChipID.ProcessorName =
+ "Unknown IDT\\Centaur\\VIA\\Zhaoxin family";
return false;
}
break;
@@ -3232,13 +3245,63 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
case 6:
this->ChipID.ProcessorName = "VIA Cyrix III - Samuel";
break;
+ case 0xf:
+ this->ChipID.ProcessorName = "Zhaoxin zxc";
+ break;
default:
- this->ChipID.ProcessorName = "Unknown IDT\\Centaur family";
+ this->ChipID.ProcessorName =
+ "Unknown IDT\\Centaur\\VIA\\Zhaoxin family";
+ return false;
+ }
+ break;
+ case 7:
+ switch (this->ChipID.Model) {
+ case 0x1b:
+ this->ChipID.ProcessorName = "Zhaoxin kx5000";
+ break;
+ case 0x3b:
+ this->ChipID.ProcessorName = "Zhaoxin kx6000";
+ break;
+ default:
+ this->ChipID.ProcessorName =
+ "Unknown IDT\\Centaur\\VIA\\Zhaoxin family";
return false;
}
break;
default:
- this->ChipID.ProcessorName = "Unknown IDT\\Centaur family";
+ this->ChipID.ProcessorName =
+ "Unknown IDT\\Centaur\\VIA\\Zhaoxin family";
+ return false;
+ }
+ break;
+
+ case Zhaoxin:
+ switch (this->ChipID.Family) {
+ case 6:
+ switch (this->ChipID.Model) {
+ case 0x19:
+ this->ChipID.ProcessorName = "Zhaoxin zxc";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Zhaoxin family";
+ return false;
+ }
+ break;
+ case 7:
+ switch (this->ChipID.Model) {
+ case 0x1b:
+ this->ChipID.ProcessorName = "Zhaoxin kx5000";
+ break;
+ case 0x3b:
+ this->ChipID.ProcessorName = "Zhaoxin kx6000";
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Zhaoxin family";
+ return false;
+ }
+ break;
+ default:
+ this->ChipID.ProcessorName = "Unknown Zhaoxin family";
return false;
}
break;
@@ -4445,33 +4508,62 @@ unsigned int SystemInformationImplementation::GetNumberOfPhysicalCPU() const
return this->NumberOfPhysicalCPU;
}
-/** For Mac use sysctlbyname calls to find system info */
+#if defined(__APPLE__)
+static int kw_sysctlbyname_int32(const char* name, int32_t* value)
+{
+ size_t len = sizeof(int32_t);
+ int err = sysctlbyname(name, value, &len, nullptr, 0);
+ if (err == 0) {
+ assert(len == sizeof(int32_t));
+ }
+ return err;
+}
+
+static int kw_sysctlbyname_int64(const char* name, int64_t* value)
+{
+ size_t len = sizeof(int64_t);
+ int err = sysctlbyname(name, value, &len, nullptr, 0);
+ if (err == 0) {
+ assert(len == sizeof(int64_t));
+ }
+ return err;
+}
+#endif
+
+/** For Apple use sysctlbyname calls to find system info */
bool SystemInformationImplementation::ParseSysCtl()
{
#if defined(__APPLE__)
- char retBuf[128];
+ char tempBuff[128];
+ int32_t tempInt32 = 0;
+ int64_t tempInt64 = 0;
int err = 0;
- uint64_t value = 0;
- size_t len = sizeof(value);
- sysctlbyname("hw.memsize", &value, &len, nullptr, 0);
- this->TotalPhysicalMemory = static_cast<size_t>(value / 1048576);
+ size_t len;
+
+ this->TotalPhysicalMemory = 0;
+ err = kw_sysctlbyname_int64("hw.memsize", &tempInt64);
+ if (err == 0) {
+ this->TotalPhysicalMemory = static_cast<size_t>(tempInt64 / 1024 / 1024);
+ }
- // Parse values for Mac
this->AvailablePhysicalMemory = 0;
vm_statistics_data_t vmstat;
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat,
&count) == KERN_SUCCESS) {
- len = sizeof(value);
- err = sysctlbyname("hw.pagesize", &value, &len, nullptr, 0);
- int64_t available_memory =
- (vmstat.free_count + vmstat.inactive_count) * value;
- this->AvailablePhysicalMemory =
- static_cast<size_t>(available_memory / 1048576);
+ err = kw_sysctlbyname_int64("hw.pagesize", &tempInt64);
+ if (err == 0) {
+ int64_t available_memory =
+ (vmstat.free_count + vmstat.inactive_count) * tempInt64;
+ this->AvailablePhysicalMemory =
+ static_cast<size_t>(available_memory / 1024 / 1024);
+ }
}
-# ifdef VM_SWAPUSAGE
// Virtual memory.
+ this->AvailableVirtualMemory = 0;
+ this->TotalVirtualMemory = 0;
+# ifdef VM_SWAPUSAGE
int mib[2] = { CTL_VM, VM_SWAPUSAGE };
unsigned int miblen =
static_cast<unsigned int>(sizeof(mib) / sizeof(mib[0]));
@@ -4480,78 +4572,98 @@ bool SystemInformationImplementation::ParseSysCtl()
err = sysctl(mib, miblen, &swap, &len, nullptr, 0);
if (err == 0) {
this->AvailableVirtualMemory =
- static_cast<size_t>(swap.xsu_avail / 1048576);
- this->TotalVirtualMemory = static_cast<size_t>(swap.xsu_total / 1048576);
+ static_cast<size_t>(swap.xsu_avail / 1024 / 1024);
+ this->TotalVirtualMemory =
+ static_cast<size_t>(swap.xsu_total / 1024 / 1024);
}
-# else
- this->AvailableVirtualMemory = 0;
- this->TotalVirtualMemory = 0;
# endif
// CPU Info
- len = sizeof(this->NumberOfPhysicalCPU);
- sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, nullptr, 0);
- len = sizeof(this->NumberOfLogicalCPU);
- sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, nullptr, 0);
-
- int cores_per_package = 0;
- len = sizeof(cores_per_package);
- err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len,
- nullptr, 0);
- // That name was not found, default to 1
- this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
- err != 0 ? 1 : static_cast<unsigned char>(cores_per_package);
+ this->NumberOfPhysicalCPU = 1;
+ err = kw_sysctlbyname_int32("hw.physicalcpu", &tempInt32);
+ if (err == 0) {
+ this->NumberOfPhysicalCPU = tempInt32;
+ }
+
+ this->NumberOfLogicalCPU = 1;
+ err = kw_sysctlbyname_int32("hw.logicalcpu", &tempInt32);
+ if (err == 0) {
+ this->NumberOfLogicalCPU = tempInt32;
+ }
+
+ this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = 1;
+ err = kw_sysctlbyname_int32("machdep.cpu.cores_per_package", &tempInt32);
+ if (err == 0) {
+ this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = tempInt32;
+ }
- len = sizeof(value);
- sysctlbyname("hw.cpufrequency", &value, &len, nullptr, 0);
- this->CPUSpeedInMHz = static_cast<float>(value) / 1000000;
+ this->CPUSpeedInMHz = 0;
+ err = kw_sysctlbyname_int64("hw.cpufrequency", &tempInt64);
+ if (err == 0) {
+ this->CPUSpeedInMHz = static_cast<float>(tempInt64) / 1000000.0f;
+ }
// Chip family
- len = sizeof(this->ChipID.Family);
- // Seems only the intel chips will have this name so if this fails it is
- // probably a PPC machine
- err =
- sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len, nullptr, 0);
+ // Seems only the Intel chips will have this name so if this fails it is
+ // a PowerPC or ARM, or something unknown
+ this->ChipID.Vendor = "";
+ this->ChipID.Family = 0;
+ this->ChipID.Model = 0;
+ this->ChipID.Revision = 0;
+ err = kw_sysctlbyname_int32("machdep.cpu.family", &tempInt32);
if (err != 0) // Go back to names we know but are less descriptive
{
- this->ChipID.Family = 0;
- ::memset(retBuf, 0, 128);
- len = 32;
- err = sysctlbyname("hw.machine", &retBuf, &len, nullptr, 0);
- std::string machineBuf(retBuf);
- if (machineBuf.find_first_of("Power") != std::string::npos) {
- this->ChipID.Vendor = "IBM";
- len = sizeof(this->ChipID.Family);
- err = sysctlbyname("hw.cputype", &this->ChipID.Family, &len, nullptr, 0);
- len = sizeof(this->ChipID.Model);
- err =
- sysctlbyname("hw.cpusubtype", &this->ChipID.Model, &len, nullptr, 0);
- this->FindManufacturer();
+ ::memset(tempBuff, 0, sizeof(tempBuff));
+ len = sizeof(tempBuff) - 1; // leave a byte for null termination
+ err = sysctlbyname("hw.machine", &tempBuff, &len, nullptr, 0);
+ if (err == 0) {
+ std::string machineBuf(tempBuff);
+ if (machineBuf.find_first_of("Power") != std::string::npos) {
+ this->ChipID.Vendor = "IBM";
+
+ err = kw_sysctlbyname_int32("hw.cputype", &tempInt32);
+ if (err == 0) {
+ this->ChipID.Family = tempInt32;
+ }
+
+ err = kw_sysctlbyname_int32("hw.cpusubtype", &tempInt32);
+ if (err == 0) {
+ this->ChipID.Model = tempInt32;
+ }
+
+ this->FindManufacturer();
+ } else if (machineBuf.find_first_of("arm64") != std::string::npos) {
+ this->ChipID.Vendor = "Apple";
+
+ this->FindManufacturer();
+ }
+ }
+ } else {
+ // Should be an Intel Chip.
+ err = kw_sysctlbyname_int32("machdep.cpu.family", &tempInt32);
+ if (err == 0) {
+ this->ChipID.Family = tempInt32;
}
- } else // Should be an Intel Chip.
- {
- len = sizeof(this->ChipID.Family);
- err = sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len,
- nullptr, 0);
- ::memset(retBuf, 0, 128);
- len = 128;
- err = sysctlbyname("machdep.cpu.vendor", retBuf, &len, nullptr, 0);
// Chip Vendor
- this->ChipID.Vendor = retBuf;
+ ::memset(tempBuff, 0, sizeof(tempBuff));
+ len = sizeof(tempBuff) - 1; // leave a byte for null termination
+ err = sysctlbyname("machdep.cpu.vendor", tempBuff, &len, nullptr, 0);
+ if (err == 0) {
+ this->ChipID.Vendor = tempBuff;
+ }
this->FindManufacturer();
// Chip Model
- len = sizeof(value);
- err = sysctlbyname("machdep.cpu.model", &value, &len, nullptr, 0);
- this->ChipID.Model = static_cast<int>(value);
+ err = kw_sysctlbyname_int32("machdep.cpu.model", &tempInt32);
+ if (err == 0) {
+ this->ChipID.Model = tempInt32;
+ }
// Chip Stepping
- len = sizeof(value);
- value = 0;
- err = sysctlbyname("machdep.cpu.stepping", &value, &len, nullptr, 0);
- if (!err) {
- this->ChipID.Revision = static_cast<int>(value);
+ err = kw_sysctlbyname_int32("machdep.cpu.stepping", &tempInt32);
+ if (err == 0) {
+ this->ChipID.Revision = tempInt32;
}
// feature string
@@ -4574,36 +4686,36 @@ bool SystemInformationImplementation::ParseSysCtl()
len = allocSize - 2; // keep space for leading and trailing space
err = sysctlbyname("machdep.cpu.features", buf + 1, &len, nullptr, 0);
}
- if (!err && buf && len) {
+ if (err == 0 && buf && len) {
// now we can match every flags as space + flag + space
buf[len + 1] = ' ';
std::string cpuflags(buf, len + 2);
- if ((cpuflags.find(" FPU ") != std::string::npos)) {
+ if (cpuflags.find(" FPU ") != std::string::npos) {
this->Features.HasFPU = true;
}
- if ((cpuflags.find(" TSC ") != std::string::npos)) {
+ if (cpuflags.find(" TSC ") != std::string::npos) {
this->Features.HasTSC = true;
}
- if ((cpuflags.find(" MMX ") != std::string::npos)) {
+ if (cpuflags.find(" MMX ") != std::string::npos) {
this->Features.HasMMX = true;
}
- if ((cpuflags.find(" SSE ") != std::string::npos)) {
+ if (cpuflags.find(" SSE ") != std::string::npos) {
this->Features.HasSSE = true;
}
- if ((cpuflags.find(" SSE2 ") != std::string::npos)) {
+ if (cpuflags.find(" SSE2 ") != std::string::npos) {
this->Features.HasSSE2 = true;
}
- if ((cpuflags.find(" APIC ") != std::string::npos)) {
+ if (cpuflags.find(" APIC ") != std::string::npos) {
this->Features.HasAPIC = true;
}
- if ((cpuflags.find(" CMOV ") != std::string::npos)) {
+ if (cpuflags.find(" CMOV ") != std::string::npos) {
this->Features.HasCMOV = true;
}
- if ((cpuflags.find(" MTRR ") != std::string::npos)) {
+ if (cpuflags.find(" MTRR ") != std::string::npos) {
this->Features.HasMTRR = true;
}
- if ((cpuflags.find(" ACPI ") != std::string::npos)) {
+ if (cpuflags.find(" ACPI ") != std::string::npos) {
this->Features.HasACPI = true;
}
}
@@ -4611,21 +4723,29 @@ bool SystemInformationImplementation::ParseSysCtl()
}
// brand string
- ::memset(retBuf, 0, sizeof(retBuf));
- len = sizeof(retBuf);
- err = sysctlbyname("machdep.cpu.brand_string", retBuf, &len, nullptr, 0);
- if (!err) {
- this->ChipID.ProcessorName = retBuf;
- this->ChipID.ModelName = retBuf;
+ this->ChipID.ProcessorName = "";
+ this->ChipID.ModelName = "";
+ ::memset(tempBuff, 0, sizeof(tempBuff));
+ len = sizeof(tempBuff) - 1; // leave a byte for null termination
+ err = sysctlbyname("machdep.cpu.brand_string", tempBuff, &len, nullptr, 0);
+ if (err == 0) {
+ this->ChipID.ProcessorName = tempBuff;
+ this->ChipID.ModelName = tempBuff;
}
- // Cache size
- len = sizeof(value);
- err = sysctlbyname("hw.l1icachesize", &value, &len, nullptr, 0);
- this->Features.L1CacheSize = static_cast<int>(value);
- len = sizeof(value);
- err = sysctlbyname("hw.l2cachesize", &value, &len, nullptr, 0);
- this->Features.L2CacheSize = static_cast<int>(value);
+ // L1 Cache size
+ this->Features.L1CacheSize = 0;
+ err = kw_sysctlbyname_int64("hw.l1icachesize", &tempInt64);
+ if (err == 0) {
+ this->Features.L1CacheSize = static_cast<int>(tempInt64);
+ }
+
+ // L2 Cache size
+ this->Features.L2CacheSize = 0;
+ err = kw_sysctlbyname_int64("hw.l2cachesize", &tempInt64);
+ if (err == 0) {
+ this->Features.L2CacheSize = static_cast<int>(tempInt64);
+ }
return true;
#else
diff --git a/Source/kwsys/testFStream.cxx b/Source/kwsys/testFStream.cxx
index afba9530e..3325e2046 100644
--- a/Source/kwsys/testFStream.cxx
+++ b/Source/kwsys/testFStream.cxx
@@ -99,12 +99,50 @@ static int testBOM()
return 0;
}
+static int testBOMIO()
+{
+ // test various encodings in binary mode
+ for (int i = 0; i < num_test_files; i++) {
+ kwsys::fstream f("bomio.txt",
+ kwsys::fstream::in | kwsys::fstream::out |
+ kwsys::fstream::binary | kwsys::fstream::trunc);
+ f.write(reinterpret_cast<const char*>(expected_bom_data[i] + 1),
+ *expected_bom_data[i]);
+ f.write(reinterpret_cast<const char*>(file_data[i] + 1), file_data[i][0]);
+ if (!f.good()) {
+ std::cout << "Unable to write data " << i << std::endl;
+ return 1;
+ }
+ f.seekp(0);
+
+ kwsys::FStream::BOM bom = kwsys::FStream::ReadBOM(f);
+ if (bom != expected_bom[i]) {
+ std::cout << "Unexpected BOM " << i << std::endl;
+ return 1;
+ }
+ char data[max_test_file_size];
+ f.read(data, file_data[i][0]);
+ if (!f.good()) {
+ std::cout << "Unable to read data " << i << std::endl;
+ return 1;
+ }
+
+ if (memcmp(data, file_data[i] + 1, file_data[i][0]) != 0) {
+ std::cout << "Incorrect read data " << i << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int testFStream(int, char* [])
{
int ret = 0;
ret |= testNoFile();
ret |= testBOM();
+ ret |= testBOMIO();
return ret;
}
diff --git a/Templates/MSBuild/FlagTables/v142_CSharp.json b/Templates/MSBuild/FlagTables/v142_CSharp.json
index 5989aea1e..4dcea9de3 100644
--- a/Templates/MSBuild/FlagTables/v142_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v142_CSharp.json
@@ -201,6 +201,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:portable",
+ "comment": "",
+ "value": "portable",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
@@ -264,6 +271,17 @@
"flags": []
},
{
+ "name": "WarningsAsErrors",
+ "switch": "warnaserror:",
+ "comment": "",
+ "value": "",
+ "flags": [
+ "UserValue",
+ "UserRequired",
+ "CommaAppendable"
+ ]
+ },
+ {
"name": "WarningLevel",
"switch": "warn:0",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v142_Link.json b/Templates/MSBuild/FlagTables/v142_Link.json
index 66ee76fcb..110dcc2b1 100644
--- a/Templates/MSBuild/FlagTables/v142_Link.json
+++ b/Templates/MSBuild/FlagTables/v142_Link.json
@@ -352,6 +352,13 @@
},
{
"name": "TargetMachine",
+ "switch": "MACHINE:ARM64EC",
+ "comment": "MachineARM64EC",
+ "value": "MachineARM64EC",
+ "flags": []
+ },
+ {
+ "name": "TargetMachine",
"switch": "MACHINE:EBC",
"comment": "MachineEBC",
"value": "MachineEBC",
diff --git a/Templates/MSBuild/FlagTables/v14_LIB.json b/Templates/MSBuild/FlagTables/v14_LIB.json
index 5990ed1b7..a0e85b28b 100644
--- a/Templates/MSBuild/FlagTables/v14_LIB.json
+++ b/Templates/MSBuild/FlagTables/v14_LIB.json
@@ -43,6 +43,13 @@
},
{
"name": "TargetMachine",
+ "switch": "MACHINE:ARM64X",
+ "comment": "MachineARM64X",
+ "value": "MachineARM64X",
+ "flags": []
+ },
+ {
+ "name": "TargetMachine",
"switch": "MACHINE:EBC",
"comment": "MachineEBC",
"value": "MachineEBC",
diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in
index 053f1ee38..3e47d6a0d 100644
--- a/Templates/TestDriver.cxx.in
+++ b/Templates/TestDriver.cxx.in
@@ -34,7 +34,7 @@ typedef struct /* NOLINT */
} functionMapEntry;
static functionMapEntry cmakeGeneratedFunctionMapEntries[] = {
- @CMAKE_FUNCTION_TABLE_ENTIRES@
+ @CMAKE_FUNCTION_TABLE_ENTRIES@
{ CM_NULL, CM_NULL } /* NOLINT */
};
diff --git a/Tests/Architecture/CMakeLists.txt b/Tests/Architecture/CMakeLists.txt
index ea5fc0b50..96def003b 100644
--- a/Tests/Architecture/CMakeLists.txt
+++ b/Tests/Architecture/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(Architecture C)
function(test_for_xcode4 result_var)
diff --git a/Tests/ArgumentExpansion/CMakeLists.txt b/Tests/ArgumentExpansion/CMakeLists.txt
index 173540067..da3bb4c90 100644
--- a/Tests/ArgumentExpansion/CMakeLists.txt
+++ b/Tests/ArgumentExpansion/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ArgumentExpansion)
diff --git a/Tests/Assembler/CMakeLists.txt b/Tests/Assembler/CMakeLists.txt
index a574c4e1f..0a2c819fd 100644
--- a/Tests/Assembler/CMakeLists.txt
+++ b/Tests/Assembler/CMakeLists.txt
@@ -9,7 +9,7 @@ set(SRCS)
# and also generate assembler files from C:
if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode|Ninja" AND
NOT CMAKE_OSX_ARCHITECTURES MATCHES ";")
- if((CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang|HP|SunPro|XL)$") OR (CMAKE_C_COMPILER_ID STREQUAL "Intel" AND UNIX)
+ if((CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang|HP|SunPro|XL)$") OR (CMAKE_C_COMPILER_ID MATCHES "Intel" AND UNIX)
AND NOT (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC"))
set(C_FLAGS "${CMAKE_C_FLAGS}")
separate_arguments(C_FLAGS)
diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt
index c438e1dde..c2576f3e3 100644
--- a/Tests/BuildDepends/Project/CMakeLists.txt
+++ b/Tests/BuildDepends/Project/CMakeLists.txt
@@ -102,6 +102,12 @@ target_link_libraries(zot zot_pch)
if(NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
target_precompile_headers(zot_pch PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/zot_pch.hxx)
endif()
+if (CMAKE_CXX_DEPENDS_USE_COMPILER AND
+ CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.4")
+ # Mixing pre-compile headers and flags to generate dependencies (-M options family)
+ # causes the compiler to crash
+ set_property(TARGET zot_pch PROPERTY DISABLE_PRECOMPILE_HEADERS ON)
+endif()
# Test the #include line macro transformation rule support.
set_property(
diff --git a/Tests/BundleTest/BundleLib.cxx b/Tests/BundleTest/BundleLib.cxx
index b7fd70d9a..d25ad279e 100644
--- a/Tests/BundleTest/BundleLib.cxx
+++ b/Tests/BundleTest/BundleLib.cxx
@@ -52,8 +52,8 @@ int foo(char* exec)
(void)br;
int res1 = findBundleFile(exec, "Resources/randomResourceFile.plist");
- int res2 = findBundleFile(exec, "MacOS/SomeRandomFile.txt");
- int res3 = findBundleFile(exec, "MacOS/README.rst");
+ int res2 = findBundleFile(exec, "Other/SomeRandomFile.txt");
+ int res3 = findBundleFile(exec, "Other/README.rst");
if (!res1 || !res2 || !res3) {
return 1;
}
diff --git a/Tests/BundleTest/BundleSubDir/CMakeLists.txt b/Tests/BundleTest/BundleSubDir/CMakeLists.txt
index 5f91f20d1..ceb52165b 100644
--- a/Tests/BundleTest/BundleSubDir/CMakeLists.txt
+++ b/Tests/BundleTest/BundleSubDir/CMakeLists.txt
@@ -16,7 +16,7 @@ set_source_files_properties(
"${BundleTest_SOURCE_DIR}/SomeRandomFile.txt"
"${BundleTest_SOURCE_DIR}/../../README.rst"
PROPERTIES
- MACOSX_PACKAGE_LOCATION MacOS
+ MACOSX_PACKAGE_LOCATION Other
)
add_executable(SecondBundle
@@ -35,11 +35,7 @@ install(TARGETS SecondBundle DESTINATION Applications)
# installed into a location that uses this output name this will fail if the
# bundle does not respect the name. Also the executable will not be found by
# the test driver if this does not work.
-set_target_properties(SecondBundle PROPERTIES
- OUTPUT_NAME SecondBundleExe
- XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
- XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
- )
+set_target_properties(SecondBundle PROPERTIES OUTPUT_NAME SecondBundleExe)
# Express one app bundle in terms of another's SOURCES to verify that
# the generators do not expose the Info.plist of one to the other.
diff --git a/Tests/BundleTest/CMakeLists.txt b/Tests/BundleTest/CMakeLists.txt
index 1bedc708d..c63461a2c 100644
--- a/Tests/BundleTest/CMakeLists.txt
+++ b/Tests/BundleTest/CMakeLists.txt
@@ -3,6 +3,15 @@ project(BundleTest)
set(MACOSX_BUNDLE_INFO_STRING "bundle_info_string")
set(CMAKE_MacOSX_Content_COMPILE_OBJECT "\"${CMAKE_COMMAND}\" -E copy_if_different <SOURCE> <OBJECT>")
+if(CMAKE_GENERATOR STREQUAL "Xcode" AND
+ "${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64")
+ # Tell Xcode to pretend the linker signed binaries so that
+ # editing with install_name_tool preserves ad-hoc signatures.
+ # See CMake Issue 21854.
+ # This option is supported by codesign on macOS 11 or higher.
+ set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "-o linker-signed")
+endif()
+
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/randomResourceFile.plist"
COMMAND /bin/cp
@@ -19,7 +28,7 @@ set_source_files_properties(
SomeRandomFile.txt
"${BundleTest_SOURCE_DIR}/../../README.rst"
PROPERTIES
- MACOSX_PACKAGE_LOCATION MacOS
+ MACOSX_PACKAGE_LOCATION Other
)
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/foobar")
@@ -56,11 +65,7 @@ install(TARGETS BundleTest DESTINATION Applications)
# installed into a location that uses this output name this will fail if the
# bundle does not respect the name. Also the executable will not be found by
# the test driver if this does not work.
-set_target_properties(BundleTest PROPERTIES
- OUTPUT_NAME BundleTestExe
- XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
- XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
- )
+set_target_properties(BundleTest PROPERTIES OUTPUT_NAME BundleTestExe)
# Test executable versioning if it is supported.
if(NOT XCODE)
diff --git a/Tests/BundleUtilities/CMakeLists.txt b/Tests/BundleUtilities/CMakeLists.txt
index 69ef53505..4a95e2fd4 100644
--- a/Tests/BundleUtilities/CMakeLists.txt
+++ b/Tests/BundleUtilities/CMakeLists.txt
@@ -1,6 +1,15 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(BundleUtilities)
+if(CMAKE_GENERATOR STREQUAL "Xcode" AND
+ "${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64")
+ # Tell Xcode to pretend the linker signed binaries so that
+ # editing with install_name_tool preserves ad-hoc signatures.
+ # See CMake Issue 21854.
+ # This option is supported by codesign on macOS 11 or higher.
+ set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "-o linker-signed")
+endif()
+
###### the various types of dependencies we can have
# a shared library
diff --git a/Tests/CFBundleTest/CMakeLists.txt b/Tests/CFBundleTest/CMakeLists.txt
index b2b1b7316..5f2e8ec25 100644
--- a/Tests/CFBundleTest/CMakeLists.txt
+++ b/Tests/CFBundleTest/CMakeLists.txt
@@ -1,6 +1,6 @@
#this is adapted from FireBreath (http://www.firebreath.org)
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CFBundleTest)
diff --git a/Tests/CMakeCommands/add_compile_options/CMakeLists.txt b/Tests/CMakeCommands/add_compile_options/CMakeLists.txt
index 995b32c28..b28d0bee9 100644
--- a/Tests/CMakeCommands/add_compile_options/CMakeLists.txt
+++ b/Tests/CMakeCommands/add_compile_options/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(add_compile_options)
diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
index a5bc1e1b3..72b3502ba 100644
--- a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(target_compile_definitions)
diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
index a7055b157..268c7eb92 100644
--- a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(target_compile_options)
diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
index 8713d99dd..0702ab5b2 100644
--- a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(target_include_directories)
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
index 5c704ac83..aa8e21a68 100644
--- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Using 2.8 will trigger a deprecation warning. In this case it's explicitly
+# intentional since the tests checks various policy implementations prior to
+# 2.8.12
cmake_minimum_required(VERSION 2.8)
project(target_link_libraries)
diff --git a/Tests/CMakeLib/run_compile_commands.cxx b/Tests/CMakeLib/run_compile_commands.cxx
index 2c77accf1..0ebe00e7d 100644
--- a/Tests/CMakeLib/run_compile_commands.cxx
+++ b/Tests/CMakeLib/run_compile_commands.cxx
@@ -36,8 +36,8 @@ public:
void Parse()
{
- NextNonWhitespace();
- ParseTranslationUnits();
+ this->NextNonWhitespace();
+ this->ParseTranslationUnits();
}
const TranslationUnitsType& GetTranslationUnits()
@@ -49,51 +49,51 @@ private:
void ParseTranslationUnits()
{
this->TranslationUnits = TranslationUnitsType();
- ExpectOrDie('[', "at start of compile command file\n");
+ this->ExpectOrDie('[', "at start of compile command file\n");
do {
- ParseTranslationUnit();
+ this->ParseTranslationUnit();
this->TranslationUnits.push_back(this->Command);
- } while (Expect(','));
- ExpectOrDie(']', "at end of array");
+ } while (this->Expect(','));
+ this->ExpectOrDie(']', "at end of array");
}
void ParseTranslationUnit()
{
this->Command = CommandType();
- if (!Expect('{')) {
+ if (!this->Expect('{')) {
return;
}
- if (Expect('}')) {
+ if (this->Expect('}')) {
return;
}
do {
- ParseString();
+ this->ParseString();
std::string name = this->String;
- ExpectOrDie(':', "between name and value");
- ParseString();
+ this->ExpectOrDie(':', "between name and value");
+ this->ParseString();
std::string value = this->String;
this->Command[name] = value;
- } while (Expect(','));
- ExpectOrDie('}', "at end of object");
+ } while (this->Expect(','));
+ this->ExpectOrDie('}', "at end of object");
}
void ParseString()
{
this->String = "";
- if (!Expect('"')) {
+ if (!this->Expect('"')) {
return;
}
- while (!Expect('"')) {
- Expect('\\');
- this->String.append(1, C);
- Next();
+ while (!this->Expect('"')) {
+ this->Expect('\\');
+ this->String.append(1, this->C);
+ this->Next();
}
}
bool Expect(char c)
{
if (this->C == c) {
- NextNonWhitespace();
+ this->NextNonWhitespace();
return true;
}
return false;
@@ -101,23 +101,23 @@ private:
void ExpectOrDie(char c, const std::string& message)
{
- if (!Expect(c)) {
- ErrorExit(std::string("'") + c + "' expected " + message + ".");
+ if (!this->Expect(c)) {
+ this->ErrorExit(std::string("'") + c + "' expected " + message + ".");
}
}
void NextNonWhitespace()
{
do {
- Next();
- } while (IsWhitespace());
+ this->Next();
+ } while (this->IsWhitespace());
}
void Next()
{
- this->C = char(Input.get());
+ this->C = char(this->Input.get());
if (this->Input.bad()) {
- ErrorExit("Unexpected end of file.");
+ this->ErrorExit("Unexpected end of file.");
}
}
@@ -127,7 +127,7 @@ private:
exit(1);
}
- bool IsWhitespace()
+ bool IsWhitespace() const
{
return (this->C == ' ' || this->C == '\t' || this->C == '\n' ||
this->C == '\r');
diff --git a/Tests/CMakeLib/testCMExtMemory.cxx b/Tests/CMakeLib/testCMExtMemory.cxx
index 2aeaf7f84..d8932cef1 100644
--- a/Tests/CMakeLib/testCMExtMemory.cxx
+++ b/Tests/CMakeLib/testCMExtMemory.cxx
@@ -26,9 +26,9 @@ public:
: value(v)
{
}
- ~Wrapper() { delete value; }
+ ~Wrapper() { delete this->value; }
- T* get() const { return value; }
+ T* get() const { return this->value; }
private:
T* value;
diff --git a/Tests/CMakeLib/testGccDepfileReader.cxx b/Tests/CMakeLib/testGccDepfileReader.cxx
index e79f047fd..d46e8f3fe 100644
--- a/Tests/CMakeLib/testGccDepfileReader.cxx
+++ b/Tests/CMakeLib/testGccDepfileReader.cxx
@@ -5,6 +5,8 @@
#include <utility>
#include <vector>
+#include <cm/optional>
+
#include "cmsys/FStream.hxx"
#include "cmGccDepfileReader.h"
@@ -112,17 +114,26 @@ int testGccDepfileReader(int argc, char* argv[])
std::string dataDirPath = argv[1];
dataDirPath += "/testGccDepfileReader_data";
- const int numberOfTestFiles = 3;
+ const int numberOfTestFiles = 7; // 6th file doesn't exist
for (int i = 1; i <= numberOfTestFiles; ++i) {
const std::string base = dataDirPath + "/deps" + std::to_string(i);
const std::string depfile = base + ".d";
const std::string plainDepfile = base + ".txt";
std::cout << "Comparing " << base << " with " << plainDepfile << std::endl;
const auto actual = cmReadGccDepfile(depfile.c_str());
- const auto expected = readPlainDepfile(plainDepfile.c_str());
- if (!compare(actual, expected)) {
- dump("actual", actual);
- dump("expected", expected);
+ if (cmSystemTools::FileExists(plainDepfile)) {
+ if (!actual) {
+ std::cerr << "Reading " << depfile << " should have succeeded\n";
+ return 1;
+ }
+ const auto expected = readPlainDepfile(plainDepfile.c_str());
+ if (!compare(*actual, expected)) {
+ dump("actual", *actual);
+ dump("expected", expected);
+ return 1;
+ }
+ } else if (actual) {
+ std::cerr << "Reading " << depfile << " should have failed\n";
return 1;
}
}
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps4.d b/Tests/CMakeLib/testGccDepfileReader_data/deps4.d
new file mode 100644
index 000000000..9977a2836
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps4.d
@@ -0,0 +1 @@
+invalid
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps5.d b/Tests/CMakeLib/testGccDepfileReader_data/deps5.d
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps5.d
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps5.txt b/Tests/CMakeLib/testGccDepfileReader_data/deps5.txt
new file mode 100644
index 000000000..6c4a75bc9
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps5.txt
@@ -0,0 +1,2 @@
+--RULES--
+--DEPENDENCIES--
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps7.d b/Tests/CMakeLib/testGccDepfileReader_data/deps7.d
new file mode 100644
index 000000000..92280cf82
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps7.d
@@ -0,0 +1,6 @@
+out1 \
+ out2: \
+ in1 \
+ in2
+
+out3: in3
diff --git a/Tests/CMakeLib/testGccDepfileReader_data/deps7.txt b/Tests/CMakeLib/testGccDepfileReader_data/deps7.txt
new file mode 100644
index 000000000..86b6600d0
--- /dev/null
+++ b/Tests/CMakeLib/testGccDepfileReader_data/deps7.txt
@@ -0,0 +1,10 @@
+--RULES--
+out1
+out2
+--DEPENDENCIES--
+in1
+in2
+--RULES--
+out3
+--DEPENDENCIES--
+in3
diff --git a/Tests/CMakeLib/testOptional.cxx b/Tests/CMakeLib/testOptional.cxx
index de09c0fce..2d7dd7c68 100644
--- a/Tests/CMakeLib/testOptional.cxx
+++ b/Tests/CMakeLib/testOptional.cxx
@@ -82,6 +82,18 @@ public:
int Value = 0;
};
+class NoMoveAssignEventLogger : public EventLogger
+{
+public:
+ using EventLogger::EventLogger;
+
+ NoMoveAssignEventLogger(const NoMoveAssignEventLogger&) = default;
+ NoMoveAssignEventLogger(NoMoveAssignEventLogger&&) = default;
+
+ NoMoveAssignEventLogger& operator=(const NoMoveAssignEventLogger&) = default;
+ NoMoveAssignEventLogger& operator=(NoMoveAssignEventLogger&&) = delete;
+};
+
#define ASSERT_TRUE(x) \
do { \
if (!(x)) { \
@@ -328,12 +340,28 @@ static bool testCopyAssign(std::vector<Event>& expected)
o1 = o4; // Intentionally duplicated to test assigning an empty optional to
// an empty optional
+ cm::optional<NoMoveAssignEventLogger> o5{ 1 };
+ auto const* v5 = &*o5;
+ const cm::optional<NoMoveAssignEventLogger> o6{ 2 };
+ auto const* v6 = &*o6;
+ o5 = std::move(o6);
+ const NoMoveAssignEventLogger e7{ 3 };
+ o5 = std::move(e7);
+
expected = {
{ Event::VALUE_CONSTRUCT, v2, nullptr, 4 },
{ Event::COPY_CONSTRUCT, v1, v2, 4 },
{ Event::VALUE_CONSTRUCT, v3, nullptr, 5 },
{ Event::COPY_ASSIGN, v1, v3, 5 },
{ Event::DESTRUCT, v1, nullptr, 5 },
+ { Event::VALUE_CONSTRUCT, v5, nullptr, 1 },
+ { Event::VALUE_CONSTRUCT, v6, nullptr, 2 },
+ { Event::COPY_ASSIGN, v5, v6, 2 },
+ { Event::VALUE_CONSTRUCT, &e7, nullptr, 3 },
+ { Event::COPY_ASSIGN, v5, &e7, 3 },
+ { Event::DESTRUCT, &e7, nullptr, 3 },
+ { Event::DESTRUCT, v6, nullptr, 2 },
+ { Event::DESTRUCT, v5, nullptr, 3 },
{ Event::DESTRUCT, v3, nullptr, 5 },
{ Event::DESTRUCT, v2, nullptr, 4 },
};
diff --git a/Tests/CMakeLib/testRST.expect b/Tests/CMakeLib/testRST.expect
index 970adaa4e..4870f658a 100644
--- a/Tests/CMakeLib/testRST.expect
+++ b/Tests/CMakeLib/testRST.expect
@@ -20,6 +20,12 @@ Environment variable ``SOME_ENV_VAR``.
Environment variable ``some env var`` with space and target.
Generator ``Some Generator`` with space.
Generator ``Some Generator`` with space.
+Generator expression ``SOME_GENEX``.
+Generator expression ``$<SOME_GENEX>`` with brackets.
+Generator expression ``$<SOME_GENEX:...>`` with brackets and parameter.
+Generator expression ``some genex`` with space and target.
+Generator expression ``$<SOME_GENEX>`` with brackets, space, and target.
+Generator expression ``$<SOME_GENEX:...>`` with brackets, parameter, space, and target.
Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
Inline link Link Text.
Inline link Link Text <With \-escaped Brackets>.
@@ -48,6 +54,22 @@ Bracket Comment Content
Command other_cmd description.
+.. cmake:envvar:: some_var
+
+ Environment variable some_var description.
+
+.. envvar:: other_var
+
+ Environment variable other_var description.
+
+.. cmake:genex:: SOME_GENEX
+
+ Generator expression SOME_GENEX description.
+
+.. genex:: $<OTHER_GENEX>
+
+ Generator expression $<OTHER_GENEX> description.
+
.. cmake:variable:: some_var
Variable some_var description.
diff --git a/Tests/CMakeLib/testRST.rst b/Tests/CMakeLib/testRST.rst
index 6462f1b7f..44931a756 100644
--- a/Tests/CMakeLib/testRST.rst
+++ b/Tests/CMakeLib/testRST.rst
@@ -27,6 +27,12 @@ Environment variable :envvar:`SOME_ENV_VAR`.
Environment variable :envvar:`some env var <SOME_ENV_VAR>` with space and target.
Generator :generator:`Some Generator` with space.
Generator :cpack_gen:`Some Generator` with space.
+Generator expression :genex:`SOME_GENEX`.
+Generator expression :genex:`$<SOME_GENEX>` with brackets.
+Generator expression :genex:`$<SOME_GENEX:...>` with brackets and parameter.
+Generator expression :genex:`some genex <SOME_GENEX>` with space and target.
+Generator expression :genex:`$<SOME_GENEX> <SOME_GENEX>` with brackets, space, and target.
+Generator expression :genex:`$<SOME_GENEX:...> <SOME_GENEX>` with brackets, parameter, space, and target.
Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
Inline link `Link Text <ExternalDest>`_.
Inline link `Link Text \<With \\-escaped Brackets\> <ExternalDest>`_.
@@ -51,6 +57,22 @@ Inline literal ``__`` followed by inline link `Link Text <InternalDest_>`_.
Command other_cmd description.
+.. cmake:envvar:: some_var
+
+ Environment variable some_var description.
+
+.. envvar:: other_var
+
+ Environment variable other_var description.
+
+.. cmake:genex:: SOME_GENEX
+
+ Generator expression SOME_GENEX description.
+
+.. genex:: $<OTHER_GENEX>
+
+ Generator expression $<OTHER_GENEX> description.
+
.. cmake:variable:: some_var
Variable some_var description.
diff --git a/Tests/CMakeLib/testUVProcessChain.cxx b/Tests/CMakeLib/testUVProcessChain.cxx
index 61a77cf7b..a003205c2 100644
--- a/Tests/CMakeLib/testUVProcessChain.cxx
+++ b/Tests/CMakeLib/testUVProcessChain.cxx
@@ -181,6 +181,10 @@ bool checkOutput(std::istream& outputStream, std::istream& errorStream)
}
std::string error = getInput(errorStream);
+ auto qemu_error_pos = error.find("qemu:");
+ if (qemu_error_pos != std::string::npos) {
+ error.resize(qemu_error_pos);
+ }
if (error.length() != 3 || error.find('1') == std::string::npos ||
error.find('2') == std::string::npos ||
error.find('3') == std::string::npos) {
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 1fb47cb01..8e7c04fbd 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -256,8 +256,6 @@ if(BUILD_TESTING)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
add_subdirectory(CMakeLib)
-
- add_subdirectory(CMakeServerLib)
endif()
add_subdirectory(CMakeOnly)
add_subdirectory(RunCMake)
@@ -431,6 +429,10 @@ if(BUILD_TESTING)
set(CMAKE_SKIP_VSGNUFortran TRUE)
endif()
endif()
+ if(CMAKE_Fortran_COMPILER_ID STREQUAL IntelLLVM)
+ message(STATUS "Skip VSGNUFortran for ifx until DLLEXPORT support is implemented")
+ set(CMAKE_SKIP_VSGNUFortran TRUE)
+ endif()
if((CMAKE_C_COMPILER MATCHES lsb)
AND (CMAKE_Fortran_COMPILER MATCHES ifort))
message(STATUS "Skip VSGNUFortran for ifort and lsb compilers")
@@ -1155,6 +1157,26 @@ if(BUILD_TESTING)
"components-depend1"
"components-depend2"
"compression")
+ # Run additional tests if dpkg-shlibdeps is available (and is new enough version)
+ find_program(SHLIBDEPS_EXECUTABLE NAMES dpkg-shlibdeps)
+ if(SHLIBDEPS_EXECUTABLE)
+ # Check version of the dpkg-shlibdeps tool
+ execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --version
+ OUTPUT_VARIABLE _TMP_VERSION
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(_TMP_VERSION MATCHES "dpkg-shlibdeps version ([0-9]+\\.[0-9]+\\.[0-9]+)")
+ set(SHLIBDEPS_EXECUTABLE_VERSION "${CMAKE_MATCH_1}")
+ else()
+ unset(SHLIBDEPS_EXECUTABLE_VERSION)
+ endif()
+ if(NOT SHLIBDEPS_EXECUTABLE_VERSION VERSION_LESS 1.19 OR
+ (NOT SHLIBDEPS_EXECUTABLE_VERSION VERSION_LESS 1.17 AND NOT CMAKE_BINARY_DIR MATCHES ".*[ ].*"))
+ list(APPEND DEB_CONFIGURATIONS_TO_TEST "shlibdeps-with-private-lib-failure"
+ "shlibdeps-with-private-lib-success")
+ endif()
+ endif()
+
set(CPackGen "DEB")
set(CPackRun_CPackGen "-DCPackGen=${CPackGen}")
@@ -1281,21 +1303,6 @@ if(BUILD_TESTING)
set_property(TEST CMakeTestAllGenerators PROPERTY RUN_SERIAL 1)
endif()
- if(NOT DEFINED CTEST_RUN_CMakeTestMultipleConfigures)
- set(CTEST_RUN_CMakeTestMultipleConfigures ON)
- endif()
-
- if(CTEST_RUN_CMakeTestMultipleConfigures)
- add_test(CMakeTestMultipleConfigures ${CMAKE_CMAKE_COMMAND}
- -D dir=${CMake_BINARY_DIR}/Tests/CMakeTestMultipleConfigures
- -D gen=${CMAKE_GENERATOR}
- -D CMake_SOURCE_DIR=${CMake_SOURCE_DIR}
- -P ${CMake_SOURCE_DIR}/Tests/CMakeTestMultipleConfigures/RunCMake.cmake
- )
- list(APPEND TEST_BUILD_DIRS
- "${CMake_BINARY_DIR}/Tests/CMakeTestMultipleConfigures")
- endif()
-
if(NOT CMake_TEST_EXTERNAL_CMAKE)
add_test(LoadedCommandOneConfig ${CMAKE_CTEST_COMMAND}
--build-and-test
@@ -1427,6 +1434,7 @@ if(BUILD_TESTING)
GTK2
Iconv
ICU
+ Intl
JPEG
JsonCpp
LAPACK
@@ -1944,7 +1952,7 @@ if(BUILD_TESTING)
if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" OR NOT "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
ADD_TEST_MACRO(ForceInclude foo)
endif()
- if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
ADD_TEST_MACRO(PrecompiledHeader foo)
endif()
set(MSVCRuntimeLibrary_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
@@ -2010,12 +2018,19 @@ if(BUILD_TESTING)
endif()
endif()
- # For the Watcom WMake generator, avoid the MFC test by default.
if(CTEST_RUN_MFC)
+ # For the Watcom WMake generator, avoid the MFC test by default.
if("${CMAKE_GENERATOR}" MATCHES "WMake")
message(STATUS
"using the Watcom WMake generator, avoiding MFC test")
set(CTEST_RUN_MFC OFF)
+ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "IntelLLVM")
+ # clang-cl cannot deal with implicit dependencies in UTF16 files
+ # (see #18311). IntelLLVM inherits this behavior from Clang.
+ # TODO: maybe clang should also skip the MFC test
+ message(STATUS
+ "using generator other than Visual Studio with clang-cl, avoiding MFC test")
+ set(CTEST_RUN_MFC OFF)
endif()
endif()
@@ -2926,13 +2941,6 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(CMakeCommands.link_directories)
ADD_TEST_MACRO(CMakeCommands.target_link_directories)
- # The cmake server-mode test requires python for a simple client.
- find_package(PythonInterp QUIET)
- if(PYTHON_EXECUTABLE)
- set(Server_BUILD_OPTIONS -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE})
- ADD_TEST_MACRO(Server Server)
- endif()
-
configure_file(
"${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"
"${CMake_BINARY_DIR}/Tests/CTestTestCrash/test.cmake"
@@ -2947,7 +2955,7 @@ if(BUILD_TESTING)
PASS_REGULAR_EXPRESSION "Failed")
else()
set_tests_properties(CTestTestCrash PROPERTIES
- PASS_REGULAR_EXPRESSION "(Illegal|SegFault|Subprocess aborted)")
+ PASS_REGULAR_EXPRESSION "(Illegal|SegFault|Subprocess aborted|SIGTRAP)")
endif()
configure_file(
@@ -3402,6 +3410,9 @@ if(BUILD_TESTING)
${build_generator_args}
--build-project helloJavaNativeHeaders
--build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/"
+ --build-target install
+ --build-options
+ "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/Install"
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders")
endif()
diff --git a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
index 1f9d3acb7..7ca68ecf4 100644
--- a/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckCXXCompilerFlag/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CheckCXXCompilerFlag)
message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
diff --git a/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt b/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt
index 859ec4172..4cbccd398 100644
--- a/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CheckStructHasMember)
diff --git a/Tests/CMakeOnly/MajorVersionSelection/CMakeLists.txt b/Tests/CMakeOnly/MajorVersionSelection/CMakeLists.txt
index 2511064a2..9f30c7dd5 100644
--- a/Tests/CMakeOnly/MajorVersionSelection/CMakeLists.txt
+++ b/Tests/CMakeOnly/MajorVersionSelection/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
if (NOT MAJOR_TEST_MODULE OR NOT MAJOR_TEST_VERSION)
message(FATAL_ERROR "test selection variables not set up")
diff --git a/Tests/CMakeOnly/find_library/CMakeLists.txt b/Tests/CMakeOnly/find_library/CMakeLists.txt
index fe3815edd..b23d5e2ea 100644
--- a/Tests/CMakeOnly/find_library/CMakeLists.txt
+++ b/Tests/CMakeOnly/find_library/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(FindLibraryTest NONE)
set(CMAKE_FIND_DEBUG_MODE 1)
diff --git a/Tests/CMakeOnly/find_path/CMakeLists.txt b/Tests/CMakeOnly/find_path/CMakeLists.txt
index 0e64ed467..bf4e350c7 100644
--- a/Tests/CMakeOnly/find_path/CMakeLists.txt
+++ b/Tests/CMakeOnly/find_path/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(FindPathTest NONE)
set(CMAKE_FIND_DEBUG_MODE 1)
diff --git a/Tests/CMakeServerLib/CMakeLists.txt b/Tests/CMakeServerLib/CMakeLists.txt
deleted file mode 100644
index 2c23c2dbe..000000000
--- a/Tests/CMakeServerLib/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-include_directories(
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMake_BINARY_DIR}/Source
- ${CMake_SOURCE_DIR}/Source
- )
-
-set(CMakeServerLib_TESTS
- testServerBuffering.cpp
- )
-
-create_test_sourcelist(CMakeLib_TEST_SRCS CMakeServerLibTests.cxx ${CMakeServerLib_TESTS})
-add_executable(CMakeServerLibTests ${CMakeLib_TEST_SRCS})
-target_link_libraries(CMakeServerLibTests CMakeLib CMakeServerLib)
-
-SET_PROPERTY(TARGET CMakeServerLibTests PROPERTY C_CLANG_TIDY "")
-SET_PROPERTY(TARGET CMakeServerLibTests PROPERTY CXX_CLANG_TIDY "")
-
-foreach(testfile ${CMakeServerLib_TESTS})
- get_filename_component(test "${testfile}" NAME_WE)
- add_test(CMakeServerLib.${test} CMakeServerLibTests ${test} ${${test}_ARGS})
-endforeach()
diff --git a/Tests/CMakeServerLib/testServerBuffering.cpp b/Tests/CMakeServerLib/testServerBuffering.cpp
deleted file mode 100644
index 6f2294067..000000000
--- a/Tests/CMakeServerLib/testServerBuffering.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include <iostream>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "cmConnection.h"
-#include "cmServerConnection.h"
-
-void print_error(const std::vector<std::string>& input,
- const std::vector<std::string>& output)
-{
- std::cerr << "Responses don't equal input messages input." << std::endl;
- std::cerr << "Responses: " << std::endl;
-
- for (auto& msg : output) {
- std::cerr << "'" << msg << "'" << std::endl;
- }
-
- std::cerr << "Input messages" << std::endl;
- for (auto& msg : input) {
- std::cerr << "'" << msg << "'" << std::endl;
- }
-}
-
-std::string trim_newline(const std::string& _buffer)
-{
- auto buffer = _buffer;
- while (!buffer.empty() && (buffer.back() == '\n' || buffer.back() == '\r')) {
- buffer.pop_back();
- }
- return buffer;
-}
-
-int testServerBuffering(int, char** const)
-{
- std::vector<std::string> messages = {
- "{ \"test\": 10}", "{ \"test\": { \"test2\": false} }",
- "{ \"test\": [1, 2, 3] }",
- "{ \"a\": { \"1\": {}, \n\n\n \"2\":[] \t\t\t\t}}"
- };
-
- std::string fullMessage;
- for (auto& msg : messages) {
- fullMessage += "[== \"CMake Server\" ==[\n";
- fullMessage += msg;
- fullMessage += "\n]== \"CMake Server\" ==]\n";
- }
-
- // The buffering strategy should cope with any fragmentation, including
- // just getting the characters one at a time.
- auto bufferingStrategy =
- std::unique_ptr<cmConnectionBufferStrategy>(new cmServerBufferStrategy);
- std::vector<std::string> response;
- std::string rawBuffer;
- for (auto& messageChar : fullMessage) {
- rawBuffer += messageChar;
- std::string packet = bufferingStrategy->BufferMessage(rawBuffer);
- do {
- if (!packet.empty() && packet != "\r\n") {
- response.push_back(trim_newline(packet));
- }
- packet = bufferingStrategy->BufferMessage(rawBuffer);
- } while (!packet.empty());
- }
-
- if (response != messages) {
- print_error(messages, response);
- return 1;
- }
-
- // We should also be able to deal with getting a bunch at once
- response.clear();
- std::string packet = bufferingStrategy->BufferMessage(fullMessage);
- do {
- if (!packet.empty() && packet != "\r\n") {
- response.push_back(trim_newline(packet));
- }
- packet = bufferingStrategy->BufferMessage(fullMessage);
- } while (!packet.empty());
-
- if (response != messages) {
- print_error(messages, response);
- return 1;
- }
-
- return 0;
-}
diff --git a/Tests/CMakeTestMultipleConfigures/RunCMake.cmake b/Tests/CMakeTestMultipleConfigures/RunCMake.cmake
deleted file mode 100644
index a79bfcbff..000000000
--- a/Tests/CMakeTestMultipleConfigures/RunCMake.cmake
+++ /dev/null
@@ -1,165 +0,0 @@
-if(NOT DEFINED CMake_SOURCE_DIR)
- message(FATAL_ERROR "CMake_SOURCE_DIR not defined")
-endif()
-
-if(NOT DEFINED dir)
- message(FATAL_ERROR "dir not defined")
-endif()
-
-if(NOT DEFINED gen)
- message(FATAL_ERROR "gen not defined")
-endif()
-
-# Call cmake once to get a baseline/reference output build tree: "Build".
-# Then call cmake N more times, each time making a copy of the entire
-# build tree after cmake is done configuring/generating. At the end,
-# analyze the diffs in the generated build trees. Expect no diffs.
-#
-message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
-
-set(N 7)
-
-# First setup source and binary trees:
-#
-execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf
- ${dir}/Source
-)
-
-execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf
- ${dir}/Build
-)
-
-execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory
- ${CMake_SOURCE_DIR}/Tests/CTestTest/SmallAndFast
- ${dir}/Source
-)
-
-execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory
- ${dir}/Build
-)
-
-# Patch SmallAndFast to build a .cxx executable too:
-#
-execute_process(COMMAND ${CMAKE_COMMAND} -E copy
- ${dir}/Source/echoargs.c
- ${dir}/Source/echoargs.cxx
-)
-file(APPEND "${dir}/Source/CMakeLists.txt" "\nadd_executable(echoargsCXX echoargs.cxx)\n")
-
-# Loop N times, saving a copy of the configured/generated build tree each time:
-#
-foreach(i RANGE 1 ${N})
- # Equivalent sequence of shell commands:
- #
- message(STATUS "${i}: cd Build && cmake -G \"${gen}\" ../Source && cd .. && cp -r Build b${i}")
-
- # Run cmake:
- #
- execute_process(COMMAND ${CMAKE_COMMAND} -G ${gen} ../Source
- RESULT_VARIABLE result
- OUTPUT_VARIABLE stdout
- ERROR_VARIABLE stderr
- WORKING_DIRECTORY ${dir}/Build
- )
-
- message(STATUS "result='${result}'")
- message(STATUS "stdout='${stdout}'")
- message(STATUS "stderr='${stderr}'")
- message(STATUS "")
-
- # Save this iteration of the Build directory:
- #
- execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf
- ${dir}/b${i}
- )
- execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory
- ${dir}/Build
- ${dir}/b${i}
- RESULT_VARIABLE result
- OUTPUT_VARIABLE stdout
- ERROR_VARIABLE stderr
- )
-
- message(STATUS "result='${result}'")
- message(STATUS "stdout='${stdout}'")
- message(STATUS "stderr='${stderr}'")
- message(STATUS "")
-endforeach()
-
-
-# Function to analyze diffs between two directories.
-# Set DIFF_EXECUTABLE before calling if 'diff' is available.
-#
-function(analyze_directory_diffs d1 d2 diff_count_var)
- set(diffs 0)
-
- message(STATUS "Analyzing directory diffs between:")
- message(STATUS " d1='${d1}'")
- message(STATUS " d2='${d2}'")
-
- if(NOT "${d1}" STREQUAL "" AND NOT "${d2}" STREQUAL "")
- message(STATUS "info: analyzing directories")
-
- file(GLOB_RECURSE files1 RELATIVE "${d1}" "${d1}/*")
- file(GLOB_RECURSE files2 RELATIVE "${d2}" "${d2}/*")
-
- if("${files1}" STREQUAL "${files2}")
- message(STATUS "info: file lists the same")
- #message(STATUS " files='${files1}'")
-
- foreach(f ${files1})
- execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files
- ${d1}/${f}
- ${d2}/${f}
- RESULT_VARIABLE result
- OUTPUT_VARIABLE stdout
- ERROR_VARIABLE stderr
- )
- if(result STREQUAL 0)
- #message(STATUS "info: file '${f}' the same")
- else()
- math(EXPR diffs "${diffs} + 1")
- message(STATUS "warning: file '${f}' differs from d1 to d2")
- file(READ "${d1}/${f}" f1contents)
- message(STATUS "contents of file '${d1}/${f}'
-[===[${f1contents}]===]")
- file(READ "${d2}/${f}" f2contents)
- message(STATUS "contents of file '${d2}/${f}'
-[===[${f2contents}]===]")
- if(DIFF_EXECUTABLE)
- message(STATUS "diff of files '${d1}/${f}' '${d2}/${f}'")
- message(STATUS "[====[")
- execute_process(COMMAND ${DIFF_EXECUTABLE} "${d1}/${f}" "${d2}/${f}")
- message(STATUS "]====]")
- endif()
- endif()
- endforeach()
- else()
- math(EXPR diffs "${diffs} + 1")
- message(STATUS "warning: file *lists* differ - some files exist in d1/not-d2 or not-d1/d2...")
- message(STATUS " files1='${files1}'")
- message(STATUS " files2='${files2}'")
- endif()
- endif()
-
- set(${diff_count_var} ${diffs} PARENT_SCOPE)
-endfunction()
-
-
-# Analyze diffs between b1:b2, b2:b3, b3:b4, b4:b5 ... bN-1:bN.
-# Expect no diffs.
-#
-find_program(DIFF_EXECUTABLE diff)
-set(total_diffs 0)
-
-foreach(i RANGE 2 ${N})
- math(EXPR prev "${i} - 1")
- set(count 0)
- analyze_directory_diffs(${dir}/b${prev} ${dir}/b${i} count)
- message(STATUS "diff count='${count}'")
- message(STATUS "")
- math(EXPR total_diffs "${total_diffs} + ${count}")
-endforeach()
-
-message(STATUS "CMAKE_COMMAND='${CMAKE_COMMAND}'")
-message(STATUS "total_diffs='${total_diffs}'")
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index 348e6d05d..6bbbe7d35 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -44,10 +44,6 @@ set_property(TEST CMake.FileDownloadBadHash PROPERTY
AddCMakeTest(FileUpload "")
-if(HAVE_ELF_H)
- AddCMakeTest(ELF "")
-endif()
-
set(EndStuff_PreArgs
"-Ddir:STRING=${CMAKE_CURRENT_BINARY_DIR}/EndStuffTest"
)
diff --git a/Tests/CMakeTests/EndStuffTestScript.cmake b/Tests/CMakeTests/EndStuffTestScript.cmake
index 9f4081801..e0d826d79 100644
--- a/Tests/CMakeTests/EndStuffTestScript.cmake
+++ b/Tests/CMakeTests/EndStuffTestScript.cmake
@@ -1,68 +1,40 @@
message(STATUS "testname='${testname}'")
-if(testname STREQUAL bad_else) # fail
- file(WRITE "${dir}/${testname}.cmake"
-"else()
-")
+function(do_end content)
+ file(WRITE "${dir}/${testname}.cmake" "${content}")
execute_process(COMMAND ${CMAKE_COMMAND} -P "${dir}/${testname}.cmake"
RESULT_VARIABLE rv)
if(NOT rv EQUAL 0)
message(FATAL_ERROR "${testname} failed")
endif()
+endfunction()
+
+if(testname STREQUAL bad_else) # fail
+ do_end("else()\n")
elseif(testname STREQUAL bad_elseif) # fail
- file(WRITE "${dir}/${testname}.cmake"
-"elseif()
-")
- execute_process(COMMAND ${CMAKE_COMMAND} -P "${dir}/${testname}.cmake"
- RESULT_VARIABLE rv)
- if(NOT rv EQUAL 0)
- message(FATAL_ERROR "${testname} failed")
- endif()
+ do_end("elseif()\n")
elseif(testname STREQUAL bad_endforeach) # fail
- endforeach()
+ do_end("endforeach()\n")
elseif(testname STREQUAL bad_endfunction) # fail
- endfunction()
+ do_end("endfunction()\n")
elseif(testname STREQUAL bad_endif) # fail
- file(WRITE "${dir}/${testname}.cmake"
-"cmake_minimum_required(VERSION 2.8)
-endif()
-")
- execute_process(COMMAND ${CMAKE_COMMAND} -P "${dir}/${testname}.cmake"
- RESULT_VARIABLE rv)
- if(NOT rv EQUAL 0)
- message(FATAL_ERROR "${testname} failed")
- endif()
+ do_end("cmake_minimum_required(VERSION 2.8.12)\nendif()\n")
-elseif(testname STREQUAL endif_low_min_version) # pass
- file(WRITE "${dir}/${testname}.cmake"
-"cmake_minimum_required(VERSION 1.2)
-endif()
-")
- execute_process(COMMAND ${CMAKE_COMMAND} -P "${dir}/${testname}.cmake"
- RESULT_VARIABLE rv)
- if(NOT rv EQUAL 0)
- message(FATAL_ERROR "${testname} failed")
- endif()
+elseif(testname STREQUAL endif_low_min_version) # fail
+ do_end("cmake_minimum_required(VERSION 1.2)\nendif()\n")
-elseif(testname STREQUAL endif_no_min_version) # pass
- file(WRITE "${dir}/${testname}.cmake"
-"endif()
-")
- execute_process(COMMAND ${CMAKE_COMMAND} -P "${dir}/${testname}.cmake"
- RESULT_VARIABLE rv)
- if(NOT rv EQUAL 0)
- message(FATAL_ERROR "${testname} failed")
- endif()
+elseif(testname STREQUAL endif_no_min_version) # fail
+ do_end("endif()\n")
elseif(testname STREQUAL bad_endmacro) # fail
- endmacro()
+ do_end("endmacro()\n")
elseif(testname STREQUAL bad_endwhile) # fail
- endwhile()
+ do_end("endwhile()\n")
else() # fail
message(FATAL_ERROR "testname='${testname}' - error: no such test in '${CMAKE_CURRENT_LIST_FILE}'")
diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in
index 69d9a14c4..e0ce99ab8 100644
--- a/Tests/CMakeTests/FileDownloadTest.cmake.in
+++ b/Tests/CMakeTests/FileDownloadTest.cmake.in
@@ -136,6 +136,9 @@ __reportIfWrongStatus("${status}" 0)
# Print status because we check its message too
message(STATUS "${status}")
+# do not use proxy for lookup of invalid site (DNS failure by proxy looks
+# different than DNS failure without proxy)
+set(ENV{no_proxy} "$ENV{no_proxy},badhostname.invalid")
message(STATUS "FileDownload:11")
file(DOWNLOAD
badhostname.invalid
diff --git a/Tests/CMakeTests/ListTest.cmake.in b/Tests/CMakeTests/ListTest.cmake.in
index 785f41da1..76737e578 100644
--- a/Tests/CMakeTests/ListTest.cmake.in
+++ b/Tests/CMakeTests/ListTest.cmake.in
@@ -142,9 +142,8 @@ set(Find-List-Only-STDERR "three")
set(Insert-List-Only-STDERR "at least three")
set(Length-List-Only-STDERR "two")
set(Remove_At-List-Only-STDERR "at least two")
-set(Remove_Item-List-Only-STDERR "two or more")
-foreach(cmd IN ITEMS Find Get Insert Length Remove_At Remove_Item)
+foreach(cmd IN ITEMS Find Get Insert Length Remove_At)
string(TOUPPER ${cmd} cmd_upper)
set(${cmd}-List-Only-RESULT 1)
set(${cmd}-List-Only-STDERR ".*CMake Error at List-${cmd}-List-Only.cmake:1 \\(list\\):.*list sub-command ${cmd_upper} requires ${${cmd}-List-Only-STDERR} arguments.*")
diff --git a/Tests/CPackComponentsDEB/CMakeLists.txt b/Tests/CPackComponentsDEB/CMakeLists.txt
index 4363f1b40..b2e2106a3 100644
--- a/Tests/CPackComponentsDEB/CMakeLists.txt
+++ b/Tests/CPackComponentsDEB/CMakeLists.txt
@@ -22,6 +22,13 @@ target_link_libraries(mylibapp mylib)
add_executable(mylibapp2 mylibapp.cpp)
target_link_libraries(mylibapp2 mylib)
+if (CPackDEBConfiguration MATCHES "shlibdeps-with-private-lib")
+ add_subdirectory("shlibdeps-with-private-lib")
+ add_executable(mylibapp3 mylibapp.cpp)
+ target_compile_definitions(mylibapp3 PRIVATE -DSHLIBDEPS_PRIVATE)
+ target_link_libraries(mylibapp3 myprivatelib)
+endif()
+
# Create installation targets. Note that we put each kind of file
# into a different component via COMPONENT. These components will
# be used to create the installation components.
@@ -39,6 +46,13 @@ install(FILES mylib.h
DESTINATION include
COMPONENT headers)
+if (CPackDEBConfiguration MATCHES "shlibdeps-with-private-lib")
+ install(TARGETS mylibapp3
+ RUNTIME
+ DESTINATION bin
+ COMPONENT applications)
+endif()
+
# CPack boilerplate for this project
set(CPACK_PACKAGE_NAME "MyLib")
set(CPACK_PACKAGE_CONTACT "None")
diff --git a/Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-failure.cmake.in b/Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-failure.cmake.in
new file mode 100644
index 000000000..cfe6df529
--- /dev/null
+++ b/Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-failure.cmake.in
@@ -0,0 +1,24 @@
+#
+# Activate component packaging
+#
+
+if(CPACK_GENERATOR MATCHES "DEB")
+ set(CPACK_DEB_COMPONENT_INSTALL "ON")
+endif()
+
+#
+# Choose grouping way
+#
+#set(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE)
+#set(CPACK_COMPONENTS_GROUPING)
+set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
+#set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
+
+# we set shlibdeps to on
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+# except for the component "headers" that do not contain any binary.
+# the packaging will just fail if this does not work
+set(CPACK_DEBIAN_HEADERS_PACKAGE_SHLIBDEPS OFF)
+
+# Also libraries contains only a static library.
+set(CPACK_DEBIAN_LIBRARIES_PACKAGE_SHLIBDEPS OFF)
diff --git a/Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-success.cmake.in b/Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-success.cmake.in
new file mode 100644
index 000000000..76aadc962
--- /dev/null
+++ b/Tests/CPackComponentsDEB/MyLibCPackConfig-shlibdeps-with-private-lib-success.cmake.in
@@ -0,0 +1,33 @@
+#
+# Activate component packaging
+#
+
+if(CPACK_GENERATOR MATCHES "DEB")
+ set(CPACK_DEB_COMPONENT_INSTALL "ON")
+endif()
+
+#
+# Choose grouping way
+#
+#set(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE)
+#set(CPACK_COMPONENTS_GROUPING)
+set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
+#set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
+
+# we set shlibdeps to on
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+# except for the component "headers" that do not contain any binary.
+# the packaging will just fail if this does not work
+set(CPACK_DEBIAN_HEADERS_PACKAGE_SHLIBDEPS OFF)
+
+# Also libraries contains only a static library.
+set(CPACK_DEBIAN_LIBRARIES_PACKAGE_SHLIBDEPS OFF)
+
+# Most importantly, we also give a list of additional search directories
+# to allow `dpkg-shlibdeps` to find the private dependency.
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS
+ "${CPACK_PACKAGE_DIRECTORY}/shlibdeps-with-private-lib"
+ "${CPACK_PACKAGE_DIRECTORY}/shlibdeps-with-private-lib/Debug"
+ "${CPACK_PACKAGE_DIRECTORY}/shlibdeps-with-private-lib/Release"
+ "${CPACK_PACKAGE_DIRECTORY}/shlibdeps-with-private-lib/RelWithDebInfo"
+ "${CPACK_PACKAGE_DIRECTORY}/shlibdeps-with-private-lib/MinSizeRel")
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-failure.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-failure.cmake
new file mode 100644
index 000000000..962a1fb48
--- /dev/null
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-failure.cmake
@@ -0,0 +1,19 @@
+if(NOT CPackComponentsDEB_SOURCE_DIR)
+ message(FATAL_ERROR "CPackComponentsDEB_SOURCE_DIR not set")
+endif()
+
+include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake)
+
+
+set(actual_output)
+run_cpack(actual_output
+ CPack_output
+ CPack_error
+ EXPECT_FAILURE
+ CONFIG_ARGS ${config_args}
+ CONFIG_VERBOSE ${config_verbose})
+
+string(REGEX MATCH "dpkg-shlibdeps: error: (cannot|couldn't) find[ \n\t]+library[ \n\t]+libmyprivatelib.so.1[ \n\t]+needed[ \n\t]+by[ \n\t]+./usr/bin/mylibapp3" expected_error ${CPack_error})
+if(NOT expected_error)
+ message(FATAL_ERROR "Did not get the expected error-message!")
+endif()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-success.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-success.cmake
new file mode 100644
index 000000000..6eff3dbff
--- /dev/null
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-shlibdeps-with-private-lib-success.cmake
@@ -0,0 +1,75 @@
+if(NOT CPackComponentsDEB_SOURCE_DIR)
+ message(FATAL_ERROR "CPackComponentsDEB_SOURCE_DIR not set")
+endif()
+
+include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake)
+
+
+
+# requirements
+
+# debian now produces lower case names
+set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb")
+set(expected_count 3)
+
+
+set(actual_output)
+run_cpack(actual_output
+ CPack_output
+ CPack_error
+ EXPECTED_FILE_MASK "${expected_file_mask}"
+ CONFIG_ARGS ${config_args}
+ CONFIG_VERBOSE ${config_verbose})
+
+message(STATUS "expected_count='${expected_count}'")
+message(STATUS "expected_file_mask='${expected_file_mask}'")
+message(STATUS "actual_output_files='${actual_output}'")
+
+if(NOT actual_output)
+ message(FATAL_ERROR "error: expected_files do not exist: CPackComponentsDEB test fails. (CPack_output=${CPack_output}, CPack_error=${CPack_error}")
+endif()
+
+list(LENGTH actual_output 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})")
+endif()
+
+
+# dpkg-deb checks for the summary of the packages
+find_program(DPKGDEB_EXECUTABLE dpkg-deb)
+if(DPKGDEB_EXECUTABLE)
+ set(dpkgdeb_output_errors_all "")
+ foreach(_f IN LISTS actual_output)
+
+ # extracts the metadata from the package
+ run_dpkgdeb(dpkg_output
+ FILENAME ${_f}
+ )
+
+ dpkgdeb_return_specific_metaentry(dpkg_package_name
+ DPKGDEB_OUTPUT "${dpkg_output}"
+ METAENTRY "Package:")
+
+ message(STATUS "package='${dpkg_package_name}'")
+
+ if(dpkg_package_name STREQUAL "mylib-applications")
+ # pass
+ elseif(dpkg_package_name STREQUAL "mylib-headers")
+ # pass
+ elseif(dpkg_package_name STREQUAL "mylib-libraries")
+ # pass
+ else()
+ set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
+ "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n")
+ endif()
+
+ endforeach()
+
+
+ if(NOT dpkgdeb_output_errors_all STREQUAL "")
+ message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}")
+ endif()
+else()
+ message("dpkg-deb executable not found - skipping dpkg-deb test")
+endif()
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
index 3bc8d2a32..8f7c19810 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
@@ -29,7 +29,7 @@ endif()
# run cpack with some options and returns the list of files generated
# -output_expected_file: list of files that match the pattern
function(run_cpack output_expected_file CPack_output_parent CPack_error_parent)
- set(options )
+ set(options "EXPECT_FAILURE")
set(oneValueArgs "EXPECTED_FILE_MASK" "CONFIG_VERBOSE")
set(multiValueArgs "CONFIG_ARGS")
cmake_parse_arguments(run_cpack_deb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
@@ -45,17 +45,26 @@ function(run_cpack output_expected_file CPack_output_parent CPack_error_parent)
message("config_args = ${run_cpack_deb_CONFIG_ARGS}")
message("config_verbose = ${run_cpack_deb_CONFIG_VERBOSE}")
+
+ set(_backup_lang "$ENV{LANG}")
+ set(_backup_lc_all "$ENV{LC_ALL}")
+ set(ENV{LANG} "C")
+ set(ENV{LC_ALL} "C")
execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${run_cpack_deb_CONFIG_VERBOSE} -G ${CPackGen} -C "${CONFIG}" ${run_cpack_deb_CONFIG_ARGS}
RESULT_VARIABLE CPack_result
OUTPUT_VARIABLE CPack_output
ERROR_VARIABLE CPack_error
WORKING_DIRECTORY ${CPackComponentsDEB_BINARY_DIR})
+ set(ENV{LANG} "${_backup_lang}")
+ set(ENV{LC_ALL} "${_backup_lc_all}")
set(${CPack_output_parent} ${CPack_output} PARENT_SCOPE)
set(${CPack_error_parent} ${CPack_error} PARENT_SCOPE)
- if (CPack_result)
+ if (CPack_result AND NOT run_cpack_deb_EXPECT_FAILURE)
message(FATAL_ERROR "error: CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}")
+ elseif (NOT CPack_result AND run_cpack_deb_EXPECT_FAILURE)
+ message(FATAL_ERROR "error: CPack execution succeeded although failure was expected!, CPack_output=${CPack_output}, CPack_error=${CPack_error}")
else ()
message(STATUS "CPack_output=${CPack_output}")
message(STATUS "CPack_error=${CPack_error}")
diff --git a/Tests/CPackComponentsDEB/mylibapp.cpp b/Tests/CPackComponentsDEB/mylibapp.cpp
index a438ac77f..bb45831a8 100644
--- a/Tests/CPackComponentsDEB/mylibapp.cpp
+++ b/Tests/CPackComponentsDEB/mylibapp.cpp
@@ -1,6 +1,19 @@
-#include "mylib.h"
+#ifndef SHLIBDEPS_PRIVATE
+
+# include "mylib.h"
int main()
{
mylib_function();
}
+
+#else
+
+# include "shlibdeps-with-private-lib/myprivatelib.h"
+
+int main()
+{
+ myprivatelib_function();
+}
+
+#endif
diff --git a/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/CMakeLists.txt b/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/CMakeLists.txt
new file mode 100644
index 000000000..c7ef38660
--- /dev/null
+++ b/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_library(myprivatelib SHARED myprivatelib.cpp)
+set_target_properties( myprivatelib PROPERTIES
+ VERSION 1.2.3
+ SOVERSION 1
+)
diff --git a/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.cpp b/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.cpp
new file mode 100644
index 000000000..67110e68e
--- /dev/null
+++ b/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.cpp
@@ -0,0 +1,8 @@
+#include "myprivatelib.h"
+
+#include "stdio.h"
+
+void myprivatelib_function()
+{
+ printf("This is myprivatelib");
+}
diff --git a/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.h b/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.h
new file mode 100644
index 000000000..7e4a42d15
--- /dev/null
+++ b/Tests/CPackComponentsDEB/shlibdeps-with-private-lib/myprivatelib.h
@@ -0,0 +1 @@
+void myprivatelib_function();
diff --git a/Tests/CPackNSISGenerator/CMakeLists.txt b/Tests/CPackNSISGenerator/CMakeLists.txt
index 8ed4d59cc..64a8ef6a5 100644
--- a/Tests/CPackNSISGenerator/CMakeLists.txt
+++ b/Tests/CPackNSISGenerator/CMakeLists.txt
@@ -17,5 +17,7 @@ set(CPACK_NSIS_MUI_UNIICON "${PROJECT_SOURCE_DIR}\\\\uninstall.ico")
set(CPACK_GENERATOR "NSIS")
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set(CPACK_NSIS_MANIFEST_DPI_AWARE ON)
+set(CPACK_NSIS_BRANDING_TEXT "CMake branding text")
+set(CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION "RIGHT")
include(CPack)
diff --git a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
index bfbcf9cba..8bfcf26f5 100644
--- a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
+++ b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
@@ -52,3 +52,11 @@ if("${output_index}" EQUAL "-1")
else()
message(STATUS "Found DPI-aware")
endif()
+
+file(STRINGS "${project_file}" line REGEX "^BrandingText /TRIMRIGHT \"CMake branding text\"")
+string(FIND "${line}" "TRIMRIGHT" output_index)
+if("${output_index}" EQUAL "-1")
+ message(FATAL_ERROR "BrandingText not found in the project")
+else()
+ message(STATUS "Found BrandingText")
+endif()
diff --git a/Tests/CPackTestAllGenerators/CMakeLists.txt b/Tests/CPackTestAllGenerators/CMakeLists.txt
index 5eeb7e90b..95daabff0 100644
--- a/Tests/CPackTestAllGenerators/CMakeLists.txt
+++ b/Tests/CPackTestAllGenerators/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CPackTestAllGenerators)
add_subdirectory(../CTestTest/SmallAndFast SmallAndFast)
install(FILES RunCPack.cmake DESTINATION .)
diff --git a/Tests/CPackWiXGenerator/CMakeLists.txt b/Tests/CPackWiXGenerator/CMakeLists.txt
index 940e849ff..2249d703a 100644
--- a/Tests/CPackWiXGenerator/CMakeLists.txt
+++ b/Tests/CPackWiXGenerator/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CPackWiXGenerator)
diff --git a/Tests/CTestCoverageCollectGCOV/test.cmake.in b/Tests/CTestCoverageCollectGCOV/test.cmake.in
index 181888875..a36f3743b 100644
--- a/Tests/CTestCoverageCollectGCOV/test.cmake.in
+++ b/Tests/CTestCoverageCollectGCOV/test.cmake.in
@@ -29,6 +29,20 @@ set(expected_out
uncovered/uncovered2.cpp
)
+# A symbolic link in the path can cause tar to put an equivalent, but not
+# minimal file name to some files in the tar file. Convert paths to absolute
+# then back to relative to get them in canonical form (or maybe this is a bug
+# in how the tarball is generated?)
+function(to_relative_paths real_paths paths)
+ foreach(file ${paths})
+ file(REAL_PATH "${file}" real_path BASE_DIRECTORY "${CTEST_BINARY_DIRECTORY}")
+ file(RELATIVE_PATH relative_path "${CTEST_BINARY_DIRECTORY}" "${real_path}")
+ list(APPEND local_real_paths "${relative_path}")
+ message(DEBUG "${file} -> ${real_path} -> ${relative_path}")
+ endforeach()
+ set("${real_paths}" "${local_real_paths}" PARENT_SCOPE)
+endfunction()
+
#------------------------------------------------------------------------------#
# Test 1: with standard arguments
#------------------------------------------------------------------------------#
@@ -50,6 +64,7 @@ execute_process(COMMAND
)
string(REPLACE "\n" ";" out "${out}")
+to_relative_paths(out "${out}")
list(SORT out)
if("${out}" STREQUAL "${expected_out}")
@@ -80,6 +95,7 @@ execute_process(COMMAND
)
string(REPLACE "\n" ";" out "${out}")
+to_relative_paths(out "${out}")
list(SORT out)
if("${out}" STREQUAL "${expected_out}")
@@ -110,6 +126,7 @@ execute_process(COMMAND
)
string(REPLACE "\n" ";" out "${out}")
+to_relative_paths(out "${out}")
list(SORT out)
if("${out}" STREQUAL "${expected_out}")
@@ -140,6 +157,7 @@ execute_process(COMMAND
)
string(REPLACE "\n" ";" out "${out}")
+to_relative_paths(out "${out}")
list(SORT out)
if("${out}" STREQUAL "${expected_out}")
@@ -170,6 +188,7 @@ execute_process(COMMAND
)
string(REPLACE "\n" ";" out "${out}")
+to_relative_paths(out "${out}")
list(SORT out)
if("${out}" STREQUAL "${expected_out}")
diff --git a/Tests/CTestLimitDashJ/CMakeLists.txt b/Tests/CTestLimitDashJ/CMakeLists.txt
index 5208d2d91..d04b3adf4 100644
--- a/Tests/CTestLimitDashJ/CMakeLists.txt
+++ b/Tests/CTestLimitDashJ/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CTestLimitDashJ NONE)
# This file demonstrates https://gitlab.kitware.com/cmake/cmake/-/issues/12904
diff --git a/Tests/CTestTest/SmallAndFast/CMakeLists.txt b/Tests/CTestTest/SmallAndFast/CMakeLists.txt
index 85cb30cef..06cbafde2 100644
--- a/Tests/CTestTest/SmallAndFast/CMakeLists.txt
+++ b/Tests/CTestTest/SmallAndFast/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(SmallAndFast)
include(CTest)
diff --git a/Tests/CTestUpdateCVS.cmake.in b/Tests/CTestUpdateCVS.cmake.in
index 5389bdf51..8e0b6110b 100644
--- a/Tests/CTestUpdateCVS.cmake.in
+++ b/Tests/CTestUpdateCVS.cmake.in
@@ -17,21 +17,11 @@ message("Using CVS tools:")
set(CVS "@CVS_EXECUTABLE@")
message(" cvs = ${CVS}")
-set(REPO ${TOP}/repo)
-
-# The MSYS cvs tool interprets "c:/" as a "machine:" name for SSH.
-# Detect the MSYS cvs and convert the repo path to an MSYS path.
-if(WIN32)
- if(EXISTS "${CVS}")
- file(STRINGS "${CVS}" cvs_is_msys LIMIT_COUNT 1 REGEX "[Mm][Ss][Yy][Ss]")
- if(cvs_is_msys)
- message(" '${CVS}' is from MSYS (contains '${cvs_is_msys}')")
- string(REGEX REPLACE "^([A-Za-z]):" "/\\1" REPO "${REPO}")
- endif()
- endif()
-endif()
+# Pre-pending :local: prevents cvs from trying to interpret Windows drive
+# letters, like "C:", as host names.
+set(REPO ":local:${TOP}/repo")
-set(CVSCMD ${CVS} -d${REPO})
+set(CVSCMD ${CVS} -d "${REPO}")
# CVSNT requires an extra option to 'cvs init'.
set(CVS_INIT_OPT)
diff --git a/Tests/CTestUpdateGIT.cmake.in b/Tests/CTestUpdateGIT.cmake.in
index 7d0fa0fab..a3ef4ebdb 100644
--- a/Tests/CTestUpdateGIT.cmake.in
+++ b/Tests/CTestUpdateGIT.cmake.in
@@ -32,6 +32,20 @@ if(UNIX)
set(GIT ${TOP}/git.sh)
endif()
+# Adapt to the system default branch name.
+execute_process(
+ COMMAND ${GIT} config --get init.defaultBranch
+ RESULT_VARIABLE defaultBranchFailed
+ OUTPUT_VARIABLE defaultBranch
+ ERROR_VARIABLE defaultBranchError
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_STRIP_TRAILING_WHITESPACE
+ )
+if(defaultBranch STREQUAL "")
+ set(defaultBranch master)
+endif()
+message("Detected default branch name '${defaultBranch}'")
+
#-----------------------------------------------------------------------------
# Create the repository.
message("Creating repository...")
@@ -64,7 +78,7 @@ run_child(WORKING_DIRECTORY ${TOP}/module
COMMAND ${GIT} commit -m "Initial content"
)
run_child(WORKING_DIRECTORY ${TOP}/module
- COMMAND ${GIT} push origin master:refs/heads/master
+ COMMAND ${GIT} push origin ${defaultBranch}:refs/heads/${defaultBranch}
)
#-----------------------------------------------------------------------------
@@ -80,7 +94,7 @@ file(APPEND ${TOP}/import/.git/config "
${AUTHOR_CONFIG}")
create_content(import)
file(WRITE ${TOP}/import/HEAD "HEAD\n")
-file(WRITE ${TOP}/import/master "master\n")
+file(WRITE ${TOP}/import/${defaultBranch} "${defaultBranch}\n")
run_child(WORKING_DIRECTORY ${TOP}/import
COMMAND ${GIT} add .
)
@@ -94,7 +108,7 @@ run_child(WORKING_DIRECTORY ${TOP}/import
COMMAND ${GIT} commit -m "Initial content"
)
run_child(WORKING_DIRECTORY ${TOP}/import
- COMMAND ${GIT} push origin master:refs/heads/master
+ COMMAND ${GIT} push origin ${defaultBranch}:refs/heads/${defaultBranch}
)
#-----------------------------------------------------------------------------
@@ -107,7 +121,7 @@ run_child(WORKING_DIRECTORY ${TOP}/module
COMMAND ${GIT} commit -m "Changed content"
)
run_child(WORKING_DIRECTORY ${TOP}/module
- COMMAND ${GIT} push origin master:refs/heads/master
+ COMMAND ${GIT} push origin ${defaultBranch}:refs/heads/${defaultBranch}
)
#-----------------------------------------------------------------------------
@@ -163,7 +177,7 @@ run_child(
COMMAND ${GIT} rm -- ${files_removed}
)
run_child(WORKING_DIRECTORY ${TOP}/user-source/module
- COMMAND ${GIT} checkout master --
+ COMMAND ${GIT} checkout ${defaultBranch} --
)
run_child(
WORKING_DIRECTORY ${TOP}/user-source
@@ -222,7 +236,7 @@ rewind_source(user-source)
# modified files) even if ~/.gitconfig sets "branch.master.rebase".
run_child(
WORKING_DIRECTORY ${TOP}/user-source
- COMMAND ${GIT} config branch.master.rebase false
+ COMMAND ${GIT} config branch.${defaultBranch}.rebase false
)
# Create a modified file.
@@ -254,7 +268,7 @@ create_build_tree(user-source user-binary-custom)
file(APPEND ${TOP}/user-binary-custom/CTestConfiguration.ini
"# GIT command configuration
UpdateCommand: ${GIT}
-GITUpdateCustom: ${GIT};pull;origin;master
+GITUpdateCustom: ${GIT};pull;origin;${defaultBranch}
")
# Run the dashboard command line interface.
@@ -304,7 +318,7 @@ create_dashboard_script(dash-binary-custom
"# git command configuration
set(CTEST_GIT_COMMAND \"${GIT}\")
set(CTEST_GIT_UPDATE_OPTIONS)
-set(CTEST_GIT_UPDATE_CUSTOM \${CTEST_GIT_COMMAND} pull origin master)
+set(CTEST_GIT_UPDATE_CUSTOM \${CTEST_GIT_COMMAND} pull origin ${defaultBranch})
")
# Run the dashboard script with CTest.
@@ -339,7 +353,7 @@ create_dashboard_script(dash-binary-quiet
"# git command configuration
set(CTEST_GIT_COMMAND \"${GIT}\")
set(CTEST_GIT_UPDATE_OPTIONS)
-set(CTEST_GIT_UPDATE_CUSTOM \${CTEST_GIT_COMMAND} pull origin master)
+set(CTEST_GIT_UPDATE_CUSTOM \${CTEST_GIT_COMMAND} pull origin ${defaultBranch})
")
unset(ctest_update_args)
diff --git a/Tests/CheckCompilerRelatedVariables/CMakeLists.txt b/Tests/CheckCompilerRelatedVariables/CMakeLists.txt
index 87b7f1acd..69fa4b610 100644
--- a/Tests/CheckCompilerRelatedVariables/CMakeLists.txt
+++ b/Tests/CheckCompilerRelatedVariables/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CheckCompilerRelatedVariables)
diff --git a/Tests/CompileDefinitions/CMakeLists.txt b/Tests/CompileDefinitions/CMakeLists.txt
index 1d8afbff3..8347d5a22 100644
--- a/Tests/CompileDefinitions/CMakeLists.txt
+++ b/Tests/CompileDefinitions/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CompileDefinitions)
# Use compile flags to tell executables which config is built
diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt
index ef9198d3b..cff98e3c5 100644
--- a/Tests/CompileFeatures/CMakeLists.txt
+++ b/Tests/CompileFeatures/CMakeLists.txt
@@ -4,9 +4,12 @@ cmake_policy(SET CMP0057 NEW)
project(CompileFeatures)
+set(ext_C c)
+set(ext_CXX cpp)
+
macro(run_test feature lang)
if (${feature} IN_LIST CMAKE_${lang}_COMPILE_FEATURES)
- add_library(test_${feature} OBJECT ${feature})
+ add_library(test_${feature} OBJECT ${feature}.${ext_${lang}})
set_property(TARGET test_${feature}
PROPERTY COMPILE_FEATURES "${feature}"
)
@@ -15,7 +18,7 @@ macro(run_test feature lang)
endif()
endmacro()
-if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|XL|XLClang)$")
+if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
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})
@@ -23,7 +26,7 @@ if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|XL|XLClang)$")
endforeach()
endif()
-if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|XL|XLClang)$")
+if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
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})
@@ -268,6 +271,7 @@ if (CMAKE_CXX_COMPILE_FEATURES)
if (std_flag_idx EQUAL -1)
add_executable(default_dialect default_dialect.cpp)
target_compile_definitions(default_dialect PRIVATE
+ DEFAULT_CXX23=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},23>
DEFAULT_CXX20=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},20>
DEFAULT_CXX17=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},17>
DEFAULT_CXX14=$<EQUAL:${CMAKE_CXX_STANDARD_DEFAULT},14>
@@ -349,6 +353,7 @@ else()
HAVE_CXX_STD_14=$<COMPILE_FEATURES:cxx_std_14>
HAVE_CXX_STD_17=$<COMPILE_FEATURES:cxx_std_17>
HAVE_CXX_STD_20=$<COMPILE_FEATURES:cxx_std_20>
+ HAVE_CXX_STD_23=$<COMPILE_FEATURES:cxx_std_23>
)
endif()
diff --git a/Tests/CompileFeatures/default_dialect.cpp b/Tests/CompileFeatures/default_dialect.cpp
index e6b3ff631..bd504ffaa 100644
--- a/Tests/CompileFeatures/default_dialect.cpp
+++ b/Tests/CompileFeatures/default_dialect.cpp
@@ -18,7 +18,11 @@ struct Outputter;
# define CXX_STD __cplusplus
#endif
-#if DEFAULT_CXX20
+#if DEFAULT_CXX23
+# if CXX_STD <= 202002L
+Outputter<CXX_STD> o;
+# endif
+#elif DEFAULT_CXX20
# if CXX_STD <= 201703L
Outputter<CXX_STD> o;
# endif
diff --git a/Tests/CompileFeatures/genex_test.cpp b/Tests/CompileFeatures/genex_test.cpp
index 53dce625a..9c3910e03 100644
--- a/Tests/CompileFeatures/genex_test.cpp
+++ b/Tests/CompileFeatures/genex_test.cpp
@@ -21,6 +21,12 @@
# if HAVE_CXX_STD_17 && !defined(ALLOW_LATER_STANDARDS)
# error HAVE_CXX_STD_17 is true with CXX_STANDARD == 11
# endif
+# if HAVE_CXX_STD_20 && !defined(ALLOW_LATER_STANDARDS)
+# error HAVE_CXX_STD_20 is true with CXX_STANDARD == 11
+# endif
+# if HAVE_CXX_STD_23 && !defined(ALLOW_LATER_STANDARDS)
+# error HAVE_CXX_STD_23 is true with CXX_STANDARD == 11
+# endif
#endif
#if !HAVE_OVERRIDE_CONTROL
diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt
index 1433462ba..cd6cacd75 100644
--- a/Tests/CompileOptions/CMakeLists.txt
+++ b/Tests/CompileOptions/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(CompileOptions)
diff --git a/Tests/ConfigSources/CMakeLists.txt b/Tests/ConfigSources/CMakeLists.txt
index 9eed1c09b..a3d98f685 100644
--- a/Tests/ConfigSources/CMakeLists.txt
+++ b/Tests/ConfigSources/CMakeLists.txt
@@ -5,6 +5,11 @@ if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE)
endif()
project(ConfigSources CXX)
+if("${CMAKE_CXX_COMPILER_ID};${CMAKE_CXX_SIMULATE_ID}" STREQUAL "Intel;MSVC")
+ string(APPEND CMAKE_CXX_FLAGS_DEBUG " -Z7")
+ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -Z7")
+endif()
+
# Source file(s) named with the configuration(s).
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp"
@@ -16,6 +21,72 @@ void config_$<CONFIG>() {}
]]
)
+# Custom command outputs named with the configuration(s).
+add_custom_command(
+ OUTPUT "custom1_$<CONFIG>.cpp"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom1.cpp.in" "custom1_$<CONFIG>.cpp"
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom1.cpp.in
+ VERBATIM
+ )
+# Output path starts in a generator expression.
+add_custom_command(
+ OUTPUT "$<1:custom2_$<CONFIG>.cpp>"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom2.cpp.in" "custom2_$<CONFIG>.cpp"
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom2.cpp.in
+ VERBATIM
+ )
+# Source file generated as a custom command's byproduct.
+add_custom_command(
+ OUTPUT custom3.txt
+ BYPRODUCTS "$<1:custom3_$<CONFIG>.cpp>"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom3.cpp.in" "custom3_$<CONFIG>.cpp"
+ COMMAND ${CMAKE_COMMAND} -E touch custom3.txt
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom3.cpp.in
+ VERBATIM
+ )
+# Source file generated as a custom target's byproduct.
+add_custom_target(custom4
+ BYPRODUCTS "custom4_$<CONFIG>.cpp"
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/custom4.cpp.in" "custom4_$<CONFIG>.cpp"
+ VERBATIM
+ )
+# Source file generated by appended custom command.
+add_custom_command(
+ OUTPUT "custom5_$<CONFIG>.cpp"
+ COMMAND ${CMAKE_COMMAND} -E echo custom5_$<CONFIG>.cpp
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom5.cpp.in
+ VERBATIM
+ )
+add_custom_command(APPEND
+ OUTPUT "custom5_$<CONFIG>.cpp"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom5.cpp.in" "custom5_$<CONFIG>.cpp.in"
+ VERBATIM
+ )
+# Appending through any configuration's output affects all configurations.
+if(CMAKE_CONFIGURATION_TYPES MATCHES ";([^;]+)$")
+ set(last_config "${CMAKE_MATCH_1}")
+else()
+ set(last_config ${CMAKE_BUILD_TYPE})
+endif()
+add_custom_command(APPEND
+ OUTPUT "custom5_${last_config}.cpp"
+ COMMAND ${CMAKE_COMMAND} -E copy "custom5_$<CONFIG>.cpp.in" "custom5_$<CONFIG>.cpp"
+ VERBATIM
+ )
+foreach(n RANGE 1 5)
+ set_property(SOURCE custom${n}_Debug.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_DEBUG)
+ foreach(other Release RelWithDebInfo MinSizeRel)
+ set_property(SOURCE custom${n}_${other}.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_OTHER)
+ endforeach()
+endforeach()
+add_library(Custom STATIC
+ custom1_$<CONFIG>.cpp
+ custom2_$<CONFIG>.cpp
+ custom3_$<CONFIG>.cpp custom3.txt
+ custom4_$<CONFIG>.cpp
+ custom5_$<CONFIG>.cpp
+ )
+
# Per-config sources via INTERFACE_SOURCES.
add_library(iface INTERFACE)
target_sources(iface INTERFACE
@@ -34,7 +105,7 @@ add_executable(ConfigSources
$<$<CONFIG:NotAConfig>:does_not_exist.cpp>
${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp
)
-target_link_libraries(ConfigSources iface)
+target_link_libraries(ConfigSources Custom iface)
# Per-config sources via LINK_LIBRARIES.
add_library(iface_debug INTERFACE)
@@ -53,6 +124,7 @@ target_compile_definitions(ConfigSourcesLink PRIVATE
"$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
)
target_link_libraries(ConfigSourcesLink PRIVATE
+ Custom
"$<$<CONFIG:Debug>:iface_debug>"
"$<$<NOT:$<CONFIG:Debug>>:iface_other>"
"$<$<CONFIG:NotAConfig>:iface_does_not_exist>"
@@ -70,7 +142,7 @@ target_compile_definitions(ConfigSourcesLinkIface PRIVATE
"$<$<CONFIG:Debug>:CFG_DEBUG>"
"$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
)
-target_link_libraries(ConfigSourcesLinkIface ConfigSourcesIface)
+target_link_libraries(ConfigSourcesLinkIface Custom ConfigSourcesIface)
# A target with sources in only one configuration that is not the
# first in CMAKE_CONFIGURATION_TYPES.
diff --git a/Tests/ConfigSources/custom1.cpp.in b/Tests/ConfigSources/custom1.cpp.in
new file mode 100644
index 000000000..e5f21c783
--- /dev/null
+++ b/Tests/ConfigSources/custom1.cpp.in
@@ -0,0 +1,13 @@
+#ifdef CUSTOM_CFG_DEBUG
+int custom1_debug()
+{
+ return 0;
+}
+#endif
+
+#ifdef CUSTOM_CFG_OTHER
+int custom1_other()
+{
+ return 0;
+}
+#endif
diff --git a/Tests/ConfigSources/custom2.cpp.in b/Tests/ConfigSources/custom2.cpp.in
new file mode 100644
index 000000000..438c1fdf7
--- /dev/null
+++ b/Tests/ConfigSources/custom2.cpp.in
@@ -0,0 +1,13 @@
+#ifdef CUSTOM_CFG_DEBUG
+int custom2_debug()
+{
+ return 0;
+}
+#endif
+
+#ifdef CUSTOM_CFG_OTHER
+int custom2_other()
+{
+ return 0;
+}
+#endif
diff --git a/Tests/ConfigSources/custom3.cpp.in b/Tests/ConfigSources/custom3.cpp.in
new file mode 100644
index 000000000..4545b6950
--- /dev/null
+++ b/Tests/ConfigSources/custom3.cpp.in
@@ -0,0 +1,13 @@
+#ifdef CUSTOM_CFG_DEBUG
+int custom3_debug()
+{
+ return 0;
+}
+#endif
+
+#ifdef CUSTOM_CFG_OTHER
+int custom3_other()
+{
+ return 0;
+}
+#endif
diff --git a/Tests/ConfigSources/custom4.cpp.in b/Tests/ConfigSources/custom4.cpp.in
new file mode 100644
index 000000000..8a8b2a8df
--- /dev/null
+++ b/Tests/ConfigSources/custom4.cpp.in
@@ -0,0 +1,13 @@
+#ifdef CUSTOM_CFG_DEBUG
+int custom4_debug()
+{
+ return 0;
+}
+#endif
+
+#ifdef CUSTOM_CFG_OTHER
+int custom4_other()
+{
+ return 0;
+}
+#endif
diff --git a/Tests/ConfigSources/custom5.cpp.in b/Tests/ConfigSources/custom5.cpp.in
new file mode 100644
index 000000000..51f40aebb
--- /dev/null
+++ b/Tests/ConfigSources/custom5.cpp.in
@@ -0,0 +1,13 @@
+#ifdef CUSTOM_CFG_DEBUG
+int custom5_debug()
+{
+ return 0;
+}
+#endif
+
+#ifdef CUSTOM_CFG_OTHER
+int custom5_other()
+{
+ return 0;
+}
+#endif
diff --git a/Tests/ConfigSources/main_debug.cpp b/Tests/ConfigSources/main_debug.cpp
index 9b1e68a26..ef776f8ea 100644
--- a/Tests/ConfigSources/main_debug.cpp
+++ b/Tests/ConfigSources/main_debug.cpp
@@ -7,7 +7,14 @@
#include "iface.h"
+extern int custom1_debug();
+extern int custom2_debug();
+extern int custom3_debug();
+extern int custom4_debug();
+extern int custom5_debug();
+
int main(int argc, char** argv)
{
- return iface_src() + iface_debug();
+ return iface_src() + iface_debug() + custom1_debug() + custom2_debug() +
+ custom3_debug() + custom4_debug() + custom5_debug();
}
diff --git a/Tests/ConfigSources/main_other.cpp b/Tests/ConfigSources/main_other.cpp
index 3184a19d2..74f21569f 100644
--- a/Tests/ConfigSources/main_other.cpp
+++ b/Tests/ConfigSources/main_other.cpp
@@ -7,7 +7,14 @@
#include "iface.h"
+extern int custom1_other();
+extern int custom2_other();
+extern int custom3_other();
+extern int custom4_other();
+extern int custom5_other();
+
int main(int argc, char** argv)
{
- return iface_src() + iface_other();
+ return iface_src() + iface_other() + custom1_other() + custom2_other() +
+ custom3_other() + custom4_other() + custom5_other();
}
diff --git a/Tests/Contracts/Trilinos/CMakeLists.txt b/Tests/Contracts/Trilinos/CMakeLists.txt
index 4d7062bbd..6cc2d09dd 100644
--- a/Tests/Contracts/Trilinos/CMakeLists.txt
+++ b/Tests/Contracts/Trilinos/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(Trilinos)
include(ExternalProject)
diff --git a/Tests/Contracts/VTK/CMakeLists.txt b/Tests/Contracts/VTK/CMakeLists.txt
index 6ae273273..0d3632390 100644
--- a/Tests/Contracts/VTK/CMakeLists.txt
+++ b/Tests/Contracts/VTK/CMakeLists.txt
@@ -1,6 +1,6 @@
# The VTK external project for CMake
# ---------------------------------------------------------------------------
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(VTK)
include(ExternalProject)
diff --git a/Tests/Cuda/Toolkit/CMakeLists.txt b/Tests/Cuda/Toolkit/CMakeLists.txt
index 00125e3b9..8b42296d0 100644
--- a/Tests/Cuda/Toolkit/CMakeLists.txt
+++ b/Tests/Cuda/Toolkit/CMakeLists.txt
@@ -5,6 +5,10 @@ project(Toolkit CXX)
# Validate that we can use CUDAToolkit to find cuda include paths
find_package(CUDAToolkit REQUIRED)
+if(NOT DEFINED CUDAToolkit_VERSION)
+ message(FATAL_ERROR "expected CUDAToolkit variable CUDAToolkit_VERSION not found")
+endif()
+
message(STATUS "CUDAToolkit_VERSION: ${CUDAToolkit_VERSION}")
message(STATUS "CUDAToolkit_VERSION_MAJOR: ${CUDAToolkit_VERSION_MAJOR}")
message(STATUS "CUDAToolkit_VERSION_MINOR: ${CUDAToolkit_VERSION_MINOR}")
diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt
index 033f1976f..fdb7a6eda 100644
--- a/Tests/CudaOnly/CMakeLists.txt
+++ b/Tests/CudaOnly/CMakeLists.txt
@@ -11,6 +11,7 @@ add_cuda_test_macro(CudaOnly.ExportPTX CudaOnlyExportPTX)
add_cuda_test_macro(CudaOnly.SharedRuntimePlusToolkit CudaOnlySharedRuntimePlusToolkit)
add_cuda_test_macro(CudaOnly.Standard98 CudaOnlyStandard98)
add_cuda_test_macro(CudaOnly.Toolkit CudaOnlyToolkit)
+add_cuda_test_macro(CudaOnly.ToolkitBeforeLang CudaOnlyToolkitBeforeLang)
add_cuda_test_macro(CudaOnly.WithDefs CudaOnlyWithDefs)
add_cuda_test_macro(CudaOnly.CircularLinkLine CudaOnlyCircularLinkLine)
add_cuda_test_macro(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
diff --git a/Tests/CudaOnly/CompileFlags/CMakeLists.txt b/Tests/CudaOnly/CompileFlags/CMakeLists.txt
index 5e8a8e40f..38765ecb9 100644
--- a/Tests/CudaOnly/CompileFlags/CMakeLists.txt
+++ b/Tests/CudaOnly/CompileFlags/CMakeLists.txt
@@ -8,6 +8,7 @@ if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
target_compile_options(CudaOnlyCompileFlags PRIVATE
-gencode arch=compute_50,code=compute_50
)
+ set_property(TARGET CudaOnlyCompileFlags PROPERTY CUDA_ARCHITECTURES)
else()
set_property(TARGET CudaOnlyCompileFlags PROPERTY CUDA_ARCHITECTURES 50-real)
endif()
diff --git a/Tests/CudaOnly/ExportPTX/CMakeLists.txt b/Tests/CudaOnly/ExportPTX/CMakeLists.txt
index ee5f54d02..e7e7bc4f4 100644
--- a/Tests/CudaOnly/ExportPTX/CMakeLists.txt
+++ b/Tests/CudaOnly/ExportPTX/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.8)
+cmake_minimum_required(VERSION 3.19)
project (ExportPTX CUDA)
#Goal for this example:
@@ -6,6 +6,10 @@ project (ExportPTX CUDA)
# How to reference PTX files for custom commands
# How to install PTX files
+# PTX can be compiled only for a single virtual architecture at a time
+list(SUBLIST CMAKE_CUDA_ARCHITECTURES 0 1 CMAKE_CUDA_ARCHITECTURES)
+string(APPEND CMAKE_CUDA_ARCHITECTURES "-virtual")
+
add_library(CudaPTX OBJECT kernelA.cu kernelB.cu)
set_property(TARGET CudaPTX PROPERTY CUDA_PTX_COMPILATION ON)
diff --git a/Tests/CudaOnly/Toolkit/CMakeLists.txt b/Tests/CudaOnly/Toolkit/CMakeLists.txt
index bb06ba8d3..1486c1ae4 100644
--- a/Tests/CudaOnly/Toolkit/CMakeLists.txt
+++ b/Tests/CudaOnly/Toolkit/CMakeLists.txt
@@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 3.15)
project(CudaOnlyToolkit CUDA)
find_package(CUDAToolkit REQUIRED)
+if(NOT DEFINED CUDAToolkit_VERSION)
+ message(FATAL_ERROR "expected CUDAToolkit variable CUDAToolkit_VERSION not found")
+endif()
+
message(STATUS "CUDAToolkit_VERSION: ${CUDAToolkit_VERSION}")
message(STATUS "CUDAToolkit_VERSION_MAJOR: ${CUDAToolkit_VERSION_MAJOR}")
message(STATUS "CUDAToolkit_VERSION_MINOR: ${CUDAToolkit_VERSION_MINOR}")
diff --git a/Tests/CudaOnly/ToolkitBeforeLang/CMakeLists.txt b/Tests/CudaOnly/ToolkitBeforeLang/CMakeLists.txt
new file mode 100644
index 000000000..8dff6cc53
--- /dev/null
+++ b/Tests/CudaOnly/ToolkitBeforeLang/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 3.15)
+project(CudaOnlyToolkitBeforeLang CXX)
+
+# Validate that CUDAToolkit gets the correct version
+# when called before CUDA the language is enabled
+find_package(CUDAToolkit REQUIRED)
+enable_language(CUDA)
+
+if(NOT DEFINED CUDAToolkit_VERSION)
+ message(FATAL_ERROR "expected CUDAToolkit variable CUDAToolkit_VERSION not found")
+endif()
+
+set(cuda_libs cudart cuda_driver)
+
+# Verify that all the CUDA:: targets and variables exist
+foreach (cuda_lib IN LISTS cuda_libs)
+ if(NOT CUDA_${cuda_lib}_LIBRARY)
+ message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found")
+ endif()
+ if(NOT TARGET CUDA::${cuda_lib})
+ message(FATAL_ERROR "expected CUDAToolkit target CUDA::${cuda_lib} not found")
+ endif()
+endforeach()
+
+add_executable(CudaOnlyToolkitBeforeLang main.cu)
+target_link_libraries(CudaOnlyToolkitBeforeLang PRIVATE CUDA::toolkit)
diff --git a/Tests/CudaOnly/ToolkitBeforeLang/main.cu b/Tests/CudaOnly/ToolkitBeforeLang/main.cu
new file mode 100644
index 000000000..0f3ccdcc8
--- /dev/null
+++ b/Tests/CudaOnly/ToolkitBeforeLang/main.cu
@@ -0,0 +1,8 @@
+// Only thing we care about is that these headers are found
+#include <cuda.h>
+#include <cuda_runtime_api.h>
+
+int main(int argc, char** argv)
+{
+ return 0;
+}
diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt
index c1a7a5768..80545c483 100644
--- a/Tests/CustomCommand/CMakeLists.txt
+++ b/Tests/CustomCommand/CMakeLists.txt
@@ -582,3 +582,7 @@ 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
+add_executable(empty_command empty_command.cxx)
+add_custom_command(TARGET empty_command POST_BUILD COMMAND $<0:date>)
diff --git a/Tests/Server/empty.cpp b/Tests/CustomCommand/empty_command.cxx
index 766b7751b..f8b643afb 100644
--- a/Tests/Server/empty.cpp
+++ b/Tests/CustomCommand/empty_command.cxx
@@ -1,4 +1,3 @@
-
int main()
{
return 0;
diff --git a/Tests/EmptyDepends/CMakeLists.txt b/Tests/EmptyDepends/CMakeLists.txt
index 832d9dce6..272eff7fa 100644
--- a/Tests/EmptyDepends/CMakeLists.txt
+++ b/Tests/EmptyDepends/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(EmptyDepends)
include(CTest)
diff --git a/Tests/ExportImport/Import/try_compile/CMakeLists.txt b/Tests/ExportImport/Import/try_compile/CMakeLists.txt
index 10884616b..813cf0666 100644
--- a/Tests/ExportImport/Import/try_compile/CMakeLists.txt
+++ b/Tests/ExportImport/Import/try_compile/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
find_package(testLibRequired 2.5 REQUIRED)
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index 29cdcc99e..59e3bcc1f 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ExternalProjectTest NONE)
if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12)
cmake_policy(SET CMP0114 NEW)
@@ -161,7 +161,7 @@ if(do_cvs_tests)
#
set(proj TutorialStep1-CVS-20090626)
ExternalProject_Add(${proj}
- CVS_REPOSITORY "${local_cvs_repo}"
+ CVS_REPOSITORY ":local:${local_cvs_repo}"
CVS_MODULE "TutorialStep1"
CVS_TAG "-D2009-06-26 16:50:00 UTC"
UPDATE_COMMAND ""
@@ -176,7 +176,7 @@ if(do_cvs_tests)
#
set(proj TutorialStep1-CVS-testtag1)
ExternalProject_Add(${proj}
- CVS_REPOSITORY "${local_cvs_repo}"
+ CVS_REPOSITORY ":local:${local_cvs_repo}"
CVS_MODULE "TutorialStep1"
CVS_TAG -rtesttag1
UPDATE_COMMAND ""
@@ -191,7 +191,7 @@ if(do_cvs_tests)
#
set(proj TutorialStep1-CVS-HEAD)
ExternalProject_Add(${proj}
- CVS_REPOSITORY "${local_cvs_repo}"
+ CVS_REPOSITORY ":local:${local_cvs_repo}"
CVS_MODULE "TutorialStep1"
CMAKE_GENERATOR "${CMAKE_GENERATOR}"
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
@@ -298,15 +298,9 @@ set(do_git_tests 0)
if(GIT_EXECUTABLE)
set(do_git_tests 1)
- execute_process(
- COMMAND "${GIT_EXECUTABLE}" --version
- OUTPUT_VARIABLE ov
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
- string(REGEX REPLACE "^git version (.+)$" "\\1" git_version "${ov}")
- message(STATUS "git_version='${git_version}'")
+ message(STATUS "GIT_VERSION_STRING='${GIT_VERSION_STRING}'")
- if(git_version VERSION_LESS 1.6.5)
+ if("${GIT_VERSION_STRING}" VERSION_LESS 1.6.5)
message(STATUS "No ExternalProject git tests with git client less than version 1.6.5")
set(do_git_tests 0)
endif()
@@ -335,7 +329,7 @@ if(do_git_tests)
set(proj TutorialStep1-GIT-byhash)
ExternalProject_Add(${proj}
GIT_REPOSITORY "${local_git_repo}"
- GIT_TAG d1970730310fe8bc07e73f15dc570071f9f9654a
+ GIT_TAG 57418671a0a0e371e7bac532337152595fbe0df5 # generated by gitrepo.bash
UPDATE_COMMAND ""
CMAKE_GENERATOR "${CMAKE_GENERATOR}"
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
@@ -670,23 +664,23 @@ endif()
if(do_git_tests)
add_test(TutorialStep1-GIT-byhash
- "${binary_base}/TutorialStep1-GIT-byhash/Tutorial" 100)
+ ${CMAKE_COMMAND} -P "${binary_base}/TutorialStep1-GIT-byhash/example.cmake")
add_test(TutorialStep1-GIT-bytag
- "${binary_base}/TutorialStep1-GIT-bytag/Tutorial" 99)
+ ${CMAKE_COMMAND} -P "${binary_base}/TutorialStep1-GIT-bytag/example.cmake")
add_test(TutorialStep1-GIT-bytag-withsubmodules
- "${binary_base}/TutorialStep1-GIT-bytag-withsubmodules/Tutorial" 99)
+ ${CMAKE_COMMAND} -P "${binary_base}/TutorialStep1-GIT-bytag-withsubmodules/example.cmake")
add_test(TutorialStep1-GIT-shallow-master
- "${binary_base}/TutorialStep1-GIT-shallow-master/Tutorial" 98)
+ ${CMAKE_COMMAND} -P "${binary_base}/TutorialStep1-GIT-shallow-master/example.cmake")
add_test(TutorialStep1-GIT-master
- "${binary_base}/TutorialStep1-GIT-master/Tutorial" 98)
+ ${CMAKE_COMMAND} -P "${binary_base}/TutorialStep1-GIT-master/example.cmake")
if(NOT git_version VERSION_LESS 1.7.7)
add_test(TutorialStep1-GIT-config
- "${binary_base}/TutorialStep1-GIT-config/Tutorial" 98)
+ ${CMAKE_COMMAND} -P "${binary_base}/TutorialStep1-GIT-config/example.cmake")
endif()
endif()
diff --git a/Tests/ExternalProject/Example/CMakeLists.txt b/Tests/ExternalProject/Example/CMakeLists.txt
index 4c128957e..c3f2614e4 100644
--- a/Tests/ExternalProject/Example/CMakeLists.txt
+++ b/Tests/ExternalProject/Example/CMakeLists.txt
@@ -1,5 +1,5 @@
# This is the canonical simplest ExternalProject example CMakeLists.txt file:
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ExternalProjectExample NONE)
include(ExternalProject)
diff --git a/Tests/ExternalProject/gitrepo-sub-rec.tgz b/Tests/ExternalProject/gitrepo-sub-rec.tgz
index b0f3f18b7..0e63651c0 100644
--- a/Tests/ExternalProject/gitrepo-sub-rec.tgz
+++ b/Tests/ExternalProject/gitrepo-sub-rec.tgz
Binary files differ
diff --git a/Tests/ExternalProject/gitrepo-sub.tgz b/Tests/ExternalProject/gitrepo-sub.tgz
index c0b536017..ab34fff0b 100644
--- a/Tests/ExternalProject/gitrepo-sub.tgz
+++ b/Tests/ExternalProject/gitrepo-sub.tgz
Binary files differ
diff --git a/Tests/ExternalProject/gitrepo.bash b/Tests/ExternalProject/gitrepo.bash
new file mode 100755
index 000000000..c341f282e
--- /dev/null
+++ b/Tests/ExternalProject/gitrepo.bash
@@ -0,0 +1,129 @@
+#!/usr/bin/env bash
+
+set -e
+set -x
+
+readonly tmpdir="$(mktemp -d)"
+trap "rm -rf '$tmpdir'" EXIT
+
+readonly outdir="${BASH_SOURCE%/*}"
+readonly defaultBranch='master'
+
+export GIT_AUTHOR_NAME='testauthor'
+export GIT_AUTHOR_EMAIL='testauthor@cmake.org'
+export GIT_COMMITTER_NAME='testauthor'
+export GIT_COMMITTER_EMAIL='testauthor@cmake.org'
+
+(
+cd "$tmpdir"
+
+git --bare init -b "$defaultBranch" gitrepo.git
+rm -f gitrepo.git/hooks/*.sample
+
+mkdir gitrepo
+cd gitrepo
+git init -b "$defaultBranch"
+echo 'cmake_minimum_required(VERSION 3.19)
+project(Example NONE)
+add_custom_target(example ALL
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/example.cmake.in example.cmake
+)' >CMakeLists.txt
+echo 'message(STATUS example)' >example.cmake.in
+git add CMakeLists.txt example.cmake.in
+git commit -m "Initial import into repo."
+git push ../gitrepo.git "$defaultBranch"
+cd ../gitrepo.git
+git gc --prune
+cd ..
+ln -s gitrepo.git GIT
+
+git --bare init -b "$defaultBranch" gitrepo-sub.git
+rm -f gitrepo-sub.git/hooks/*.sample
+
+mkdir gitrepo-sub
+cd gitrepo-sub
+git init -b "$defaultBranch"
+echo 'cmake_minimum_required(VERSION 3.19)
+project(ExampleWithSub NONE)
+file(STRINGS "${CMAKE_SOURCE_DIR}/.git/config" git_config_strings
+ REGEX "^\\[submodule")
+foreach(submodule m1 m2)
+ option(WITH_${submodule} "Enable ${submodule}" OFF)
+ set(${submodule}_INITED FALSE)
+ set(${submodule}_UPDATED FALSE)
+ foreach(s ${git_config_strings})
+ if("${s}" MATCHES "${submodule}")
+ set(${submodule}_INITED TRUE)
+ endif()
+ endforeach()
+ if(EXISTS "${CMAKE_SOURCE_DIR}/m/${submodule}/CMakeLists.txt")
+ set(${submodule}_UPDATED TRUE)
+ endif()
+ if(WITH_${submodule})
+ if(NOT ${submodule}_INITED)
+ message(FATAL_ERROR "${submodule} not inited")
+ elseif(NOT ${submodule}_UPDATED)
+ message(FATAL_ERROR "${submodule} not updated")
+ endif()
+ else()
+ if(${submodule}_INITED)
+ message(FATAL_ERROR "${submodule} inited")
+ elseif(${submodule}_UPDATED)
+ message(FATAL_ERROR "${submodule} updated")
+ endif()
+ endif()
+endforeach()' >CMakeLists.txt
+git add CMakeLists.txt
+git submodule add -- ../GIT m/m1
+git submodule add -- ../GIT m/m2
+git submodule add -- ../GIT m/m3
+git commit -m "Initial import into repo."
+git push ../gitrepo-sub.git "$defaultBranch"
+cd ../gitrepo-sub.git
+git gc --prune
+cd ..
+ln -s gitrepo-sub.git GIT-with-submodules
+
+git --bare init -b "$defaultBranch" gitrepo-sub-rec.git
+rm -f gitrepo-sub-rec.git/hooks/*.sample
+
+mkdir gitrepo-sub-rec
+cd gitrepo-sub-rec
+git init -b "$defaultBranch"
+echo 'cmake_minimum_required(VERSION 3.19)
+project(ExampleWithRecSub NONE)
+set(top_submodule_dir "${CMAKE_SOURCE_DIR}/submodule")
+if(NOT EXISTS "${top_submodule_dir}/CMakeLists.txt")
+ message(FATAL_ERROR "Top submodule not updated")
+endif()
+option(WITH_RECURSIVE "Submodules are updated recursively" ON)
+foreach(submodule m1 m2 m3)
+ set(${submodule}_UPDATED FALSE)
+ if(EXISTS "${top_submodule_dir}/m/${submodule}/CMakeLists.txt")
+ set(${submodule}_UPDATED TRUE)
+ endif()
+ if(WITH_RECURSIVE)
+ if(NOT ${submodule}_UPDATED)
+ message(FATAL_ERROR "${submodule} not updated")
+ endif()
+ else()
+ if(${submodule}_UPDATED)
+ message(FATAL_ERROR "${submodule} updated")
+ endif()
+ endif()
+endforeach()' >CMakeLists.txt
+git add CMakeLists.txt
+git submodule add -- ../GIT-with-submodules submodule
+git commit -m "Initial import into repo."
+git push ../gitrepo-sub-rec.git "$defaultBranch"
+cd ../gitrepo-sub-rec.git
+git gc --prune
+cd ..
+)
+
+tar cvzf "$outdir/gitrepo.tgz" -C "$tmpdir" gitrepo.git
+tar cvzf "$outdir/gitrepo-sub.tgz" -C "$tmpdir" gitrepo-sub.git
+tar cvzf "$outdir/gitrepo-sub-rec.tgz" -C "$tmpdir" gitrepo-sub-rec.git
+
+git_tag=$(cd "$tmpdir/gitrepo.git" ; git rev-parse HEAD)
+sed -i "/generated by gitrepo.bash/ s/ [0-9a-f]\\+ / $git_tag /" "$outdir/CMakeLists.txt"
diff --git a/Tests/ExternalProject/gitrepo.tgz b/Tests/ExternalProject/gitrepo.tgz
index 0a84bda7c..8d2d14472 100644
--- a/Tests/ExternalProject/gitrepo.tgz
+++ b/Tests/ExternalProject/gitrepo.tgz
Binary files differ
diff --git a/Tests/ExternalProjectLocal/CMakeLists.txt b/Tests/ExternalProjectLocal/CMakeLists.txt
index 789e4fb29..9a0241c27 100644
--- a/Tests/ExternalProjectLocal/CMakeLists.txt
+++ b/Tests/ExternalProjectLocal/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ExternalProjectLocalTest NONE)
if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12)
cmake_policy(SET CMP0114 NEW)
diff --git a/Tests/ExternalProjectUpdate/CMakeLists.txt b/Tests/ExternalProjectUpdate/CMakeLists.txt
index 563a6cf9f..6f8a7b15b 100644
--- a/Tests/ExternalProjectUpdate/CMakeLists.txt
+++ b/Tests/ExternalProjectUpdate/CMakeLists.txt
@@ -1,7 +1,12 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ExternalProjectUpdateTest NONE)
if(CMAKE_XCODE_BUILD_SYSTEM VERSION_GREATER_EQUAL 12)
cmake_policy(SET CMP0114 NEW)
+else()
+ # This test is very noisy with warnings about this policy if we don't
+ # explicitly set it. Projects shouldn't do this, but for test code this
+ # is reasonable.
+ cmake_policy(SET CMP0114 OLD)
endif()
cmake_policy(GET CMP0114 cmp0114)
@@ -51,15 +56,9 @@ set(do_git_tests 0)
if(GIT_EXECUTABLE)
set(do_git_tests 1)
- execute_process(
- COMMAND "${GIT_EXECUTABLE}" --version
- OUTPUT_VARIABLE ov
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
- string(REGEX REPLACE "^git version (.+)$" "\\1" git_version "${ov}")
- message(STATUS "git_version='${git_version}'")
+ message(STATUS "GIT_VERSION_STRING='${GIT_VERSION_STRING}'")
- if(git_version VERSION_LESS 1.6.5)
+ if("${GIT_VERSION_STRING}" VERSION_LESS 1.6.5)
message(STATUS "No ExternalProject git tests with git client less than version 1.6.5")
set(do_git_tests 0)
endif()
diff --git a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
index ddc513f04..394df8721 100644
--- a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
+++ b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
@@ -167,15 +167,9 @@ set(do_git_tests 0)
if(GIT_EXECUTABLE)
set(do_git_tests 1)
- execute_process(
- COMMAND "${GIT_EXECUTABLE}" --version
- OUTPUT_VARIABLE ov
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
- string(REGEX REPLACE "^git version (.+)$" "\\1" git_version "${ov}")
- message(STATUS "git_version='${git_version}'")
+ message(STATUS "GIT_VERSION_STRING='${GIT_VERSION_STRING}'")
- if(git_version VERSION_LESS 1.6.5)
+ if("${GIT_VERSION_STRING}" VERSION_LESS 1.6.5)
message(STATUS "No ExternalProject git tests with git client less than version 1.6.5")
set(do_git_tests 0)
endif()
@@ -185,17 +179,16 @@ endif()
file(REMOVE_RECURSE ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals)
if(do_git_tests)
- check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 1 REBASE)
- # With the Git UPDATE_COMMAND performance patch, this will not required a
+ # With the Git UPDATE_COMMAND performance patch, this will not require a
# 'git fetch'
check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
check_a_tag(tag2 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
- check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 1 REBASE)
check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
- check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
# This is a remote symbolic ref, so it will always trigger a 'git fetch'
- check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
foreach(strategy IN ITEMS CHECKOUT REBASE_CHECKOUT)
# Move local master back, then apply a change that will cause a conflict
@@ -229,7 +222,19 @@ if(do_git_tests)
message(FATAL_ERROR "Could not commit conflicting change.")
endif()
# This should discard our commit but leave behind an annotated tag
- check_a_tag(origin/master 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 ${strategy})
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 ${strategy})
endforeach()
+ # This file matches a .gitignore rule that the last commit defines. We can't
+ # directly check that updates don't stash ignored contents because the stash
+ # and pop are both done within the update step. We don't have an opportunity
+ # to check things in between, but we can at least check that the update step
+ # doesn't choke on it.
+ set(ignoredFile ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT/ignored_item)
+ file(TOUCH ${ignoredFile})
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
+ if(NOT EXISTS ${ignoredFile})
+ message(FATAL_ERROR "Ignored file is missing")
+ endif()
+
endif()
diff --git a/Tests/ExternalProjectUpdate/gitrepo.tgz b/Tests/ExternalProjectUpdate/gitrepo.tgz
index 87090ab0b..4dab56be6 100644
--- a/Tests/ExternalProjectUpdate/gitrepo.tgz
+++ b/Tests/ExternalProjectUpdate/gitrepo.tgz
Binary files differ
diff --git a/Tests/FindGTK2/atk/CMakeLists.txt b/Tests/FindGTK2/atk/CMakeLists.txt
index be37957ed..0392d88c4 100644
--- a/Tests/FindGTK2/atk/CMakeLists.txt
+++ b/Tests/FindGTK2/atk/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(atk C)
diff --git a/Tests/FindGTK2/atkmm/CMakeLists.txt b/Tests/FindGTK2/atkmm/CMakeLists.txt
index e8320b533..ec838deb9 100644
--- a/Tests/FindGTK2/atkmm/CMakeLists.txt
+++ b/Tests/FindGTK2/atkmm/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(atkmm CXX)
diff --git a/Tests/FindGTK2/cairo/CMakeLists.txt b/Tests/FindGTK2/cairo/CMakeLists.txt
index 97a736944..3652ad603 100644
--- a/Tests/FindGTK2/cairo/CMakeLists.txt
+++ b/Tests/FindGTK2/cairo/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(cairo C)
diff --git a/Tests/FindGTK2/cairomm/CMakeLists.txt b/Tests/FindGTK2/cairomm/CMakeLists.txt
index 47a156e2c..cde0f4220 100644
--- a/Tests/FindGTK2/cairomm/CMakeLists.txt
+++ b/Tests/FindGTK2/cairomm/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(cairomm CXX)
diff --git a/Tests/FindGTK2/gdk/CMakeLists.txt b/Tests/FindGTK2/gdk/CMakeLists.txt
index f4852368c..35ef33777 100644
--- a/Tests/FindGTK2/gdk/CMakeLists.txt
+++ b/Tests/FindGTK2/gdk/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gdk C)
diff --git a/Tests/FindGTK2/gdk_pixbuf/CMakeLists.txt b/Tests/FindGTK2/gdk_pixbuf/CMakeLists.txt
index 004e82e8a..ea1b05da6 100644
--- a/Tests/FindGTK2/gdk_pixbuf/CMakeLists.txt
+++ b/Tests/FindGTK2/gdk_pixbuf/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gdk_pixbuf C)
diff --git a/Tests/FindGTK2/gdkmm/CMakeLists.txt b/Tests/FindGTK2/gdkmm/CMakeLists.txt
index a54fc4f13..72fc6f415 100644
--- a/Tests/FindGTK2/gdkmm/CMakeLists.txt
+++ b/Tests/FindGTK2/gdkmm/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gdkmm CXX)
diff --git a/Tests/FindGTK2/gio/CMakeLists.txt b/Tests/FindGTK2/gio/CMakeLists.txt
index db9cdd00a..4835afa54 100644
--- a/Tests/FindGTK2/gio/CMakeLists.txt
+++ b/Tests/FindGTK2/gio/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gio C)
diff --git a/Tests/FindGTK2/giomm/CMakeLists.txt b/Tests/FindGTK2/giomm/CMakeLists.txt
index 46cfef50a..b639979b5 100644
--- a/Tests/FindGTK2/giomm/CMakeLists.txt
+++ b/Tests/FindGTK2/giomm/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(giomm CXX)
diff --git a/Tests/FindGTK2/glib/CMakeLists.txt b/Tests/FindGTK2/glib/CMakeLists.txt
index 1aa73ff16..536fc67d0 100644
--- a/Tests/FindGTK2/glib/CMakeLists.txt
+++ b/Tests/FindGTK2/glib/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(glib C)
diff --git a/Tests/FindGTK2/glibmm/CMakeLists.txt b/Tests/FindGTK2/glibmm/CMakeLists.txt
index af8ddcf27..25d55184c 100644
--- a/Tests/FindGTK2/glibmm/CMakeLists.txt
+++ b/Tests/FindGTK2/glibmm/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(glibmm CXX)
diff --git a/Tests/FindGTK2/gmodule/CMakeLists.txt b/Tests/FindGTK2/gmodule/CMakeLists.txt
index 9717da8d5..2bfb81eeb 100644
--- a/Tests/FindGTK2/gmodule/CMakeLists.txt
+++ b/Tests/FindGTK2/gmodule/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gmodule C)
diff --git a/Tests/FindGTK2/gobject/CMakeLists.txt b/Tests/FindGTK2/gobject/CMakeLists.txt
index c51fd4dee..11520f8a1 100644
--- a/Tests/FindGTK2/gobject/CMakeLists.txt
+++ b/Tests/FindGTK2/gobject/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gobject C)
diff --git a/Tests/FindGTK2/gthread/CMakeLists.txt b/Tests/FindGTK2/gthread/CMakeLists.txt
index a90294d0a..5ecfd9be6 100644
--- a/Tests/FindGTK2/gthread/CMakeLists.txt
+++ b/Tests/FindGTK2/gthread/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gthread C)
diff --git a/Tests/FindGTK2/gtk/CMakeLists.txt b/Tests/FindGTK2/gtk/CMakeLists.txt
index 11603aec9..2c6761998 100644
--- a/Tests/FindGTK2/gtk/CMakeLists.txt
+++ b/Tests/FindGTK2/gtk/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gtk C)
diff --git a/Tests/FindGTK2/gtkmm/CMakeLists.txt b/Tests/FindGTK2/gtkmm/CMakeLists.txt
index eb0b7aa8d..3375a5583 100644
--- a/Tests/FindGTK2/gtkmm/CMakeLists.txt
+++ b/Tests/FindGTK2/gtkmm/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(gtkmm CXX)
diff --git a/Tests/FindGTK2/pango/CMakeLists.txt b/Tests/FindGTK2/pango/CMakeLists.txt
index af382a4c7..bd6b13a6e 100644
--- a/Tests/FindGTK2/pango/CMakeLists.txt
+++ b/Tests/FindGTK2/pango/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(pango C)
diff --git a/Tests/FindGTK2/pangocairo/CMakeLists.txt b/Tests/FindGTK2/pangocairo/CMakeLists.txt
index 8f61379b3..157b9c2fe 100644
--- a/Tests/FindGTK2/pangocairo/CMakeLists.txt
+++ b/Tests/FindGTK2/pangocairo/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(pangocairo C)
diff --git a/Tests/FindGTK2/pangoft2/CMakeLists.txt b/Tests/FindGTK2/pangoft2/CMakeLists.txt
index 0f84c7fdf..76966e7a9 100644
--- a/Tests/FindGTK2/pangoft2/CMakeLists.txt
+++ b/Tests/FindGTK2/pangoft2/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(pangoft2 C)
diff --git a/Tests/FindGTK2/pangomm/CMakeLists.txt b/Tests/FindGTK2/pangomm/CMakeLists.txt
index 3650c5080..0bb49e2d0 100644
--- a/Tests/FindGTK2/pangomm/CMakeLists.txt
+++ b/Tests/FindGTK2/pangomm/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(pangomm CXX)
diff --git a/Tests/FindGTK2/pangoxft/CMakeLists.txt b/Tests/FindGTK2/pangoxft/CMakeLists.txt
index 0db16b153..7051d3513 100644
--- a/Tests/FindGTK2/pangoxft/CMakeLists.txt
+++ b/Tests/FindGTK2/pangoxft/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(pangoxft C)
diff --git a/Tests/FindGTK2/sigc++/CMakeLists.txt b/Tests/FindGTK2/sigc++/CMakeLists.txt
index f830b81b7..9c1fff783 100644
--- a/Tests/FindGTK2/sigc++/CMakeLists.txt
+++ b/Tests/FindGTK2/sigc++/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(sigc++ CXX)
diff --git a/Tests/FindIntl/CMakeLists.txt b/Tests/FindIntl/CMakeLists.txt
new file mode 100644
index 000000000..0906ede35
--- /dev/null
+++ b/Tests/FindIntl/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindIntl.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindIntl/Test"
+ "${CMake_BINARY_DIR}/Tests/FindIntl/Test"
+ ${build_generator_args}
+ --build-project TestFindIntl
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindIntl/Test/CMakeLists.txt b/Tests/FindIntl/Test/CMakeLists.txt
new file mode 100644
index 000000000..51404061c
--- /dev/null
+++ b/Tests/FindIntl/Test/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.10)
+project(TestFindIntl CXX)
+include(CTest)
+
+find_package(Intl REQUIRED)
+
+add_executable(test_intl_tgt main.cxx)
+target_link_libraries(test_intl_tgt Intl::Intl)
+add_test(NAME test_intl_tgt COMMAND test_intl_tgt)
+
+add_executable(test_intl_var main.cxx)
+target_include_directories(test_intl_var PRIVATE ${Intl_INCLUDE_DIRS})
+target_link_libraries(test_intl_var PRIVATE ${Intl_LIBRARIES})
+add_test(NAME test_intl_var COMMAND test_intl_var)
diff --git a/Tests/FindIntl/Test/main.cxx b/Tests/FindIntl/Test/main.cxx
new file mode 100644
index 000000000..d90c09541
--- /dev/null
+++ b/Tests/FindIntl/Test/main.cxx
@@ -0,0 +1,11 @@
+extern "C" {
+#include <libintl.h>
+}
+
+int main()
+{
+ // Check if we include the directory correctly and have no link errors
+ bindtextdomain("", "");
+ gettext("");
+ return 0;
+}
diff --git a/Tests/FindPostgreSQL/Test/CMakeLists.txt b/Tests/FindPostgreSQL/Test/CMakeLists.txt
index 374e1477b..1bc5c56d4 100644
--- a/Tests/FindPostgreSQL/Test/CMakeLists.txt
+++ b/Tests/FindPostgreSQL/Test/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
project(TestFindPostgreSQL C)
include(CTest)
-find_package(PostgreSQL REQUIRED)
+find_package(PostgreSQL REQUIRED COMPONENTS Server)
add_definitions(-DCMAKE_EXPECTED_POSTGRESQL_VERSION="${PostgreSQL_VERSION_STRING}")
diff --git a/Tests/FindPython/CMakeLists.txt b/Tests/FindPython/CMakeLists.txt
index 44484c35e..520ba9e16 100644
--- a/Tests/FindPython/CMakeLists.txt
+++ b/Tests/FindPython/CMakeLists.txt
@@ -451,6 +451,18 @@ if(CMake_TEST_FindPython)
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
endif()
+
+ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ add_test(NAME FindPython.UnversionedNames COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindPython/UnversionedNames"
+ "${CMake_BINARY_DIR}/Tests/FindPython/UnversionedNames"
+ ${build_generator_args}
+ --build-project UnversionedNames
+ --build-options ${build_options}
+ )
+ endif()
endif()
if(CMake_TEST_FindPython_NumPy)
diff --git a/Tests/FindPython/UnversionedNames/CMakeLists.txt b/Tests/FindPython/UnversionedNames/CMakeLists.txt
new file mode 100644
index 000000000..597bd4ecb
--- /dev/null
+++ b/Tests/FindPython/UnversionedNames/CMakeLists.txt
@@ -0,0 +1,66 @@
+cmake_minimum_required(VERSION 3.19...3.20)
+
+project(UnversionedNames LANGUAGES NONE)
+
+# check if it is possible to find python with a generic name
+find_program(UNVERSIONED_Python3 NAMES python3)
+
+if (NOT UNVERSIONED_Python3)
+ # no generic name available
+ # test cannot be done
+ return()
+endif()
+
+# search with default configuration
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
+
+if (Python3_EXECUTABLE STREQUAL UNVERSIONED_Python3)
+ # default configuration pick-up the generic name
+ # test cannot be completed
+ return()
+endif()
+
+unset(Python3_EXECUTABLE)
+# Force now to search first for generic name
+set(Python3_FIND_UNVERSIONED_NAMES FIRST)
+
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
+
+if (NOT Python3_EXECUTABLE STREQUAL UNVERSIONED_Python3)
+ message(SEND_ERROR "Found unexpected interpreter ${Python3_EXECUTABLE} instead of ${UNVERSIONED_Python3}")
+endif()
+
+# To check value 'NEVER", creates directory holding a symlink to the generic name
+file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/bin")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
+file(CREATE_LINK "${UNVERSIONED_Python3}" "${CMAKE_CURRENT_BINARY_DIR}/bin/python3" SYMBOLIC)
+
+unset(Python3_EXECUTABLE)
+set(Python3_FIND_UNVERSIONED_NAMES FIRST)
+set(Python3_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+# First search: generic name must be found
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
+
+if (NOT Python3_EXECUTABLE STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/bin/python3")
+ message(FATAL_ERROR "Found unexpected interpreter ${Python3_EXECUTABLE} instead of ${CMAKE_CURRENT_BINARY_DIR}/bin/python3")
+endif()
+
+unset(Python3_EXECUTABLE)
+set(Python3_FIND_UNVERSIONED_NAMES LAST)
+
+# Second search: generic name must be found
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
+
+if (NOT Python3_EXECUTABLE STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/bin/python3")
+ message(FATAL_ERROR "Found unexpected interpreter ${Python3_EXECUTABLE} instead of ${CMAKE_CURRENT_BINARY_DIR}/bin/python3")
+endif()
+
+unset(Python3_EXECUTABLE)
+set(Python3_FIND_UNVERSIONED_NAMES NEVER)
+
+# Third search: generic name must NOT be found
+find_package(Python3 REQUIRED COMPONENTS Interpreter)
+
+if (Python3_EXECUTABLE STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/bin/python3")
+ message(FATAL_ERROR "Found unexpected interpreter ${Python3_EXECUTABLE}")
+endif()
diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt
index 929fa4ddf..18688923f 100644
--- a/Tests/Fortran/CMakeLists.txt
+++ b/Tests/Fortran/CMakeLists.txt
@@ -120,7 +120,7 @@ endfunction()
# if the id's match or the compilers are compatible, then
# call the test_fortran_c_interface_module function
if("${CMAKE_Fortran_COMPILER_ID}:${CMAKE_C_COMPILER_ID}" MATCHES
- "(Intel:MSVC|Absoft:GNU)"
+ "(Intel(LLVM)?:MSVC|Absoft:GNU)"
OR ("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "${CMAKE_C_COMPILER_ID}" ))
test_fortran_c_interface_module()
else()
diff --git a/Tests/Fortran/myc.c b/Tests/Fortran/myc.c
index efd9b68aa..1a4d5a495 100644
--- a/Tests/Fortran/myc.c
+++ b/Tests/Fortran/myc.c
@@ -1,6 +1,6 @@
#include "foo.h"
-extern F_test_mod_sub(void);
-extern F_mysub(void);
+extern void F_test_mod_sub(void);
+extern void F_mysub(void);
int myc(void)
{
F_mysub();
diff --git a/Tests/FortranC/CMakeLists.txt b/Tests/FortranC/CMakeLists.txt
index 79c670d6f..83c27296a 100644
--- a/Tests/FortranC/CMakeLists.txt
+++ b/Tests/FortranC/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(FortranC C Fortran)
# Skip this test for compilers not known to be compatible.
diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt
index 637f5816a..b5b5e56e7 100644
--- a/Tests/FortranOnly/CMakeLists.txt
+++ b/Tests/FortranOnly/CMakeLists.txt
@@ -111,7 +111,7 @@ endif()
# Test that with Intel Fortran we always compile with preprocessor
# defines even if splitting the preprocessing and compilation steps.
-if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
+if(CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
add_executable(IntelIfDef IntelIfDef.f)
set_property(TARGET IntelIfDef PROPERTY Fortran_FORMAT FIXED)
target_compile_definitions(IntelIfDef PRIVATE SOME_DEF)
@@ -146,13 +146,13 @@ 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|SunPro|XL)")
+if(test_pp_flags 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}" STREQUAL "Intel;MSVC")
+ 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()
diff --git a/Tests/Fuzzing/README.rst b/Tests/Fuzzing/README.rst
new file mode 100644
index 000000000..a869f9c0d
--- /dev/null
+++ b/Tests/Fuzzing/README.rst
@@ -0,0 +1,8 @@
+The fuzzers in this directory are run continuously through OSS-fuzz.
+All fuzzers are implemented by way of the `libFuzzer engine`_.
+
+The link to the OSS-fuzz integration can be found here: (pending)
+All email addresses in the `project.yaml` file on OSS-fuzz will have access
+to detailed bug reports and will be notified via email if/when bugs are found.
+
+.. _`libFuzzer Engine`: https://llvm.org/docs/LibFuzzer.html
diff --git a/Tests/Fuzzing/xml_parser_fuzzer.cc b/Tests/Fuzzing/xml_parser_fuzzer.cc
new file mode 100644
index 000000000..1faa9180d
--- /dev/null
+++ b/Tests/Fuzzing/xml_parser_fuzzer.cc
@@ -0,0 +1,27 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cmXMLParser.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ char test_file[] = "libfuzzer.xml";
+
+ FILE* fp = fopen(test_file, "wb");
+ if (!fp)
+ return 0;
+ fwrite(data, size, 1, fp);
+ fclose(fp);
+
+ cmXMLParser parser;
+ if (!parser.ParseFile(test_file)) {
+ return 1;
+ }
+
+ remove(test_file);
+ return 0;
+}
diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt
index 1f5b66447..d4c19c79b 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -67,7 +67,11 @@ else()
endif()
# Test escaping of special characters in include directory paths.
-set(special_chars "~@%&{}()!'")
+set(special_chars "~@&{}()!'")
+if(NOT CMAKE_GENERATOR MATCHES "(Unix|MinGW|MSYS) Makefiles")
+ # when compiler is used for dependencies, special characters for make are not escaped
+ string(APPEND special_chars "%")
+endif()
if(NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
# Watcom seems to have no way to encode these characters.
string(APPEND special_chars "#=[]")
diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
index 20bd60196..dee39c826 100644
--- a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(SystemIncludeDirectories)
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
index a9edf9a97..3b994a233 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(TargetIncludeDirectories)
diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt
index ec0a60405..a302c7c28 100644
--- a/Tests/InterfaceLibrary/CMakeLists.txt
+++ b/Tests/InterfaceLibrary/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(InterfaceLibrary)
diff --git a/Tests/JavaNativeHeaders/CMakeLists.txt b/Tests/JavaNativeHeaders/CMakeLists.txt
index 2023d25f9..f3cc89d68 100644
--- a/Tests/JavaNativeHeaders/CMakeLists.txt
+++ b/Tests/JavaNativeHeaders/CMakeLists.txt
@@ -11,7 +11,7 @@ include (UseJava)
# JNI support
find_package(JNI)
-add_jar(B1 D.java GENERATE_NATIVE_HEADERS D1-native)
+add_jar(B1 D.java GENERATE_NATIVE_HEADERS D1-native DESTINATION INSTALL include)
add_jar(E1 E.java GENERATE_NATIVE_HEADERS E1-native)
add_jar(hello4 HelloWorld3.java)
@@ -19,6 +19,13 @@ add_jar(hello4 HelloWorld3.java)
add_library(D SHARED D.cpp E.cpp)
target_link_libraries (D PRIVATE D1-native E1-native)
+install(TARGETS D1-native EXPORT native)
+install(DIRECTORY "$<TARGET_PROPERTY:D1-native,NATIVE_HEADERS_DIRECTORY>/" DESTINATION include)
+install(EXPORT native DESTINATION "${CMAKE_INSTALL_PREFIX}" NAMESPACE D1::)
+
add_test (NAME Java.NativeHeaders
COMMAND "${Java_JAVA_EXECUTABLE}" -Djava.library.path=$<TARGET_FILE_DIR:D> -classpath hello4.jar HelloWorld3)
+
+add_test (NAME Java.ImportNativeHeaders
+ COMMAND "${CMAKE_COMMAND}" "-DNATIVE_HEADERS_IMPORT_DIR=${CMAKE_INSTALL_PREFIX}" -S "${CMAKE_CURRENT_SOURCE_DIR}/Import" -B "${CMAKE_CURRENT_BINARY_DIR}/Import")
diff --git a/Tests/JavaNativeHeaders/Import/CMakeLists.txt b/Tests/JavaNativeHeaders/Import/CMakeLists.txt
new file mode 100644
index 000000000..5486da956
--- /dev/null
+++ b/Tests/JavaNativeHeaders/Import/CMakeLists.txt
@@ -0,0 +1,19 @@
+project(ImportJavaNativeHeaders LANGUAGES NONE)
+
+cmake_minimum_required (VERSION 3.19...3.20)
+set(CMAKE_VERBOSE_MAKEFILE 1)
+
+include(${NATIVE_HEADERS_IMPORT_DIR}/native.cmake)
+
+if(NOT TARGET D1::D1-native)
+ message(FATAL_ERROR "Target 'D1::D1-native' not found.")
+endif()
+
+get_property(incs TARGET D1::D1-native PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+if (NOT incs MATCHES "${NATIVE_HEADERS_IMPORT_DIR}/include")
+ message(FATAL_ERROR "Target 'D1::D1-native', property 'INTERFACE_INCLUDE_DIRECTORIES' badly defined: ${incs}.")
+endif()
+
+if (NOT EXISTS "${NATIVE_HEADERS_IMPORT_DIR}/include/D.h")
+ message(FATAL_ERROR "file '${NATIVE_HEADERS_IMPORT_DIR}/include/D.h' not found.")
+endif()
diff --git a/Tests/LinkDirectory/CMakeLists.txt b/Tests/LinkDirectory/CMakeLists.txt
index c7a270091..d9a8ac8e2 100644
--- a/Tests/LinkDirectory/CMakeLists.txt
+++ b/Tests/LinkDirectory/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(LinkDirectory C)
# Put the subproject source tree in our build tree so it can refer to
diff --git a/Tests/LinkDirectory/External/CMakeLists.txt b/Tests/LinkDirectory/External/CMakeLists.txt
index c87791358..e2229299e 100644
--- a/Tests/LinkDirectory/External/CMakeLists.txt
+++ b/Tests/LinkDirectory/External/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(LinkDirectoryExternal C)
diff --git a/Tests/LinkFlags/CMakeLists.txt b/Tests/LinkFlags/CMakeLists.txt
index 460703542..31ff9b5cf 100644
--- a/Tests/LinkFlags/CMakeLists.txt
+++ b/Tests/LinkFlags/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(LinkFlags C)
string(TOUPPER "${TEST_CONFIG}" TEST_CONFIG_UPPER)
diff --git a/Tests/MFC/CMakeLists.txt b/Tests/MFC/CMakeLists.txt
index 62ff749fe..d17b95543 100644
--- a/Tests/MFC/CMakeLists.txt
+++ b/Tests/MFC/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(mfc_driver)
include(CTest)
diff --git a/Tests/MFC/CMakeLists.txt.in b/Tests/MFC/CMakeLists.txt.in
index 3632e03e2..a600c63cb 100644
--- a/Tests/MFC/CMakeLists.txt.in
+++ b/Tests/MFC/CMakeLists.txt.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(mfc1)
macro(replace_flags var these those)
diff --git a/Tests/MFC/try_compile/CMakeLists.txt b/Tests/MFC/try_compile/CMakeLists.txt
index 8e5d746f6..768d2a639 100644
--- a/Tests/MFC/try_compile/CMakeLists.txt
+++ b/Tests/MFC/try_compile/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(try_compile_mfc)
set(files
diff --git a/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt b/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt
index 27838a40a..41bd6f54f 100644
--- a/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt
+++ b/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt
@@ -6,8 +6,9 @@ foreach(t MultiThreaded SingleThreaded)
foreach(dbg "" Debug)
foreach(dll "" DLL)
set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_${t}${dbg}${dll}")
- if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
- # ifort does not actually define these, so inject them
+ if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel"
+ OR CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM")
+ # ifort and ifx do not actually define these, so inject them
string(REPLACE "-threads" "-threads;-D_MT" "${var}" "${${var}}")
string(REPLACE "-dbglibs" "-dbglibs;-D_DEBUG" "${var}" "${${var}}")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Flang")
diff --git a/Tests/MacRuntimePath/A/CMakeLists.txt b/Tests/MacRuntimePath/A/CMakeLists.txt
index bf937e6c9..c9d3f2c43 100644
--- a/Tests/MacRuntimePath/A/CMakeLists.txt
+++ b/Tests/MacRuntimePath/A/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(MacRuntimePath_A)
# a shared library
diff --git a/Tests/MacRuntimePath/B/CMakeLists.txt b/Tests/MacRuntimePath/B/CMakeLists.txt
index 4317af655..85598c418 100644
--- a/Tests/MacRuntimePath/B/CMakeLists.txt
+++ b/Tests/MacRuntimePath/B/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(MacRuntimePath_B)
include(${MacRuntimePath_B_BINARY_DIR}/../Root/lib/exp.cmake)
diff --git a/Tests/MissingSourceFile/CMakeLists.txt b/Tests/MissingSourceFile/CMakeLists.txt
index a7206c897..b4f00333f 100644
--- a/Tests/MissingSourceFile/CMakeLists.txt
+++ b/Tests/MissingSourceFile/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(MissingSourceFile C)
add_executable(MissingSourceFile DoesNotExist/MissingSourceFile.c)
diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
index cffef5a0b..0cf74bf08 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|XL|XLClang)$")
+ if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
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|XL|XLClang)$")
+ if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang|IntelLLVM)$")
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/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt
index fca5f410f..74f34e4d0 100644
--- a/Tests/ObjectLibrary/CMakeLists.txt
+++ b/Tests/ObjectLibrary/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ObjectLibrary C)
add_subdirectory(A)
diff --git a/Tests/ObjectLibrary/ExportLanguages/CMakeLists.txt b/Tests/ObjectLibrary/ExportLanguages/CMakeLists.txt
index 22c92a7f3..fb0ebc0cc 100644
--- a/Tests/ObjectLibrary/ExportLanguages/CMakeLists.txt
+++ b/Tests/ObjectLibrary/ExportLanguages/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ExportLanguages CXX)
add_library(ExportLanguagesA OBJECT a.cxx)
add_library(ExportLanguagesB STATIC a.c $<TARGET_OBJECTS:ExportLanguagesA>)
diff --git a/Tests/ObjectLibrary/ExportLanguages/ExportLanguagesTest/CMakeLists.txt b/Tests/ObjectLibrary/ExportLanguages/ExportLanguagesTest/CMakeLists.txt
index fc8dd2b78..854479859 100644
--- a/Tests/ObjectLibrary/ExportLanguages/ExportLanguagesTest/CMakeLists.txt
+++ b/Tests/ObjectLibrary/ExportLanguages/ExportLanguagesTest/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(ExportLanguagesTest)
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
index 44194ca1a..5aa2459f9 100644
--- a/Tests/PDBDirectoryAndName/CMakeLists.txt
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
cmake_policy(SET CMP0054 NEW)
project(PDBDirectoryAndName C)
@@ -9,8 +9,9 @@ endif()
# Intel 11.1 does not support /Fd but Intel 14.0 does.
# TODO: Did a version in between these add it?
-if(CMAKE_C_COMPILER_ID STREQUAL Intel AND
- CMAKE_C_COMPILER_VERSION VERSION_LESS 14.0)
+if((CMAKE_C_COMPILER_ID STREQUAL Intel AND
+ CMAKE_C_COMPILER_VERSION VERSION_LESS 14.0) OR
+ CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
set(NO_COMPILE_PDB 1)
endif()
diff --git a/Tests/Plugin/PluginTest/CMakeLists.txt b/Tests/Plugin/PluginTest/CMakeLists.txt
index 5626dbcf7..f00122dcb 100644
--- a/Tests/Plugin/PluginTest/CMakeLists.txt
+++ b/Tests/Plugin/PluginTest/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(PluginTest)
diff --git a/Tests/PositionIndependentTargets/CMakeLists.txt b/Tests/PositionIndependentTargets/CMakeLists.txt
index e79f3b74b..ff779d393 100644
--- a/Tests/PositionIndependentTargets/CMakeLists.txt
+++ b/Tests/PositionIndependentTargets/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(PositionIndependentTargets)
diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt
index bce1b3f07..bf2af645c 100644
--- a/Tests/Preprocess/CMakeLists.txt
+++ b/Tests/Preprocess/CMakeLists.txt
@@ -147,8 +147,13 @@ endif()
# - NMake is okay with just \\\"
# - The XL compiler does not re-escape \\\" when launching an
# internal tool to do preprocessing .
+# - The IntelLLVM C and C++ compiler drivers do not re-escape the \\\" when
+# launching the underlying compiler. FIXME: this bug is expected to be fixed
+# in a future release.
if((PP_NMAKE OR PP_UMAKE) AND
- NOT CMAKE_C_COMPILER_ID STREQUAL "XL")
+ NOT CMAKE_C_COMPILER_ID STREQUAL "XL" AND
+ NOT CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM" AND
+ NOT CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
string(APPEND STRING_EXTRA "\\\"")
endif()
diff --git a/Tests/Qt4Targets/CMakeLists.txt b/Tests/Qt4Targets/CMakeLists.txt
index 2ca11e40b..3ddc3459b 100644
--- a/Tests/Qt4Targets/CMakeLists.txt
+++ b/Tests/Qt4Targets/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(Qt4Targets)
diff --git a/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt b/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt
index d9fc2b07d..17855ffd8 100644
--- a/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt
+++ b/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt
@@ -2,6 +2,15 @@ cmake_minimum_required(VERSION 3.11)
project(AutogenOriginDependsOff)
include("../AutogenCoreTest.cmake")
+get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+# XXX(xcode-per-cfg-src): Enable multi-config code path for Xcode
+# when the Xcode generator supports per-config sources.
+if(_isMultiConfig AND NOT CMAKE_GENERATOR STREQUAL "Xcode")
+ set(mocs_compilation_cpp "mocs_compilation_$<CONFIG>.cpp")
+else()
+ set(mocs_compilation_cpp "mocs_compilation.cpp")
+endif()
+
set(CSD ${CMAKE_CURRENT_SOURCE_DIR})
set(CBD ${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CSD})
@@ -19,7 +28,7 @@ add_custom_command (
add_custom_target ( a_mc
COMMAND ${CMAKE_COMMAND} -E sleep 2
COMMAND ${CMAKE_COMMAND}
- "-DMCF=${CBD}/a_qt_autogen/mocs_compilation.cpp"
+ "-DMCF=${CBD}/a_qt_autogen/${mocs_compilation_cpp}"
"-DCF_IN=${CSD}/a_mc.hpp.in"
"-DCF_OUT=${CBD}/a_mc.hpp"
-P ${CSD}/configure_content.cmake
@@ -51,7 +60,7 @@ add_custom_command (
DEPENDS b_qt_autogen
COMMAND ${CMAKE_COMMAND} -E sleep 2
COMMAND ${CMAKE_COMMAND}
- "-DMCF=${CBD}/b_qt_autogen/mocs_compilation.cpp"
+ "-DMCF=${CBD}/b_qt_autogen/${mocs_compilation_cpp}"
"-DCF_IN=${CSD}/b_mc.cpp.in"
"-DCF_OUT=${CBD}/b_mc.cpp"
-P ${CSD}/configure_content.cmake
diff --git a/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt b/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt
index 81fd8db27..e95c626e7 100644
--- a/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt
+++ b/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt
@@ -13,10 +13,10 @@ include("../AutogenCoreTest.cmake")
set(GAT_SDIR "${CMAKE_CURRENT_SOURCE_DIR}/GAT")
set(GAT_BDIR "${CMAKE_CURRENT_BINARY_DIR}/GAT")
# Files
-set(MCA "sda/sda_autogen/mocs_compilation.cpp")
-set(MCB "sdb/sdb_autogen/mocs_compilation.cpp")
-set(MCC "sdc/sdc_autogen/mocs_compilation.cpp")
-set(MCG "gat_autogen/mocs_compilation.cpp")
+set(MCA "sda/sda_autogen/mocs_compilation*.cpp")
+set(MCB "sdb/sdb_autogen/mocs_compilation*.cpp")
+set(MCC "sdc/sdc_autogen/mocs_compilation*.cpp")
+set(MCG "gat_autogen/mocs_compilation*.cpp")
set(DRA "sda/sda_autogen/*qrc_data.cpp")
set(DRB "sdb/sdb_autogen/*qrc_data.cpp")
diff --git a/Tests/QtAutogen/MocOnly/CMakeLists.txt b/Tests/QtAutogen/MocOnly/CMakeLists.txt
index e109154aa..f4fde58e7 100644
--- a/Tests/QtAutogen/MocOnly/CMakeLists.txt
+++ b/Tests/QtAutogen/MocOnly/CMakeLists.txt
@@ -11,6 +11,18 @@ add_executable(mocOnly
IncA.cpp
IncB.cpp
)
+# XXX(xcode-per-cfg-src): Drop the NO_PER_CONFIG_SOURCES exclusion
+# when the Xcode generator supports per-config sources.
+if(NOT NO_PER_CONFIG_SOURCES)
+ target_sources(mocOnly PRIVATE
+ "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/CfgDebug.cpp>"
+ "$<$<NOT:$<CONFIG:Debug>>:${CMAKE_CURRENT_SOURCE_DIR}/CfgOther.cpp>"
+ )
+ target_compile_definitions(mocOnly PRIVATE
+ "$<$<CONFIG:Debug>:HAVE_CFG_DEBUG>"
+ "$<$<NOT:$<CONFIG:Debug>>:HAVE_CFG_OTHER>"
+ )
+endif()
set_property(TARGET mocOnly PROPERTY AUTOMOC ON)
target_link_libraries(mocOnly ${QT_LIBRARIES})
# Add compile definitions with unusual characters
diff --git a/Tests/QtAutogen/MocOnly/CfgDebug.cpp b/Tests/QtAutogen/MocOnly/CfgDebug.cpp
new file mode 100644
index 000000000..07ca3fb3c
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/CfgDebug.cpp
@@ -0,0 +1,5 @@
+#include "CfgDebug.hpp"
+
+CfgDebug::CfgDebug()
+{
+}
diff --git a/Tests/QtAutogen/MocOnly/CfgDebug.hpp b/Tests/QtAutogen/MocOnly/CfgDebug.hpp
new file mode 100644
index 000000000..3cd90a4f3
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/CfgDebug.hpp
@@ -0,0 +1,15 @@
+#ifndef CFGDEBUG_HPP
+#define CFGDEBUG_HPP
+
+#include <QObject>
+
+/* clang-format off */
+class CfgDebug : public QObject
+{
+ Q_OBJECT
+public:
+ CfgDebug();
+};
+/* clang-format on */
+
+#endif
diff --git a/Tests/QtAutogen/MocOnly/CfgOther.cpp b/Tests/QtAutogen/MocOnly/CfgOther.cpp
new file mode 100644
index 000000000..0ccd43333
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/CfgOther.cpp
@@ -0,0 +1,5 @@
+#include "CfgOther.hpp"
+
+CfgOther::CfgOther()
+{
+}
diff --git a/Tests/QtAutogen/MocOnly/CfgOther.hpp b/Tests/QtAutogen/MocOnly/CfgOther.hpp
new file mode 100644
index 000000000..7cacd52c4
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/CfgOther.hpp
@@ -0,0 +1,15 @@
+#ifndef CFGOTHER_HPP
+#define CFGOTHER_HPP
+
+#include <QObject>
+
+/* clang-format off */
+class CfgOther : public QObject
+{
+ Q_OBJECT
+public:
+ CfgOther();
+};
+/* clang-format on */
+
+#endif
diff --git a/Tests/QtAutogen/MocOnly/main.cpp b/Tests/QtAutogen/MocOnly/main.cpp
index ec8da214e..6c0f6f2af 100644
--- a/Tests/QtAutogen/MocOnly/main.cpp
+++ b/Tests/QtAutogen/MocOnly/main.cpp
@@ -5,6 +5,14 @@
#include "StyleA.hpp"
#include "StyleB.hpp"
+#ifdef HAVE_CFG_DEBUG
+# include "CfgDebug.hpp"
+#endif
+
+#ifdef HAVE_CFG_OTHER
+# include "CfgOther.hpp"
+#endif
+
int main(int argv, char** args)
{
StyleA styleA;
diff --git a/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt b/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt
index 9b32e5951..c53e857e7 100644
--- a/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt
@@ -47,19 +47,38 @@ macro(require_change_not)
endmacro()
-# Initial build
+# Configure the test project
configure_file("${mocBasicSrcDir}/test1a.h.in" "${mocBasicBinDir}/test1.h" COPYONLY)
-try_compile(MOC_RERUN
- "${mocBasicBinDir}"
- "${mocBasicSrcDir}"
- MocBasic
- CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
- "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
- "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+configure_file("${mocBasicSrcDir}/myobject3a.h.in" "${mocBasicBinDir}/myobject3.h" @ONLY)
+if(CMAKE_GENERATOR_INSTANCE)
+ set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}")
+else()
+ set(_D_CMAKE_GENERATOR_INSTANCE "")
+endif()
+execute_process(
+ COMMAND "${CMAKE_COMMAND}" -B "${mocBasicBinDir}" -S "${mocBasicSrcDir}"
+ -G "${CMAKE_GENERATOR}"
+ -A "${CMAKE_GENERATOR_PLATFORM}"
+ -T "${CMAKE_GENERATOR_TOOLSET}"
+ ${_D_CMAKE_GENERATOR_INSTANCE}
+ "-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
)
-if (NOT MOC_RERUN)
- message(FATAL_ERROR "Initial build of mocBasic failed. Output: ${output}")
+if(NOT exit_code EQUAL 0)
+ message(FATAL_ERROR "Initial configuration of mocBasic failed. Output: ${output}")
+endif()
+
+# Initial build
+execute_process(
+ COMMAND "${CMAKE_COMMAND}" --build "${mocBasicBinDir}"
+ RESULT_VARIABLE exit_code
+ OUTPUT_VARIABLE output
+)
+if(NOT exit_code EQUAL 0)
+ message(FATAL_ERROR "Initial build of mocBasic failed. Output: ${output}")
endif()
# Get name of the output binary
@@ -100,3 +119,43 @@ message(STATUS "Changing nothing for no MOC re-run")
rebuild(3)
acquire_timestamp(After)
require_change_not()
+
+
+# - Ensure that the timestamp will change
+# - Remove Q_OBJECT from header
+# - Rebuild
+acquire_timestamp(Before)
+sleep()
+message(STATUS "Remove Q_OBJECT from header file for a MOC re-run")
+configure_file("${mocBasicSrcDir}/test1c.h.in" "${mocBasicBinDir}/test1.h" COPYONLY)
+sleep()
+rebuild(4)
+acquire_timestamp(After)
+require_change()
+
+
+# - Ensure that the timestamp will change
+# - Add Q_OBJECT to header again
+# - Rebuild
+acquire_timestamp(Before)
+sleep()
+message(STATUS "Add Q_OBJECT to test1.h for a MOC re-run")
+configure_file("${mocBasicSrcDir}/test1a.h.in" "${mocBasicBinDir}/test1.h" COPYONLY)
+sleep()
+rebuild(5)
+acquire_timestamp(After)
+require_change()
+
+
+# - Ensure that the timestamp will change
+# - Add Q_OBJECT to MyObject3
+# - Rebuild
+acquire_timestamp(Before)
+sleep()
+message(STATUS "Add Q_OBJECT to myobject3.h file for a MOC re-run")
+set(CLASS_CONTENT "Q_OBJECT")
+configure_file("${mocBasicSrcDir}/myobject3a.h.in" "${mocBasicBinDir}/myobject3.h" @ONLY)
+sleep()
+rebuild(6)
+acquire_timestamp(After)
+require_change()
diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt b/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt
index 6a9f5507c..42f2f57c5 100644
--- a/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt
@@ -13,10 +13,15 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
add_executable(mocBasic
${CMAKE_CURRENT_BINARY_DIR}/test1.h
+ ${CMAKE_CURRENT_BINARY_DIR}/myobject3.h
${CMAKE_CURRENT_BINARY_DIR}/main.cpp
+ plainobject.cpp
res1.qrc
)
-target_include_directories(mocBasic PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+target_include_directories(mocBasic PRIVATE
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
target_link_libraries(mocBasic ${QT_QTCORE_TARGET})
# Write target name to text file
add_custom_command(TARGET mocBasic POST_BUILD COMMAND
diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/main.cpp.in b/Tests/QtAutogen/RerunMocBasic/MocBasic/main.cpp.in
index 9d7ea37ae..5accfd67a 100644
--- a/Tests/QtAutogen/RerunMocBasic/MocBasic/main.cpp.in
+++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/main.cpp.in
@@ -1,4 +1,5 @@
#include "test1.h"
+#include "plainobject.h"
extern int qInitResources_res1();
@@ -16,6 +17,7 @@ int main()
Test1 test1;
Test2 test2;
+ PlainObject plainObject;
return 0;
}
diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/myobject3a.h.in b/Tests/QtAutogen/RerunMocBasic/MocBasic/myobject3a.h.in
new file mode 100644
index 000000000..d62c31465
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/myobject3a.h.in
@@ -0,0 +1,13 @@
+#ifndef MYOBJECT3_H
+#define MYOBJECT3_H
+
+#include <qobject.h>
+
+class MyObject3 : public QObject
+{
+ @CLASS_CONTENT@
+public:
+ MyObject3() {}
+};
+
+#endif
diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.cpp b/Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.cpp
new file mode 100644
index 000000000..0ca785ebd
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.cpp
@@ -0,0 +1,12 @@
+#include "plainobject.h"
+
+#include "myobject3.h"
+
+PlainObject::PlainObject()
+{
+}
+
+void PlainObject::doSomething()
+{
+ MyObject3 obj3;
+}
diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.h b/Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.h
new file mode 100644
index 000000000..80378582b
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/plainobject.h
@@ -0,0 +1,12 @@
+#ifndef PLAINOBJECT_H
+#define PLAINOBJECT_H
+
+// Class that is plain C++, no Qt involved.
+class PlainObject
+{
+public:
+ PlainObject();
+ void doSomething();
+};
+
+#endif
diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/test1c.h.in b/Tests/QtAutogen/RerunMocBasic/MocBasic/test1c.h.in
new file mode 100644
index 000000000..d0b9868f1
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/test1c.h.in
@@ -0,0 +1,6 @@
+#include <QObject>
+class Test1
+{
+public:
+ void onTst1() {}
+};
diff --git a/Tests/QtAutogen/TestMacros.cmake b/Tests/QtAutogen/TestMacros.cmake
index 0e2718807..1024996ab 100644
--- a/Tests/QtAutogen/TestMacros.cmake
+++ b/Tests/QtAutogen/TestMacros.cmake
@@ -1,12 +1,19 @@
# Autogen build options
set(Autogen_BUILD_OPTIONS "-DQT_TEST_VERSION=${QT_TEST_VERSION}")
-if(NOT _isMultiConfig) # Set in Tests/CMakeLists.txt
+if(_isMultiConfig) # Set in Tests/CMakeLists.txt
+ list(APPEND Autogen_CTEST_OPTIONS --build-config $<CONFIGURATION>)
+else()
list(APPEND Autogen_BUILD_OPTIONS "-DCMAKE_BUILD_TYPE=$<CONFIGURATION>")
endif()
list(APPEND Autogen_BUILD_OPTIONS
"-DCMAKE_AUTOGEN_VERBOSE=1"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
)
+# XXX(xcode-per-cfg-src): Drop the NO_PER_CONFIG_SOURCES exclusion
+# when the Xcode generator supports per-config sources.
+if(CMAKE_GENERATOR STREQUAL "Xcode")
+ list(APPEND Autogen_BUILD_OPTIONS -DNO_PER_CONFIG_SOURCES=1)
+endif()
# A macro to add a QtAutogen test
macro(ADD_AUTOGEN_TEST NAME)
@@ -30,6 +37,7 @@ macro(ADD_AUTOGEN_TEST NAME)
"${_BuildDir}"
${build_generator_args}
--build-project ${NAME}
+ ${Autogen_CTEST_OPTIONS}
--build-exe-dir "${_BuildDir}"
--force-new-ctest-process
--build-options ${build_options} ${Autogen_BUILD_OPTIONS}
diff --git a/Tests/QtAutomocNoQt/CMakeLists.txt b/Tests/QtAutomocNoQt/CMakeLists.txt
index b26e47117..655f12bef 100644
--- a/Tests/QtAutomocNoQt/CMakeLists.txt
+++ b/Tests/QtAutomocNoQt/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(QtAutomocNoQt)
diff --git a/Tests/RunCMake/ABI/C-stdout.txt b/Tests/RunCMake/ABI/C-stdout.txt
new file mode 100644
index 000000000..5b67b8476
--- /dev/null
+++ b/Tests/RunCMake/ABI/C-stdout.txt
@@ -0,0 +1 @@
+-- Check if the system is big endian
diff --git a/Tests/RunCMake/ABI/C.cmake b/Tests/RunCMake/ABI/C.cmake
new file mode 100644
index 000000000..92f5da474
--- /dev/null
+++ b/Tests/RunCMake/ABI/C.cmake
@@ -0,0 +1,22 @@
+enable_language(C)
+if(NOT CMAKE_C_BYTE_ORDER MATCHES "^(BIG_ENDIAN|LITTLE_ENDIAN)$")
+ if(CMAKE_OSX_ARCHITECTURES MATCHES ";ppc|ppc;")
+ return()
+ endif()
+ message(FATAL_ERROR "CMAKE_C_BYTE_ORDER has unexpected value '${CMAKE_C_BYTE_ORDER}'")
+endif()
+
+include(TestBigEndian)
+test_big_endian(IS_BIG_ENDIAN)
+if(IS_BIG_ENDIAN AND NOT CMAKE_C_BYTE_ORDER STREQUAL "BIG_ENDIAN")
+ message(FATAL_ERROR "test_big_endian result does not match ABI result")
+endif()
+
+# Test legacy check.
+set(byte_order "${CMAKE_C_BYTE_ORDER}")
+unset(CMAKE_C_BYTE_ORDER)
+include(TestBigEndian)
+test_big_endian(IS_BIG)
+if(IS_BIG AND NOT byte_order STREQUAL "BIG_ENDIAN")
+ message(FATAL_ERROR "test_big_endian result does not match ABI result")
+endif()
diff --git a/Tests/RunCMake/ABI/CMakeLists.txt b/Tests/RunCMake/ABI/CMakeLists.txt
new file mode 100644
index 000000000..ab1a20c7e
--- /dev/null
+++ b/Tests/RunCMake/ABI/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/ABI/CUDA.cmake b/Tests/RunCMake/ABI/CUDA.cmake
new file mode 100644
index 000000000..8ede3a94a
--- /dev/null
+++ b/Tests/RunCMake/ABI/CUDA.cmake
@@ -0,0 +1,13 @@
+enable_language(CUDA)
+if(NOT CMAKE_CUDA_BYTE_ORDER MATCHES "^(BIG_ENDIAN|LITTLE_ENDIAN)$")
+ if(CMAKE_OSX_ARCHITECTURES MATCHES ";ppc|ppc;")
+ return()
+ endif()
+ message(FATAL_ERROR "CMAKE_CUDA_BYTE_ORDER has unexpected value '${CMAKE_CUDA_BYTE_ORDER}'")
+endif()
+
+include(TestBigEndian)
+test_big_endian(IS_BIG_ENDIAN)
+if(IS_BIG_ENDIAN AND NOT CMAKE_CUDA_BYTE_ORDER STREQUAL "BIG_ENDIAN")
+ message(FATAL_ERROR "test_big_endian result does not match ABI result")
+endif()
diff --git a/Tests/RunCMake/ABI/CXX-stdout.txt b/Tests/RunCMake/ABI/CXX-stdout.txt
new file mode 100644
index 000000000..5b67b8476
--- /dev/null
+++ b/Tests/RunCMake/ABI/CXX-stdout.txt
@@ -0,0 +1 @@
+-- Check if the system is big endian
diff --git a/Tests/RunCMake/ABI/CXX.cmake b/Tests/RunCMake/ABI/CXX.cmake
new file mode 100644
index 000000000..231000262
--- /dev/null
+++ b/Tests/RunCMake/ABI/CXX.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+if(NOT CMAKE_CXX_BYTE_ORDER MATCHES "^(BIG_ENDIAN|LITTLE_ENDIAN)$")
+ if(CMAKE_OSX_ARCHITECTURES MATCHES ";ppc|ppc;")
+ return()
+ endif()
+ message(FATAL_ERROR "CMAKE_CXX_BYTE_ORDER has unexpected value '${CMAKE_CXX_BYTE_ORDER}'")
+endif()
+
+include(TestBigEndian)
+test_big_endian(IS_BIG_ENDIAN)
+if(IS_BIG_ENDIAN AND NOT CMAKE_CXX_BYTE_ORDER STREQUAL "BIG_ENDIAN")
+ message(FATAL_ERROR "test_big_endian result does not match ABI result")
+endif()
+
+# Test legacy check.
+set(byte_order "${CMAKE_CXX_BYTE_ORDER}")
+unset(CMAKE_CXX_BYTE_ORDER)
+include(TestBigEndian)
+test_big_endian(IS_BIG)
+if(IS_BIG AND NOT byte_order STREQUAL "BIG_ENDIAN")
+ message(FATAL_ERROR "test_big_endian result does not match ABI result")
+endif()
diff --git a/Tests/RunCMake/ABI/OBJC.cmake b/Tests/RunCMake/ABI/OBJC.cmake
new file mode 100644
index 000000000..ab6745908
--- /dev/null
+++ b/Tests/RunCMake/ABI/OBJC.cmake
@@ -0,0 +1,13 @@
+enable_language(OBJC)
+if(NOT CMAKE_OBJC_BYTE_ORDER MATCHES "^(BIG_ENDIAN|LITTLE_ENDIAN)$")
+ if(CMAKE_OSX_ARCHITECTURES MATCHES ";ppc|ppc;")
+ return()
+ endif()
+ message(FATAL_ERROR "CMAKE_OBJC_BYTE_ORDER has unexpected value '${CMAKE_OBJC_BYTE_ORDER}'")
+endif()
+
+include(TestBigEndian)
+test_big_endian(IS_BIG_ENDIAN)
+if(IS_BIG_ENDIAN AND NOT CMAKE_OBJC_BYTE_ORDER STREQUAL "BIG_ENDIAN")
+ message(FATAL_ERROR "test_big_endian result does not match ABI result")
+endif()
diff --git a/Tests/RunCMake/ABI/OBJCXX.cmake b/Tests/RunCMake/ABI/OBJCXX.cmake
new file mode 100644
index 000000000..41a719e2b
--- /dev/null
+++ b/Tests/RunCMake/ABI/OBJCXX.cmake
@@ -0,0 +1,13 @@
+enable_language(OBJCXX)
+if(NOT CMAKE_OBJCXX_BYTE_ORDER MATCHES "^(BIG_ENDIAN|LITTLE_ENDIAN)$")
+ if(CMAKE_OSX_ARCHITECTURES MATCHES ";ppc|ppc;")
+ return()
+ endif()
+ message(FATAL_ERROR "CMAKE_OBJCXX_BYTE_ORDER has unexpected value '${CMAKE_OBJCXX_BYTE_ORDER}'")
+endif()
+
+include(TestBigEndian)
+test_big_endian(IS_BIG_ENDIAN)
+if(IS_BIG_ENDIAN AND NOT CMAKE_OBJCXX_BYTE_ORDER STREQUAL "BIG_ENDIAN")
+ message(FATAL_ERROR "test_big_endian result does not match ABI result")
+endif()
diff --git a/Tests/RunCMake/ABI/RunCMakeTest.cmake b/Tests/RunCMake/ABI/RunCMakeTest.cmake
new file mode 100644
index 000000000..d9eabb753
--- /dev/null
+++ b/Tests/RunCMake/ABI/RunCMakeTest.cmake
@@ -0,0 +1,15 @@
+include(RunCMake)
+
+run_cmake(C)
+run_cmake(CXX)
+
+if(APPLE)
+ run_cmake(OBJC)
+ run_cmake(OBJCXX)
+endif()
+
+if(CMake_TEST_CUDA)
+ run_cmake(CUDA)
+endif()
+
+run_cmake(TestBigEndian-NoLang)
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-result.txt b/Tests/RunCMake/ABI/TestBigEndian-NoLang-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/CommandLine/E_server-arg-result.txt
+++ b/Tests/RunCMake/ABI/TestBigEndian-NoLang-result.txt
diff --git a/Tests/RunCMake/ABI/TestBigEndian-NoLang-stderr.txt b/Tests/RunCMake/ABI/TestBigEndian-NoLang-stderr.txt
new file mode 100644
index 000000000..d0aa89997
--- /dev/null
+++ b/Tests/RunCMake/ABI/TestBigEndian-NoLang-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Error at [^
+]*/Modules/TestBigEndian.cmake:[0-9]+ \(message\):
+ TEST_BIG_ENDIAN needs either C or CXX language enabled
+Call Stack \(most recent call first\):
+ [^
+]*/Modules/TestBigEndian.cmake:[0-9]+ \(__TEST_BIG_ENDIAN_LEGACY_IMPL\)
+ TestBigEndian-NoLang.cmake:[0-9]+ \(test_big_endian\)
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/ABI/TestBigEndian-NoLang.cmake b/Tests/RunCMake/ABI/TestBigEndian-NoLang.cmake
new file mode 100644
index 000000000..8c102017d
--- /dev/null
+++ b/Tests/RunCMake/ABI/TestBigEndian-NoLang.cmake
@@ -0,0 +1,2 @@
+include(TestBigEndian)
+test_big_endian(var)
diff --git a/Tests/RunCMake/Android/RunCMakeTest.cmake b/Tests/RunCMake/Android/RunCMakeTest.cmake
index c4b1a00dd..aa0cf4d92 100644
--- a/Tests/RunCMake/Android/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Android/RunCMakeTest.cmake
@@ -103,6 +103,13 @@ foreach(ndk IN LISTS TEST_ANDROID_NDK)
set(ndk_arg)
endif()
+ set(RunCMake_TEST_OPTIONS
+ -DCMAKE_SYSTEM_NAME=Android
+ -DCMAKE_FIND_ROOT_PATH=/tmp
+ ${ndk_arg}
+ )
+ run_cmake(ndk-search-order)
+
# Test failure cases.
message(STATUS "ndk='${ndk}'")
if(RunCMake_GENERATOR MATCHES "Visual Studio")
diff --git a/Tests/RunCMake/Android/common.cmake b/Tests/RunCMake/Android/common.cmake
index 32412aa84..7c80a0490 100644
--- a/Tests/RunCMake/Android/common.cmake
+++ b/Tests/RunCMake/Android/common.cmake
@@ -5,10 +5,21 @@ if(NOT ANDROID)
message(SEND_ERROR "CMake variable 'ANDROID' is not set to a true value.")
endif()
-foreach(f
- "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ar${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
+set(files
+ "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ar${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
+ )
+if(NOT CMAKE_ANDROID_NDK_VERSION VERSION_GREATER_EQUAL 22)
+ list(APPEND files
"${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ld${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
)
+endif()
+if(NOT CMAKE_ANDROID_NDK_VERSION VERSION_GREATER_EQUAL 19)
+ list(APPEND files
+ "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}"
+ "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}g++${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
+ )
+endif()
+foreach(f IN LISTS files)
if(NOT EXISTS "${f}")
message(SEND_ERROR "Expected file does not exist:\n \"${f}\"")
endif()
diff --git a/Tests/RunCMake/Android/ndk-search-order.cmake b/Tests/RunCMake/Android/ndk-search-order.cmake
new file mode 100644
index 000000000..498d775c4
--- /dev/null
+++ b/Tests/RunCMake/Android/ndk-search-order.cmake
@@ -0,0 +1,17 @@
+if(NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+ return()
+endif()
+
+find_library(LIBDL dl)
+if(NOT LIBDL)
+ message(FATAL_ERROR "libdl not found.")
+endif()
+
+if(LIBDL MATCHES ".a$")
+ message(FATAL_ERROR "found libdl.a")
+endif()
+
+find_program(CLANG clang)
+if(NOT CLANG)
+ message(FATAL_ERROR "clang not found")
+endif()
diff --git a/Tests/RunCMake/ArtifactOutputDirs/ArtifactOutputDirs.cmake b/Tests/RunCMake/ArtifactOutputDirs/ArtifactOutputDirs.cmake
new file mode 100644
index 000000000..d0accd7de
--- /dev/null
+++ b/Tests/RunCMake/ArtifactOutputDirs/ArtifactOutputDirs.cmake
@@ -0,0 +1,27 @@
+enable_language(C)
+
+if(CMAKE_IMPORT_LIBRARY_SUFFIX)
+ set(expect_dll 1)
+else()
+ set(expect_dll 0)
+endif()
+
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/$<IF:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>,rtlib,rtbin>")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/$<IF:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>,sharedlib,others>")
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/$<IF:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>,staticlib,others>")
+
+add_executable(exe_tgt main.c)
+add_library(shared_tgt SHARED lib.c)
+add_library(static_tgt STATIC lib.c)
+
+add_custom_target(checkDirs ALL
+ COMMAND ${CMAKE_COMMAND}
+ -Dartifact_path=${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>
+ -Dexe_name=$<TARGET_FILE_NAME:exe_tgt>
+ -Dshared_name=$<TARGET_FILE_NAME:shared_tgt>
+ -Dstatic_name=$<TARGET_FILE_NAME:static_tgt>
+ -Dexpect_dll=${expect_dll}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
+ )
+
+add_dependencies(checkDirs exe_tgt shared_tgt static_tgt)
diff --git a/Tests/RunCMake/ArtifactOutputDirs/CMakeLists.txt b/Tests/RunCMake/ArtifactOutputDirs/CMakeLists.txt
new file mode 100644
index 000000000..ab1a20c7e
--- /dev/null
+++ b/Tests/RunCMake/ArtifactOutputDirs/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/ArtifactOutputDirs/RunCMakeTest.cmake b/Tests/RunCMake/ArtifactOutputDirs/RunCMakeTest.cmake
new file mode 100644
index 000000000..1bf84380d
--- /dev/null
+++ b/Tests/RunCMake/ArtifactOutputDirs/RunCMakeTest.cmake
@@ -0,0 +1,19 @@
+include(RunCMake)
+
+function(run_cmake_and_verify_after_build case)
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${case}-build")
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
+ else()
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+ run_cmake(${case})
+ run_cmake_command("${case}-build" ${CMAKE_COMMAND} --build .)
+ unset(RunCMake_TEST_NO_CLEAN)
+ unset(RunCMake_TEST_BINARY_DIR)
+endfunction()
+
+run_cmake_and_verify_after_build(ArtifactOutputDirs)
diff --git a/Tests/RunCMake/ArtifactOutputDirs/check.cmake b/Tests/RunCMake/ArtifactOutputDirs/check.cmake
new file mode 100644
index 000000000..ca37eba53
--- /dev/null
+++ b/Tests/RunCMake/ArtifactOutputDirs/check.cmake
@@ -0,0 +1,21 @@
+set(expected ${artifact_path}/rtbin/${exe_name})
+if(NOT EXISTS "${expected}")
+ message(SEND_ERROR "executable artifact not created in the expected path:\n ${expected}")
+endif()
+
+set(expected ${artifact_path}/staticlib/${static_name})
+if(NOT EXISTS "${expected}")
+ message(SEND_ERROR "static artifact not created in the expected path:\n ${expected}")
+endif()
+
+if(expect_dll)
+ set(expected ${artifact_path}/rtlib/${shared_name})
+ if(NOT EXISTS "${expected}")
+ message(SEND_ERROR "dll artifact not created in the expected path:\n ${expected}")
+ endif()
+else()
+ set(expected ${artifact_path}/sharedlib/${shared_name})
+ if(NOT EXISTS "${expected}")
+ message(SEND_ERROR "shared artifact not created in the expected path:\n ${expected}")
+ endif()
+endif()
diff --git a/Tests/RunCMake/TargetObjects/empty.cpp b/Tests/RunCMake/ArtifactOutputDirs/lib.c
index 4086dcc87..22373f194 100644
--- a/Tests/RunCMake/TargetObjects/empty.cpp
+++ b/Tests/RunCMake/ArtifactOutputDirs/lib.c
@@ -1,4 +1,4 @@
-int empty()
+int func(void)
{
return 0;
}
diff --git a/Tests/Server/buildsystem1/foo.cpp b/Tests/RunCMake/ArtifactOutputDirs/main.c
index 7f39d7175..8488f4e58 100644
--- a/Tests/Server/buildsystem1/foo.cpp
+++ b/Tests/RunCMake/ArtifactOutputDirs/main.c
@@ -1,5 +1,4 @@
-
-int foo()
+int main(void)
{
return 0;
}
diff --git a/Tests/RunCMake/BuildDepends/CMakeLists.txt b/Tests/RunCMake/BuildDepends/CMakeLists.txt
index 74b3ff8de..99f238b9e 100644
--- a/Tests/RunCMake/BuildDepends/CMakeLists.txt
+++ b/Tests/RunCMake/BuildDepends/CMakeLists.txt
@@ -1,3 +1,3 @@
cmake_minimum_required(VERSION 3.3)
project(${RunCMake_TEST} NONE)
-include(${RunCMake_TEST}.cmake)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
diff --git a/Tests/RunCMake/BuildDepends/CompilerDependencies.cmake b/Tests/RunCMake/BuildDepends/CompilerDependencies.cmake
new file mode 100644
index 000000000..8a9e6008b
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CompilerDependencies.cmake
@@ -0,0 +1,46 @@
+enable_language(C)
+
+add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c)
+
+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\"
+ \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.h\"
+ )
+set(check_exes
+ \"$<TARGET_FILE:main>\"
+ )
+
+if (check_step EQUAL 2)
+ include(\"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.cmake\")
+ if (NOT CMAKE_DEPEND_INFO_FILES)
+ set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPEND_INFO_FILES not found.\")
+ else()
+ include(\"${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_DEPEND_INFO_FILES}\")
+ if (NOT CMAKE_DEPENDS_DEPENDENCY_FILES)
+ set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPENDS_DEPENDENCY_FILES not found.\")
+ else()
+ list(GET CMAKE_DEPENDS_DEPENDENCY_FILES 1 OBJECT_FILE)
+ list(GET CMAKE_DEPENDS_DEPENDENCY_FILES 3 DEP_FILE)
+ if (NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\")
+ set(RunCMake_TEST_FAILED \"File \${DEP_FILE} not found.\")
+ else()
+ set (TARGET_DEP_FILE \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\")
+ cmake_path(REPLACE_FILENAME TARGET_DEP_FILE \"compiler_depend.make\")
+ file(READ \"\${TARGET_DEP_FILE}\" DEPENDS_CONTENT)
+ if (WIN32)
+ string (REPLACE \"\\\\\" \"/\" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
+ string (TOLOWER \"\${DEPENDS_CONTENT}\" DEPENDS_CONTENT)
+ string (TOLOWER \"\${OBJECT_FILE}\" OBJECT_FILE)
+ else()
+ string(REPLACE \"\\\\ \" \" \" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
+ endif()
+ if(NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c\"
+ OR NOT DEPENDS_CONTENT MATCHES \"main.h\")
+ set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated.\")
+ endif()
+ endif()
+ endif()
+ endif()
+endif()
+")
diff --git a/Tests/RunCMake/BuildDepends/CompilerDependencies.step1.cmake b/Tests/RunCMake/BuildDepends/CompilerDependencies.step1.cmake
new file mode 100644
index 000000000..1da2593cd
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CompilerDependencies.step1.cmake
@@ -0,0 +1,9 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.h" [[
+#define COUNT 1
+]])
+
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c" [[
+#include "main.h"
+
+int main(void) { return COUNT; }
+]])
diff --git a/Tests/RunCMake/BuildDepends/CompilerDependencies.step2.cmake b/Tests/RunCMake/BuildDepends/CompilerDependencies.step2.cmake
new file mode 100644
index 000000000..e983665f8
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CompilerDependencies.step2.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.h" [[
+#define COUNT 2
+]])
diff --git a/Tests/RunCMake/ExternalProject/IncludeScope-Add-result.txt b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/ExternalProject/IncludeScope-Add-result.txt
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-result.txt
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt
new file mode 100644
index 000000000..cddea3c18
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at CustomCommandDependencies-BadArgs.cmake:[0-9]+ \(add_custom_command\):
+ add_custom_command IMPLICIT_DEPENDS and DEPFILE can not both be specified.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake
new file mode 100644
index 000000000..91ee3383e
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+add_custom_command(OUTPUT main.c
+ DEPFILE main.c.d
+ IMPLICIT_DEPENDS C main.c.in
+ COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+add_custom_target(mainc ALL DEPENDS main.c)
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake
new file mode 100644
index 000000000..28bbf114f
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake
@@ -0,0 +1,73 @@
+enable_language(C)
+
+add_custom_command(OUTPUT main.c
+ DEPFILE main.c.d
+ COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+add_custom_target(mainc ALL DEPENDS main.c)
+
+add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c)
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+cmake_minimum_required(VERSION 3.19)
+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>\"
+ )
+
+if (check_step EQUAL 2)
+ include(\"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.cmake\")
+ if (NOT CMAKE_DEPEND_INFO_FILES)
+ set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPEND_INFO_FILES not found.\")
+ else()
+ foreach(DEPEND_INFO_FILE IN LISTS CMAKE_DEPEND_INFO_FILES)
+ include(\"${CMAKE_CURRENT_BINARY_DIR}/\${DEPEND_INFO_FILE}\")
+ if (NOT CMAKE_DEPENDS_DEPENDENCY_FILES)
+ set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPENDS_DEPENDENCY_FILES not found.\")
+ else()
+ list(LENGTH CMAKE_DEPENDS_DEPENDENCY_FILES DEPENDENCY_FILES_SIZE)
+ math(EXPR STOP_INDEX \"\${DEPENDENCY_FILES_SIZE} - 1\")
+ foreach(INDEX RANGE 0 \${STOP_INDEX} 4)
+ math(EXPR OBJECT_INDEX \"\${INDEX} + 1\")
+ math(EXPR FORMAT_INDEX \"\${INDEX} + 2\")
+ math(EXPR DEP_INDEX \"\${INDEX} + 3\")
+ list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${OBJECT_INDEX} OBJECT_FILE)
+ list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${FORMAT_INDEX} DEP_FORMAT)
+ list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${DEP_INDEX} DEP_FILE)
+ if (NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\")
+ set(RunCMake_TEST_FAILED \"File \${DEP_FILE} not found.\")
+ else()
+ cmake_path(APPEND TARGET_DEP_FILE \"${CMAKE_CURRENT_BINARY_DIR}\" \"\${DEPEND_INFO_FILE}\")
+ cmake_path(REPLACE_FILENAME TARGET_DEP_FILE \"compiler_depend.make\")
+ file(READ \"\${TARGET_DEP_FILE}\" DEPENDS_CONTENT)
+ if (WIN32)
+ string (REPLACE \"\\\\\" \"/\" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
+ string (TOLOWER \"\${DEPENDS_CONTENT}\" DEPENDS_CONTENT)
+ string (TOLOWER \"\${OBJECT_FILE}\" OBJECT_FILE)
+ else()
+ string(REPLACE \"\\\\ \" \" \" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
+ endif()
+ if(DEPEND_INFO_FILE MATCHES \"main\\\\.dir\")
+ if (DEP_FORMAT STREQUAL \"gcc\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c\")
+ set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
+ endif()
+ if (DEP_FORMAT STREQUAL \"custom\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\")
+ set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
+ endif()
+ else()
+ if (NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\")
+ set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
+ endif()
+ endif()
+ endif()
+ endforeach()
+ endif()
+ endforeach()
+ endif()
+endif()
+")
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step1.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step1.cmake
new file mode 100644
index 000000000..87576ebf0
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.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/CustomCommandDependencies.step2.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step2.cmake
new file mode 100644
index 000000000..69b21b831
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.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/CustomCommandDepfile.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake
new file mode 100644
index 000000000..01eac91dd
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake
@@ -0,0 +1,61 @@
+cmake_policy(SET CMP0116 NEW)
+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"
+ )
+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"
+ )
+add_executable(topexe "${CMAKE_CURRENT_BINARY_DIR}/topexe.c")
+
+add_custom_command(
+ OUTPUT toplib.c
+ DEPFILE toplib.c.d
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=toplib.c -DINFILE=toplibdep.txt -DDEPFILE=toplib.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
+ )
+add_library(toplib STATIC toplib.c)
+
+add_subdirectory(DepfileSubdir)
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+function(check_exists file)
+ if(NOT EXISTS \"\${file}\")
+ string(APPEND RunCMake_TEST_FAILED \"\${file} does not exist\\n\")
+ endif()
+ set(RunCMake_TEST_FAILED \"\${RunCMake_TEST_FAILED}\" PARENT_SCOPE)
+endfunction()
+
+function(check_not_exists file)
+ if(EXISTS \"\${file}\")
+ string(APPEND RunCMake_TEST_FAILED \"\${file} exists\\n\")
+ endif()
+ set(RunCMake_TEST_FAILED \"\${RunCMake_TEST_FAILED}\" PARENT_SCOPE)
+endfunction()
+
+set(check_pairs
+ \"${CMAKE_BINARY_DIR}/topcc.c|${CMAKE_BINARY_DIR}/topccdep.txt\"
+ \"$<TARGET_FILE:topexe>|${CMAKE_BINARY_DIR}/topexedep.txt\"
+ \"$<TARGET_FILE:toplib>|${CMAKE_BINARY_DIR}/toplibdep.txt\"
+ \"${CMAKE_BINARY_DIR}/DepfileSubdir/subcc.c|${CMAKE_BINARY_DIR}/DepfileSubdir/subccdep.txt\"
+ \"$<TARGET_FILE:subexe>|${CMAKE_BINARY_DIR}/DepfileSubdir/subexedep.txt\"
+ \"$<TARGET_FILE:sublib>|${CMAKE_BINARY_DIR}/DepfileSubdir/sublibdep.txt\"
+ )
+
+if(check_step EQUAL 3)
+ list(APPEND check_pairs
+ \"${CMAKE_BINARY_DIR}/step3.timestamp|${CMAKE_BINARY_DIR}/topcc.c\"
+ \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:topexe>\"
+ \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:toplib>\"
+ \"${CMAKE_BINARY_DIR}/step3.timestamp|${CMAKE_BINARY_DIR}/DepfileSubdir/subcc.c\"
+ \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:subexe>\"
+ \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:sublib>\"
+ )
+endif()
+")
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step1.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step1.cmake
new file mode 100644
index 000000000..0dfe78e70
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step1.cmake
@@ -0,0 +1,10 @@
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir")
+file(REMOVE "${RunCMake_TEST_BINARY_DIR}/../sublib.c")
+file(REMOVE "${RunCMake_TEST_BINARY_DIR}/step3.timestamp")
+
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topccdep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topexedep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/toplibdep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subccdep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subexedep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/sublibdep.txt")
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step2.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step2.cmake
new file mode 100644
index 000000000..c7115145a
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step2.cmake
@@ -0,0 +1,6 @@
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topccdep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topexedep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/toplibdep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subccdep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subexedep.txt")
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/sublibdep.txt")
diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step3.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step3.cmake
new file mode 100644
index 000000000..c55ccc144
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step3.cmake
@@ -0,0 +1 @@
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/step3.timestamp")
diff --git a/Tests/RunCMake/BuildDepends/DepfileSubdir/CMakeLists.txt b/Tests/RunCMake/BuildDepends/DepfileSubdir/CMakeLists.txt
new file mode 100644
index 000000000..f131751cd
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/DepfileSubdir/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_policy(SET CMP0116 NEW)
+
+add_custom_command(
+ OUTPUT subcc.c
+ DEPFILE subcc.c.d
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/subcc.c -DINFILE=subccdep.txt -DDEPFILE=subcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake"
+ )
+add_custom_target(subcc ALL DEPENDS subcc.c)
+
+add_custom_command(
+ OUTPUT subexe.c
+ DEPFILE subexe.c.d
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=subexe.c -DINFILE=subexedep.txt -DDEPFILE=subexe.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake"
+ )
+add_executable(subexe subexe.c)
+
+add_custom_command(
+ OUTPUT ${CMAKE_BINARY_DIR}/../sublib.c
+ DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/sublib.c.d
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_BINARY_DIR}/../sublib.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/sublibdep.txt" -DDEPFILE=sublib.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake"
+ )
+add_library(sublib STATIC "${CMAKE_BINARY_DIR}/../sublib.c")
diff --git a/Tests/RunCMake/BuildDepends/GenerateDepFile.cmake b/Tests/RunCMake/BuildDepends/GenerateDepFile.cmake
new file mode 100644
index 000000000..f7d0f134c
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/GenerateDepFile.cmake
@@ -0,0 +1,6 @@
+file(READ "${INFILE}" INCONTENT)
+file(WRITE "${OUTFILE}" "${INCONTENT}")
+
+string(REPLACE [[ ]] [[\ ]] OUTFILE "${OUTFILE}")
+string(REPLACE [[ ]] [[\ ]] INFILE "${INFILE}")
+file(WRITE "${DEPFILE}" "${OUTFILE}: ${INFILE}\n")
diff --git a/Tests/RunCMake/BuildDepends/MakeDependencies.cmake b/Tests/RunCMake/BuildDepends/MakeDependencies.cmake
new file mode 100644
index 000000000..33e8c7e22
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/MakeDependencies.cmake
@@ -0,0 +1,13 @@
+enable_language(C)
+
+add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c)
+
+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\"
+ \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.h\"
+ )
+set(check_exes
+ \"$<TARGET_FILE:main>\"
+ )
+")
diff --git a/Tests/RunCMake/BuildDepends/MakeDependencies.step1.cmake b/Tests/RunCMake/BuildDepends/MakeDependencies.step1.cmake
new file mode 100644
index 000000000..c74f03319
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/MakeDependencies.step1.cmake
@@ -0,0 +1,18 @@
+file(TOUCH "${RunCMake_TEST_BINARY_DIR}/main.c")
+foreach(i RANGE 1 20000)
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/temp_header_file_${i}.h"
+ "#define HEADER_${i} ${i}\n"
+ )
+ file(APPEND "${RunCMake_TEST_BINARY_DIR}/main.c"
+ "#include \"temp_header_file_${i}.h\"\n"
+ )
+endforeach()
+file(APPEND "${RunCMake_TEST_BINARY_DIR}/main.c"
+ "#include \"main.h\"\n"
+ )
+file(APPEND "${RunCMake_TEST_BINARY_DIR}/main.c"
+ "int main(void) { return COUNT; }\n"
+ )
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.h"
+ "#define COUNT 1\n"
+ )
diff --git a/Tests/RunCMake/BuildDepends/MakeDependencies.step2.cmake b/Tests/RunCMake/BuildDepends/MakeDependencies.step2.cmake
new file mode 100644
index 000000000..c826d3c41
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/MakeDependencies.step2.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.h"
+ "#define COUNT 2\n"
+ )
diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
index 6c6d548d7..62326345e 100644
--- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
+++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
@@ -30,8 +30,17 @@ function(run_BuildDepends CASE)
include(${RunCMake_SOURCE_DIR}/${CASE}.step2.cmake OPTIONAL)
set(check_step 2)
run_cmake_command(${CASE}-build2 ${CMAKE_COMMAND} --build . --config Debug)
+ if(run_BuildDepends_skip_step_3)
+ return()
+ endif()
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay}) # handle 1s resolution
+ include(${RunCMake_SOURCE_DIR}/${CASE}.step3.cmake OPTIONAL)
+ set(check_step 3)
+ run_cmake_command(${CASE}-build3 ${CMAKE_COMMAND} --build . --config Debug)
endfunction()
+set(run_BuildDepends_skip_step_3 1)
+
run_BuildDepends(C-Exe)
if(NOT RunCMake_GENERATOR STREQUAL "Xcode")
if(RunCMake_GENERATOR MATCHES "Visual Studio 10" OR
@@ -130,3 +139,28 @@ if(CMake_TEST_BuildDepends_GNU_AS)
set(ENV{ASM} "${CMake_TEST_BuildDepends_GNU_AS}")
run_BuildDepends(GNU-AS)
endif()
+
+if ((RunCMake_GENERATOR STREQUAL "Unix Makefiles"
+ AND (CMAKE_C_COMPILER_ID STREQUAL "GNU"
+ OR CMAKE_C_COMPILER_ID STREQUAL "Clang"
+ OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"))
+ OR (RunCMake_GENERATOR STREQUAL "NMake Makefiles"
+ AND MSVC_VERSION GREATER 1300
+ AND CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
+ run_BuildDepends(CompilerDependencies)
+ run_BuildDepends(CustomCommandDependencies)
+endif()
+
+if (RunCMake_GENERATOR MATCHES "Makefiles")
+ run_cmake(CustomCommandDependencies-BadArgs)
+endif()
+
+if(RunCMake_GENERATOR MATCHES "Make|Ninja")
+ unset(run_BuildDepends_skip_step_3)
+ run_BuildDepends(CustomCommandDepfile)
+ set(run_BuildDepends_skip_step_3 1)
+endif()
+
+if(RunCMake_GENERATOR MATCHES "Make")
+ run_BuildDepends(MakeDependencies)
+endif()
diff --git a/Tests/RunCMake/BuildDepends/WriteDepfile.cmake b/Tests/RunCMake/BuildDepends/WriteDepfile.cmake
new file mode 100644
index 000000000..c958cdebc
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/WriteDepfile.cmake
@@ -0,0 +1,8 @@
+file(WRITE "${OUTFILE}" [[int main(void)
+{
+ return 0;
+}
+]])
+string(REPLACE [[ ]] [[\ ]] OUTFILE "${OUTFILE}")
+string(REPLACE [[ ]] [[\ ]] INFILE "${INFILE}")
+file(WRITE "${DEPFILE}" "${OUTFILE}: ${INFILE}\n")
diff --git a/Tests/RunCMake/CMP0026/LOCATION-and-TARGET_OBJECTS.cmake b/Tests/RunCMake/CMP0026/LOCATION-and-TARGET_OBJECTS.cmake
index 3d8eb73d2..ee5ed5bd4 100644
--- a/Tests/RunCMake/CMP0026/LOCATION-and-TARGET_OBJECTS.cmake
+++ b/Tests/RunCMake/CMP0026/LOCATION-and-TARGET_OBJECTS.cmake
@@ -1,4 +1,4 @@
-
+cmake_policy(SET CMP0118 NEW)
enable_language(CXX)
add_library(foo OBJECT empty.cpp)
diff --git a/Tests/RunCMake/CMP0026/clear-cached-information.cmake b/Tests/RunCMake/CMP0026/clear-cached-information.cmake
index dd2dd7246..99169482c 100644
--- a/Tests/RunCMake/CMP0026/clear-cached-information.cmake
+++ b/Tests/RunCMake/CMP0026/clear-cached-information.cmake
@@ -1,4 +1,4 @@
-
+cmake_policy(SET CMP0118 NEW)
enable_language(C)
cmake_policy(SET CMP0026 OLD)
diff --git a/Tests/RunCMake/CMP0104/CMP0104-OLD.cmake b/Tests/RunCMake/CMP0104/CMP0104-OLD.cmake
index 415eecc5c..698844724 100644
--- a/Tests/RunCMake/CMP0104/CMP0104-OLD.cmake
+++ b/Tests/RunCMake/CMP0104/CMP0104-OLD.cmake
@@ -1,3 +1,5 @@
+set(ENV{CUDAARCHS})
+
cmake_policy(SET CMP0104 OLD)
include(CMP0104-Common.cmake)
diff --git a/Tests/RunCMake/CMP0106/CMP0106-NEW-stderr.txt b/Tests/RunCMake/CMP0106/CMP0106-NEW-stderr.txt
index 7ad774e96..8a4d7e430 100644
--- a/Tests/RunCMake/CMP0106/CMP0106-NEW-stderr.txt
+++ b/Tests/RunCMake/CMP0106/CMP0106-NEW-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at .*/Modules/Documentation.cmake:15 \(message\):
+CMake Error at .*/Modules/Documentation.cmake:[0-9]+ \(message\):
Documentation.cmake is VTK-specific code and should not be used in non-VTK
projects. This logic in this module is best shipped with the project using
it rather than with CMake. This is now an error according to policy
diff --git a/Tests/RunCMake/CMP0106/CMP0106-WARN-stderr.txt b/Tests/RunCMake/CMP0106/CMP0106-WARN-stderr.txt
index d0d48d0b1..af6bb051f 100644
--- a/Tests/RunCMake/CMP0106/CMP0106-WARN-stderr.txt
+++ b/Tests/RunCMake/CMP0106/CMP0106-WARN-stderr.txt
@@ -8,7 +8,7 @@ Call Stack \(most recent call first\):
CMakeLists.txt:7 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
-CMake Warning \(dev\) at .*/Modules/Documentation.cmake:27 \(message\):
+CMake Warning \(dev\) at .*/Modules/Documentation.cmake:[0-9]+ \(message\):
Policy CMP0106 is not set: The Documentation module is removed. Run "cmake
--help-policy CMP0106" for policy details. Use the cmake_policy command to
set the policy and suppress this warning.
@@ -22,7 +22,7 @@ Call Stack \(most recent call first\):
CMakeLists.txt:7 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
-CMake Warning \(dev\) at .*/Modules/Documentation.cmake:27 \(message\):
+CMake Warning \(dev\) at .*/Modules/Documentation.cmake:[0-9]+ \(message\):
Policy CMP0106 is not set: The Documentation module is removed. Run "cmake
--help-policy CMP0106" for policy details. Use the cmake_policy command to
set the policy and suppress this warning.
diff --git a/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step-result.txt b/Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step-result.txt
+++ b/Tests/RunCMake/CMP0115/CMP0115-NEW-result.txt
diff --git a/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt
new file mode 100644
index 000000000..b63c53d53
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-NEW-stderr.txt
@@ -0,0 +1,17 @@
+^CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+ Cannot find source file:
+
+ main
+Call Stack \(most recent call first\):
+ CMP0115-NEW\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+ No SOURCES given to target: exe
+Call Stack \(most recent call first\):
+ CMP0115-NEW\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake b/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake
new file mode 100644
index 000000000..ddf5071f6
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-NEW.cmake
@@ -0,0 +1 @@
+include(CMP0115.cmake)
diff --git a/Tests/RunCMake/File_Configure/BadArg-result.txt b/Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/File_Configure/BadArg-result.txt
+++ b/Tests/RunCMake/CMP0115/CMP0115-OLD-result.txt
diff --git a/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt
new file mode 100644
index 000000000..8b9031111
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-OLD-stderr.txt
@@ -0,0 +1,22 @@
+^CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+ Cannot find source file:
+
+ noexist
+
+ Tried extensions [^
+]*
+ [^
+]*
+Call Stack \(most recent call first\):
+ CMP0115-OLD\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+ No SOURCES given to target: exe
+Call Stack \(most recent call first\):
+ CMP0115-OLD\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake b/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake
new file mode 100644
index 000000000..ddf5071f6
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-OLD.cmake
@@ -0,0 +1 @@
+include(CMP0115.cmake)
diff --git a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-result.txt b/Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-result.txt
+++ b/Tests/RunCMake/CMP0115/CMP0115-WARN-result.txt
diff --git a/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt b/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt
new file mode 100644
index 000000000..7b100b6e4
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-WARN-stderr.txt
@@ -0,0 +1,36 @@
+^CMake Warning \(dev\) at CMP0115\.cmake:[0-9]+ \(add_executable\):
+ Policy CMP0115 is not set: Source file extensions must be explicit\. Run
+ "cmake --help-policy CMP0115" for policy details\. Use the cmake_policy
+ command to set the policy and suppress this warning\.
+
+ File:
+
+ [^
+]*/Tests/RunCMake/CMP0115/main\.c
+Call Stack \(most recent call first\):
+ CMP0115-WARN\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+ Cannot find source file:
+
+ noexist
+
+ Tried extensions [^
+]*
+ [^
+]*
+Call Stack \(most recent call first\):
+ CMP0115-WARN\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at CMP0115\.cmake:[0-9]+ \(add_executable\):
+ No SOURCES given to target: exe
+Call Stack \(most recent call first\):
+ CMP0115-WARN\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake b/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake
new file mode 100644
index 000000000..ddf5071f6
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115-WARN.cmake
@@ -0,0 +1 @@
+include(CMP0115.cmake)
diff --git a/Tests/RunCMake/CMP0115/CMP0115.cmake b/Tests/RunCMake/CMP0115/CMP0115.cmake
new file mode 100644
index 000000000..be910a420
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMP0115.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+
+add_executable(exe main noexist)
diff --git a/Tests/RunCMake/CMP0115/CMakeLists.txt b/Tests/RunCMake/CMP0115/CMakeLists.txt
new file mode 100644
index 000000000..b646c4ac6
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0115/RunCMakeTest.cmake b/Tests/RunCMake/CMP0115/RunCMakeTest.cmake
new file mode 100644
index 000000000..58182ac75
--- /dev/null
+++ b/Tests/RunCMake/CMP0115/RunCMakeTest.cmake
@@ -0,0 +1,12 @@
+include(RunCMake)
+
+function(run_cmp0115 status)
+ if(NOT status STREQUAL "WARN")
+ set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0115=${status})
+ endif()
+ run_cmake(CMP0115-${status})
+endfunction()
+
+run_cmp0115(OLD)
+run_cmp0115(WARN)
+run_cmp0115(NEW)
diff --git a/Tests/Server/buildsystem1/subdir/empty.cpp b/Tests/RunCMake/CMP0115/main.c
index 7f39d7175..8488f4e58 100644
--- a/Tests/Server/buildsystem1/subdir/empty.cpp
+++ b/Tests/RunCMake/CMP0115/main.c
@@ -1,5 +1,4 @@
-
-int foo()
+int main(void)
{
return 0;
}
diff --git a/Tests/RunCMake/CMP0116/CMP0116-Mixed-stderr.txt b/Tests/RunCMake/CMP0116/CMP0116-Mixed-stderr.txt
new file mode 100644
index 000000000..10e83a905
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-Mixed-stderr.txt
@@ -0,0 +1,17 @@
+^CMake Warning \(dev\) at CMP0116-Mixed\.cmake:1 \(add_custom_command\):
+ Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+ add_custom_command\(\)\. Run "cmake --help-policy CMP0116" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.(
+
+CMake Warning \(dev\) at CMP0116-Mixed\.cmake:1 \(add_custom_command\):
+ Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+ add_custom_command\(\)\. Run "cmake --help-policy CMP0116" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+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/CMP0116/CMP0116-Mixed.cmake b/Tests/RunCMake/CMP0116/CMP0116-Mixed.cmake
new file mode 100644
index 000000000..6cbbc092f
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-Mixed.cmake
@@ -0,0 +1,18 @@
+add_custom_command(
+ OUTPUT warn.txt
+ COMMAND ${CMAKE_COMMAND} -E touch warn.txt
+ DEPFILE warn.d
+ )
+cmake_policy(SET CMP0116 OLD)
+add_custom_command(
+ OUTPUT old.txt
+ COMMAND ${CMAKE_COMMAND} -E touch old.txt
+ DEPFILE old.d
+ )
+cmake_policy(SET CMP0116 NEW)
+add_custom_command(
+ OUTPUT new.txt
+ COMMAND ${CMAKE_COMMAND} -E touch new.txt
+ DEPFILE new.d
+ )
+add_custom_target(cc ALL DEPENDS warn.txt old.txt new.txt)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-NEW-NOWARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-NEW-NOWARN.cmake
new file mode 100644
index 000000000..f92fac68a
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-NEW-NOWARN.cmake
@@ -0,0 +1,3 @@
+set(depdir)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-NEW-WARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-NEW-WARN.cmake
new file mode 100644
index 000000000..f92fac68a
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-NEW-WARN.cmake
@@ -0,0 +1,3 @@
+set(depdir)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-OLD-NOWARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-OLD-NOWARN.cmake
new file mode 100644
index 000000000..665f48531
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-OLD-NOWARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-OLD-WARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-OLD-WARN.cmake
new file mode 100644
index 000000000..665f48531
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-OLD-WARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN-stderr.txt b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN-stderr.txt
new file mode 100644
index 000000000..843ff1c7a
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN-stderr.txt
@@ -0,0 +1,7 @@
+^(CMake Warning \(dev\) at Subdirectory/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+ add_custom_command\(\)\. Run "cmake --help-policy CMP0116" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+*)+$
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN.cmake
new file mode 100644
index 000000000..665f48531
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-NOWARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN-stderr.txt b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN-stderr.txt
new file mode 100644
index 000000000..e29af91a0
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN-stderr.txt
@@ -0,0 +1,16 @@
+^(CMake Warning \(dev\) at Common\.cmake:[0-9]+ \(add_custom_command\):
+ Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+ add_custom_command\(\)\. Run "cmake --help-policy CMP0116" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+Call Stack \(most recent call first\):
+ CMP0116-WARN-WARN\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+(CMake Warning \(dev\) at Subdirectory/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ Policy CMP0116 is not set: Ninja generators transform DEPFILEs from
+ add_custom_command\(\)\. Run "cmake --help-policy CMP0116" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+*)+$
diff --git a/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN.cmake b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN.cmake
new file mode 100644
index 000000000..665f48531
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMP0116-WARN-WARN.cmake
@@ -0,0 +1,3 @@
+set(depdir Subdirectory/)
+
+include(Common.cmake)
diff --git a/Tests/RunCMake/CMP0116/CMakeLists.txt b/Tests/RunCMake/CMP0116/CMakeLists.txt
new file mode 100644
index 000000000..b646c4ac6
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0116/Common.cmake b/Tests/RunCMake/CMP0116/Common.cmake
new file mode 100644
index 000000000..472b1625b
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/Common.cmake
@@ -0,0 +1,8 @@
+add_custom_command(
+ OUTPUT top.txt
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=top.txt -DINFILE=topdep.txt -DDEPFILE=top.txt.d -DSTAMPFILE=topstamp.txt -DDEPDIR= -P ${CMAKE_SOURCE_DIR}/WriteDepfile.cmake
+ DEPFILE top.txt.d
+ )
+add_custom_target(top ALL DEPENDS top.txt)
+
+add_subdirectory(Subdirectory)
diff --git a/Tests/RunCMake/CMP0116/RunCMakeTest.cmake b/Tests/RunCMake/CMP0116/RunCMakeTest.cmake
new file mode 100644
index 000000000..ce3e86a69
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/RunCMakeTest.cmake
@@ -0,0 +1,52 @@
+include(RunCMake)
+
+function(run_cmp0116 status warn)
+ if(warn)
+ set(name CMP0116-${status}-WARN)
+ else()
+ set(name CMP0116-${status}-NOWARN)
+ endif()
+ set(RunCMake_TEST_OPTIONS
+ -DCMAKE_POLICY_WARNING_CMP0116:BOOL=${warn}
+ )
+ if(NOT status STREQUAL "WARN")
+ list(APPEND RunCMake_TEST_OPTIONS
+ -DCMAKE_POLICY_DEFAULT_CMP0116:STRING=${status}
+ )
+ endif()
+
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+ run_cmake(${name})
+ unset(RunCMake_TEST_OPTIONS)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake-check-file check.cmake)
+
+ file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topdep.txt")
+ file(TOUCH "${RunCMake_TEST_BINARY_DIR}/Subdirectory/subdep.txt")
+ set(cmp0116_step 1)
+ run_cmake_command(${name}-build1 ${CMAKE_COMMAND} --build . --config Debug)
+ file(REMOVE "${RunCMake_TEST_BINARY_DIR}/topstamp.txt")
+ file(REMOVE "${RunCMake_TEST_BINARY_DIR}/Subdirectory/substamp.txt")
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1.25)
+
+ file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topdep.txt")
+ file(TOUCH "${RunCMake_TEST_BINARY_DIR}/Subdirectory/subdep.txt")
+ set(cmp0116_step 2)
+ run_cmake_command(${name}-build2 ${CMAKE_COMMAND} --build . --config Debug)
+ file(REMOVE "${RunCMake_TEST_BINARY_DIR}/topstamp.txt")
+ file(REMOVE "${RunCMake_TEST_BINARY_DIR}/Subdirectory/substamp.txt")
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1.25)
+
+ set(cmp0116_step 3)
+ run_cmake_command(${name}-build3 ${CMAKE_COMMAND} --build . --config Debug)
+endfunction()
+
+run_cmp0116(WARN OFF)
+run_cmp0116(OLD OFF)
+run_cmp0116(NEW OFF)
+run_cmp0116(WARN ON)
+run_cmp0116(OLD ON)
+run_cmp0116(NEW ON)
+
+set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_WARNING_CMP0116:BOOL=TRUE)
+run_cmake(CMP0116-Mixed)
diff --git a/Tests/RunCMake/CMP0116/Subdirectory/CMakeLists.txt b/Tests/RunCMake/CMP0116/Subdirectory/CMakeLists.txt
new file mode 100644
index 000000000..f0f60b2a2
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/Subdirectory/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_custom_command(
+ OUTPUT sub.txt
+ COMMAND ${CMAKE_COMMAND} -DOUTFILE=sub.txt -DINFILE=subdep.txt -DDEPFILE=sub.txt.d -DSTAMPFILE=substamp.txt -DDEPDIR=${depdir} -P ${CMAKE_SOURCE_DIR}/WriteDepfile.cmake
+ DEPFILE ${depdir}sub.txt.d
+ )
+add_custom_target(sub ALL DEPENDS sub.txt)
diff --git a/Tests/RunCMake/CMP0116/WriteDepfile.cmake b/Tests/RunCMake/CMP0116/WriteDepfile.cmake
new file mode 100644
index 000000000..1a74d2a8c
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/WriteDepfile.cmake
@@ -0,0 +1,3 @@
+file(TOUCH "${OUTFILE}")
+file(TOUCH "${STAMPFILE}")
+file(WRITE "${DEPFILE}" "${DEPDIR}${OUTFILE}: ${DEPDIR}${INFILE}\n")
diff --git a/Tests/RunCMake/CMP0116/check.cmake b/Tests/RunCMake/CMP0116/check.cmake
new file mode 100644
index 000000000..1b16748da
--- /dev/null
+++ b/Tests/RunCMake/CMP0116/check.cmake
@@ -0,0 +1,18 @@
+function(check_exists file)
+ if(NOT EXISTS "${file}")
+ string(APPEND RunCMake_TEST_FAILED "${file} does not exist\n")
+ endif()
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
+
+function(check_not_exists file)
+ if(EXISTS "${file}")
+ string(APPEND RunCMake_TEST_FAILED "${file} exists\n")
+ endif()
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
+
+if(cmp0116_step EQUAL 3)
+ check_not_exists("${RunCMake_TEST_BINARY_DIR}/topstamp.txt")
+ check_not_exists("${RunCMake_TEST_BINARY_DIR}/Subdirectory/substamp.txt")
+endif()
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Helper.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Helper.cmake
new file mode 100644
index 000000000..b237b7f25
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Helper.cmake
@@ -0,0 +1,14 @@
+macro(get_and_print_GENERATED_property filename)
+ get_property(prop SOURCE "${CMAKE_CURRENT_BINARY_DIR}/${filename}" PROPERTY GENERATED)
+ message(NOTICE "${filename}: # 1a # GENERATED = `${prop}`")
+ get_source_file_property(prop "${CMAKE_CURRENT_BINARY_DIR}/${filename}" GENERATED)
+ message(NOTICE "${filename}: # 1b # GENERATED = `${prop}`")
+ get_property(prop SOURCE "${filename}" PROPERTY GENERATED)
+ message(NOTICE "${filename}: # 2a # GENERATED = `${prop}`")
+ get_source_file_property(prop "${filename}" GENERATED)
+ message(NOTICE "${filename}: # 2b # GENERATED = `${prop}`")
+ get_property(prop SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/${filename}" PROPERTY GENERATED)
+ message(NOTICE "${filename}: # 3a # GENERATED = `${prop}`")
+ get_source_file_property(prop "${CMAKE_CURRENT_SOURCE_DIR}/${filename}" GENERATED)
+ message(NOTICE "${filename}: # 3b # GENERATED = `${prop}`")
+endmacro()
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test1.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test1.cmake
new file mode 100644
index 000000000..2b66515fc
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test1.cmake
@@ -0,0 +1,9 @@
+add_custom_target(custom)
+target_sources(custom PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/GeneratedMain.txt"
+)
+
+get_property(prop SOURCE
+ "${CMAKE_CURRENT_BINARY_DIR}/GeneratedMain.txt"
+ PROPERTY GENERATED)
+message(NOTICE "prop: `${prop}`")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test10.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test10.cmake
new file mode 100644
index 000000000..d060207c5
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test10.cmake
@@ -0,0 +1,65 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+# The sources of custom0 will not be modified by set_property!
+add_custom_target(custom0)
+target_sources(custom0 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+# The sources of custom[1-6] will (tried to) be modified by set_property!
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+
+add_subdirectory(subdir-Common-Test10)
+
+get_and_print_GENERATED_property("Generated_source0.txt")
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test11.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test11.cmake
new file mode 100644
index 000000000..00b204e8e
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test11.cmake
@@ -0,0 +1,65 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+# The sources of custom0 will not be modified by set_property!
+add_custom_target(custom0)
+target_sources(custom0 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+# The sources of custom[1-6] will (tried to) be modified by set_property!
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+
+add_subdirectory(subdir-Common-Test11)
+
+get_and_print_GENERATED_property("Generated_source0.txt")
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test12.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test12.cmake
new file mode 100644
index 000000000..1182d1777
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test12.cmake
@@ -0,0 +1,65 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+# The sources of custom0 will not be modified by set_property!
+add_custom_target(custom0)
+target_sources(custom0 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+# The sources of custom[1-6] will (tried to) be modified by set_property!
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+add_custom_command(TARGET custom0 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+add_custom_command(TARGET custom1 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_command(TARGET custom2 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_command(TARGET custom3 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+
+add_subdirectory(subdir-Common-Test12)
+
+get_and_print_GENERATED_property("Generated_source0.txt")
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test13.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test13.cmake
new file mode 100644
index 000000000..12f4ac1e0
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test13.cmake
@@ -0,0 +1,65 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+# The sources of custom0 will not be modified by set_property!
+add_custom_target(custom0)
+target_sources(custom0 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+# The sources of custom[1-6] will (tried to) be modified by set_property!
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+add_custom_command(TARGET custom0 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+add_custom_command(TARGET custom1 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_command(TARGET custom2 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_command(TARGET custom3 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+
+add_subdirectory(subdir-Common-Test13)
+
+get_and_print_GENERATED_property("Generated_source0.txt")
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test14.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test14.cmake
new file mode 100644
index 000000000..30e3edca0
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test14.cmake
@@ -0,0 +1,65 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+# The sources of custom0 will not be modified by set_property!
+add_custom_target(custom0)
+target_sources(custom0 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+# The sources of custom[1-6] will (tried to) be modified by set_property!
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+add_custom_target(custom0_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+add_custom_target(custom1_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+
+add_subdirectory(subdir-Common-Test14)
+
+get_and_print_GENERATED_property("Generated_source0.txt")
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test15.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test15.cmake
new file mode 100644
index 000000000..fb05248cd
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test15.cmake
@@ -0,0 +1,65 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+# The sources of custom0 will not be modified by set_property!
+add_custom_target(custom0)
+target_sources(custom0 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+# The sources of custom[1-6] will (tried to) be modified by set_property!
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+add_custom_target(custom0_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source0.txt"
+)
+add_custom_target(custom1_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+
+add_subdirectory(subdir-Common-Test15)
+
+get_and_print_GENERATED_property("Generated_source0.txt")
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test2.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test2.cmake
new file mode 100644
index 000000000..1180b6b38
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test2.cmake
@@ -0,0 +1,12 @@
+add_custom_target(custom)
+target_sources(custom PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/GeneratedMain.txt"
+)
+
+set_property(SOURCE
+ "${CMAKE_CURRENT_BINARY_DIR}/GeneratedMain.txt"
+ PROPERTY GENERATED "1")
+get_property(prop SOURCE
+ "${CMAKE_CURRENT_BINARY_DIR}/GeneratedMain.txt"
+ PROPERTY GENERATED)
+message(NOTICE "prop: `${prop}`")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test3.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test3.cmake
new file mode 100644
index 000000000..27516b7dc
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test3.cmake
@@ -0,0 +1,66 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path2.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path3.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "Generated_with_relative_path1.txt"
+ "Generated_with_relative_path2.txt"
+ "Generated_with_relative_path3.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path1.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path2.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path3.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_path1.txt")
+
+set_property(SOURCE "Generated_with_full_path2.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_path3.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_relative_path1.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_relative_path1.txt")
+
+set_property(SOURCE "Generated_with_relative_path2.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_relative_path2.txt")
+
+set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_relative_path3.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_relative_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_source_path1.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_source_path1.txt")
+
+set_property(SOURCE "Generated_with_full_source_path2.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_source_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_source_path3.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_source_path3.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test3b.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test3b.cmake
new file mode 100644
index 000000000..3e03a1f82
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test3b.cmake
@@ -0,0 +1,66 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_path1.txt")
+
+set_property(SOURCE "Generated_with_full_path2.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_path3.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_relative_path1.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_relative_path1.txt")
+
+set_property(SOURCE "Generated_with_relative_path2.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_relative_path2.txt")
+
+set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_relative_path3.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_relative_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_source_path1.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_source_path1.txt")
+
+set_property(SOURCE "Generated_with_full_source_path2.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_source_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_source_path3.txt"
+ PROPERTY GENERATED "1")
+get_and_print_GENERATED_property("Generated_with_full_source_path3.txt")
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path2.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path3.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "Generated_with_relative_path1.txt"
+ "Generated_with_relative_path2.txt"
+ "Generated_with_relative_path3.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path1.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path2.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path3.txt"
+)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test4.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test4.cmake
new file mode 100644
index 000000000..953e26a36
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test4.cmake
@@ -0,0 +1,66 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path2.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path3.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "Generated_with_relative_path1.txt"
+ "Generated_with_relative_path2.txt"
+ "Generated_with_relative_path3.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path1.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path2.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path3.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_path1.txt")
+
+set_property(SOURCE "Generated_with_full_path2.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_path3.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_relative_path1.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_relative_path1.txt")
+
+set_property(SOURCE "Generated_with_relative_path2.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_relative_path2.txt")
+
+set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_relative_path3.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_relative_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_source_path1.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_source_path1.txt")
+
+set_property(SOURCE "Generated_with_full_source_path2.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_source_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_source_path3.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_source_path3.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test4b.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test4b.cmake
new file mode 100644
index 000000000..025caa887
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test4b.cmake
@@ -0,0 +1,66 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_path1.txt")
+
+set_property(SOURCE "Generated_with_full_path2.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_path3.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_relative_path1.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_relative_path1.txt")
+
+set_property(SOURCE "Generated_with_relative_path2.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_relative_path2.txt")
+
+set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_relative_path3.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_relative_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_source_path1.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_source_path1.txt")
+
+set_property(SOURCE "Generated_with_full_source_path2.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_source_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_source_path3.txt"
+ PROPERTY GENERATED "0")
+get_and_print_GENERATED_property("Generated_with_full_source_path3.txt")
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path2.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path3.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "Generated_with_relative_path1.txt"
+ "Generated_with_relative_path2.txt"
+ "Generated_with_relative_path3.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path1.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path2.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path3.txt"
+)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test5.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test5.cmake
new file mode 100644
index 000000000..5349bffa0
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test5.cmake
@@ -0,0 +1,78 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "Generated_with_relative_path1.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "Generated_with_relative_path2.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "Generated_with_relative_path3.txt"
+)
+add_custom_target(custom7)
+target_sources(custom7 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path1.txt"
+)
+add_custom_target(custom8)
+target_sources(custom8 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path2.txt"
+)
+add_custom_target(custom9)
+target_sources(custom9 PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path3.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path1.txt"
+ PROPERTY GENERATED "tRue")
+get_and_print_GENERATED_property("Generated_with_full_path1.txt")
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path2.txt"
+ PROPERTY GENERATED "SomeVar-NOTFOUND")
+get_and_print_GENERATED_property("Generated_with_full_path2.txt")
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_path3.txt"
+ PROPERTY GENERATED "Junk-value")
+get_and_print_GENERATED_property("Generated_with_full_path3.txt")
+
+
+set_property(SOURCE "Generated_with_relative_path1.txt"
+ PROPERTY GENERATED "tRue")
+get_and_print_GENERATED_property("Generated_with_relative_path1.txt")
+
+set_property(SOURCE "Generated_with_relative_path2.txt"
+ PROPERTY GENERATED "SomeVar-NOTFOUND")
+get_and_print_GENERATED_property("Generated_with_relative_path2.txt")
+
+set_property(SOURCE "Generated_with_relative_path3.txt"
+ PROPERTY GENERATED "Junk-value")
+get_and_print_GENERATED_property("Generated_with_relative_path3.txt")
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_with_full_source_path1.txt"
+ PROPERTY GENERATED "tRue")
+get_and_print_GENERATED_property("Generated_with_full_source_path1.txt")
+
+set_property(SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/Generated_with_full_source_path2.txt"
+ PROPERTY GENERATED "SomeVar-NOTFOUND")
+get_and_print_GENERATED_property("Generated_with_full_source_path2.txt")
+
+set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/"Generated_with_full_source_path3.txt"
+ PROPERTY GENERATED "Junk-value")
+get_and_print_GENERATED_property("Generated_with_full_source_path3.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test6.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test6.cmake
new file mode 100644
index 000000000..a6f28aa59
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test6.cmake
@@ -0,0 +1,44 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ PROPERTY GENERATED "1")
+
+add_subdirectory(subdir-Common-Test6)
+
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test7.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test7.cmake
new file mode 100644
index 000000000..eed49b822
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test7.cmake
@@ -0,0 +1,44 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ PROPERTY GENERATED "1")
+
+add_subdirectory(subdir-Common-Test7)
+
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test8.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test8.cmake
new file mode 100644
index 000000000..5cc6e99e4
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test8.cmake
@@ -0,0 +1,50 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+
+add_subdirectory(subdir-Common-Test8)
+
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/CMP0118/CMP0118-Common-Test9.cmake b/Tests/RunCMake/CMP0118/CMP0118-Common-Test9.cmake
new file mode 100644
index 000000000..b7d36ef5f
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-Common-Test9.cmake
@@ -0,0 +1,50 @@
+include(${CMAKE_CURRENT_LIST_DIR}/CMP0118-Common-Helper.cmake)
+
+
+add_custom_target(custom1)
+target_sources(custom1 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+)
+add_custom_target(custom2)
+target_sources(custom2 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+)
+add_custom_target(custom3)
+target_sources(custom3 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+)
+add_custom_target(custom4)
+target_sources(custom4 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+)
+add_custom_target(custom5)
+target_sources(custom5 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+)
+add_custom_target(custom6)
+target_sources(custom6 PRIVATE
+ "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+)
+
+
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source1.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source2.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source3.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+
+add_subdirectory(subdir-Common-Test9)
+
+get_and_print_GENERATED_property("Generated_source1.txt")
+get_and_print_GENERATED_property("Generated_source2.txt")
+get_and_print_GENERATED_property("Generated_source3.txt")
+get_and_print_GENERATED_property("Generated_source4.txt")
+get_and_print_GENERATED_property("Generated_source5.txt")
+get_and_print_GENERATED_property("Generated_source6.txt")
diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-stderr.txt
new file mode 100644
index 000000000..ec777f763
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-stderr.txt
@@ -0,0 +1,10 @@
+^prop: `0`
+CMake Error at CMP0118-Common-Test1\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-NEW-Test1-build/GeneratedMain\.txt
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test1\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1.cmake
new file mode 100644
index 000000000..bbbee4313
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test1.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test1.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test10-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test10-stderr.txt
new file mode 100644
index 000000000..2bd1cba82
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test10-stderr.txt
@@ -0,0 +1,42 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test10.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test10.cmake
new file mode 100644
index 000000000..15a717884
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test10.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test10.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test11-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test11-stderr.txt
new file mode 100644
index 000000000..05b2353d7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test11-stderr.txt
@@ -0,0 +1,55 @@
+^(CMake Warning \(dev\) at subdir-Common-Test11/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+(CMake Warning \(dev\) at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_subdirectory\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test11.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test11.cmake
new file mode 100644
index 000000000..cb87a8695
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test11.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test11.cmake)
diff --git a/Tests/RunCMake/cmake_path/CMAKE_PATH-OUTPUT_VARIABLE-no-arg-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CMAKE_PATH-OUTPUT_VARIABLE-no-arg-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12-stderr.txt
new file mode 100644
index 000000000..e6c429c74
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12-stderr.txt
@@ -0,0 +1,51 @@
+^CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12.cmake
new file mode 100644
index 000000000..61bf97751
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test12.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test12.cmake)
diff --git a/Tests/RunCMake/cmake_path/CMAKE_PATH-invalid-output-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CMAKE_PATH-invalid-output-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13-stderr.txt
new file mode 100644
index 000000000..7802538fc
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13-stderr.txt
@@ -0,0 +1,64 @@
+^CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+(CMake Warning \(dev\) at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+(CMake Warning \(dev\) at CMP0118-Common-Test13\.cmake:[0-9]+ \(add_subdirectory\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test13\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13.cmake
new file mode 100644
index 000000000..569e4c675
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test13.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test13.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test14-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test14-stderr.txt
new file mode 100644
index 000000000..2bd1cba82
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test14-stderr.txt
@@ -0,0 +1,42 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test14.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test14.cmake
new file mode 100644
index 000000000..e7d8d7701
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test14.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test14.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test15-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test15-stderr.txt
new file mode 100644
index 000000000..3166f45d6
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test15-stderr.txt
@@ -0,0 +1,55 @@
+^(CMake Warning \(dev\) at subdir-Common-Test15/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+(CMake Warning \(dev\) at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_subdirectory\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test15.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test15.cmake
new file mode 100644
index 000000000..93513ae8f
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test15.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test15.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test2-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test2-stderr.txt
new file mode 100644
index 000000000..403ce5a56
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test2-stderr.txt
@@ -0,0 +1 @@
+^prop: `1`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test2.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test2.cmake
new file mode 100644
index 000000000..ee8233d03
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test2.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test2.cmake)
diff --git a/Tests/RunCMake/cmake_path/CMAKE_PATH-missing-output-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CMAKE_PATH-missing-output-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3-stderr.txt
new file mode 100644
index 000000000..f7d9f6bff
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3-stderr.txt
@@ -0,0 +1,87 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3.cmake
new file mode 100644
index 000000000..b9533fdc1
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test3.cmake)
diff --git a/Tests/RunCMake/cmake_path/CMAKE_PATH-unexpected-arg-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CMAKE_PATH-unexpected-arg-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b-stderr.txt
new file mode 100644
index 000000000..a87639039
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b-stderr.txt
@@ -0,0 +1,87 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b.cmake
new file mode 100644
index 000000000..79631e7c9
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test3b.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test3b.cmake)
diff --git a/Tests/RunCMake/cmake_path/CMAKE_PATH-wrong-path-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CMAKE_PATH-wrong-path-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4-stderr.txt
new file mode 100644
index 000000000..b750ae7e5
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4-stderr.txt
@@ -0,0 +1,167 @@
+^CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4.cmake
new file mode 100644
index 000000000..8a7d35af3
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test4.cmake)
diff --git a/Tests/RunCMake/cmake_path/COMPARE-EQUAL-wrong-path-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/COMPARE-EQUAL-wrong-path-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b-stderr.txt
new file mode 100644
index 000000000..580f04f9c
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b-stderr.txt
@@ -0,0 +1,167 @@
+^CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4b-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4b-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4b-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4b-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test4b-build/Generated_with_full_path1\.txt|CMP0118-NEW-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b.cmake
new file mode 100644
index 000000000..c03a39d80
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test4b.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test4b.cmake)
diff --git a/Tests/RunCMake/cmake_path/COMPARE-NOT_EQUAL-wrong-path-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/COMPARE-NOT_EQUAL-wrong-path-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5-stderr.txt
new file mode 100644
index 000000000..e268a7ac3
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5-stderr.txt
@@ -0,0 +1,174 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is set to NEW and the following non-boolean value given for
+ property 'GENERATED' is therefore not allowed:
+
+ Junk-value
+
+ Replace it with a boolean value!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is set to NEW and the following non-boolean value given for
+ property 'GENERATED' is therefore not allowed:
+
+ Junk-value
+
+ Replace it with a boolean value!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is set to NEW and the following non-boolean value given for
+ property 'GENERATED' is therefore not allowed:
+
+ Junk-value
+
+ Replace it with a boolean value!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-NEW-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5.cmake
new file mode 100644
index 000000000..691f94a20
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test5.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test5.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test6-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test6-stderr.txt
new file mode 100644
index 000000000..0c84cfe5b
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test6-stderr.txt
@@ -0,0 +1,36 @@
+^Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test6.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test6.cmake
new file mode 100644
index 000000000..09b87a53e
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test6.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test6.cmake)
diff --git a/Tests/RunCMake/cmake_path/CONCAT-OUTPUT_VARIABLE-invalid-arg-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CONCAT-OUTPUT_VARIABLE-invalid-arg-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-stderr.txt
new file mode 100644
index 000000000..08eb6826a
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-stderr.txt
@@ -0,0 +1,74 @@
+^(CMake Warning \(dev\) at subdir-Common-Test7/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+(CMake Warning \(dev\) at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_subdirectory\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-NEW-Test7-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7.cmake
new file mode 100644
index 000000000..ceb8bebb0
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test7.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test7.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test8-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test8-stderr.txt
new file mode 100644
index 000000000..f72387557
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test8-stderr.txt
@@ -0,0 +1,36 @@
+^Generated_source1\.txt: # 1a # GENERATED = `0`
+Generated_source1\.txt: # 1b # GENERATED = `0`
+Generated_source1\.txt: # 2a # GENERATED = `0`
+Generated_source1\.txt: # 2b # GENERATED = `0`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test8.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test8.cmake
new file mode 100644
index 000000000..6878b9400
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test8.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test8.cmake)
diff --git a/Tests/RunCMake/cmake_path/CONCAT-OUTPUT_VARIABLE-no-arg-result.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CONCAT-OUTPUT_VARIABLE-no-arg-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-stderr.txt
new file mode 100644
index 000000000..b7c496c5b
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-stderr.txt
@@ -0,0 +1,74 @@
+^(CMake Warning \(dev\) at subdir-Common-Test9/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+(CMake Warning \(dev\) at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_subdirectory\):
+ Unsetting the 'GENERATED' property is not allowed under CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source1\.txt: # 1a # GENERATED = `0`
+Generated_source1\.txt: # 1b # GENERATED = `0`
+Generated_source1\.txt: # 2a # GENERATED = `0`
+Generated_source1\.txt: # 2b # GENERATED = `0`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `0`
+Generated_source2\.txt: # 1b # GENERATED = `0`
+Generated_source2\.txt: # 2a # GENERATED = `0`
+Generated_source2\.txt: # 2b # GENERATED = `0`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `0`
+Generated_source3\.txt: # 1b # GENERATED = `0`
+Generated_source3\.txt: # 2a # GENERATED = `0`
+Generated_source3\.txt: # 2b # GENERATED = `0`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-NEW-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-NEW-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9.cmake b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9.cmake
new file mode 100644
index 000000000..00b05fddd
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-NEW-Test9.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(CMP0118-Common-Test9.cmake)
diff --git a/Tests/RunCMake/cmake_path/CONCAT-wrong-path-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/CONCAT-wrong-path-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-stderr.txt
new file mode 100644
index 000000000..58144c8d8
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-stderr.txt
@@ -0,0 +1,10 @@
+^prop: `0`
+CMake Error at CMP0118-Common-Test1\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test1-build/GeneratedMain\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test1\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1.cmake
new file mode 100644
index 000000000..c18dd251a
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test1.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test1.cmake)
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-invalid-output-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-invalid-output-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-stderr.txt
new file mode 100644
index 000000000..1f1bc904a
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-stderr.txt
@@ -0,0 +1,51 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test10\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test10-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test10\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10.cmake
new file mode 100644
index 000000000..b96973f87
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test10.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test10.cmake)
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-missing-output-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-missing-output-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-stderr.txt
new file mode 100644
index 000000000..5c15f1203
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-stderr.txt
@@ -0,0 +1,67 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test11-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11.cmake
new file mode 100644
index 000000000..d6ad7d22d
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test11.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test11.cmake)
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-unexpected-arg-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-unexpected-arg-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12-stderr.txt
new file mode 100644
index 000000000..e6c429c74
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12-stderr.txt
@@ -0,0 +1,51 @@
+^CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12.cmake
new file mode 100644
index 000000000..b87b03aee
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test12.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test12.cmake)
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-wrong-path-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/GET-RELATIVE_PATH-wrong-path-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13-stderr.txt
new file mode 100644
index 000000000..75dbf2308
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13-stderr.txt
@@ -0,0 +1,51 @@
+^CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13.cmake
new file mode 100644
index 000000000..17a135b06
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test13.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test13.cmake)
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-invalid-output-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-invalid-output-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-stderr.txt
new file mode 100644
index 000000000..12a913a9e
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-stderr.txt
@@ -0,0 +1,51 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test14\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test14-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test14\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14.cmake
new file mode 100644
index 000000000..070229177
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test14.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test14.cmake)
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-missing-output-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-missing-output-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-stderr.txt
new file mode 100644
index 000000000..62db7ee4a
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-stderr.txt
@@ -0,0 +1,67 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test15-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15.cmake
new file mode 100644
index 000000000..c330d4eee
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test15.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test15.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test2-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test2-stderr.txt
new file mode 100644
index 000000000..403ce5a56
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test2-stderr.txt
@@ -0,0 +1 @@
+^prop: `1`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test2.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test2.cmake
new file mode 100644
index 000000000..3ea8800f4
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test2.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test2.cmake)
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-unexpected-arg-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-unexpected-arg-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3-stderr.txt
new file mode 100644
index 000000000..7f86d38b3
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3-stderr.txt
@@ -0,0 +1,87 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3.cmake
new file mode 100644
index 000000000..c8f5a0e1b
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test3.cmake)
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-wrong-path-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b-result.txt
index d00491fd7..d00491fd7 100644
--- a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PATH-wrong-path-result.txt
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b-result.txt
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b-stderr.txt
new file mode 100644
index 000000000..4104fc003
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b-stderr.txt
@@ -0,0 +1,87 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b.cmake
new file mode 100644
index 000000000..0b046b480
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test3b.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test3b.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-stderr.txt
new file mode 100644
index 000000000..7a16d0b64
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4-stderr.txt
@@ -0,0 +1,95 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4.cmake
new file mode 100644
index 000000000..2f7739704
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test4.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-stderr.txt
new file mode 100644
index 000000000..5a5c4ecea
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b-stderr.txt
@@ -0,0 +1,95 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4b-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4b-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4b-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4b-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test4b-build/Generated_with_full_path1\.txt|CMP0118-OLD-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b.cmake
new file mode 100644
index 000000000..ce6726d77
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test4b.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test4b.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-stderr.txt
new file mode 100644
index 000000000..12fa617ab
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5-stderr.txt
@@ -0,0 +1,111 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-OLD-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5.cmake
new file mode 100644
index 000000000..2de6d89c9
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test5.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test5.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-stderr.txt
new file mode 100644
index 000000000..7199f0441
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-stderr.txt
@@ -0,0 +1,45 @@
+^Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test6\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test6-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test6\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6.cmake
new file mode 100644
index 000000000..b57105244
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test6.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test6.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-stderr.txt
new file mode 100644
index 000000000..233fd8bdf
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-stderr.txt
@@ -0,0 +1,77 @@
+^Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `0`
+Generated_source2\.txt: # 1b # GENERATED = `0`
+Generated_source2\.txt: # 2a # GENERATED = `0`
+Generated_source2\.txt: # 2b # GENERATED = `0`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `0`
+Generated_source3\.txt: # 1b # GENERATED = `0`
+Generated_source3\.txt: # 2a # GENERATED = `0`
+Generated_source3\.txt: # 2b # GENERATED = `0`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7.cmake
new file mode 100644
index 000000000..551da2397
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test7.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test7.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-stderr.txt
new file mode 100644
index 000000000..4aed2edd1
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-stderr.txt
@@ -0,0 +1,45 @@
+^Generated_source1\.txt: # 1a # GENERATED = `0`
+Generated_source1\.txt: # 1b # GENERATED = `0`
+Generated_source1\.txt: # 2a # GENERATED = `0`
+Generated_source1\.txt: # 2b # GENERATED = `0`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test8\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test8-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test8\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8.cmake
new file mode 100644
index 000000000..2d9e3d340
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test8.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test8.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-result.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-stderr.txt
new file mode 100644
index 000000000..cea8c224d
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-stderr.txt
@@ -0,0 +1,61 @@
+^Generated_source1\.txt: # 1a # GENERATED = `0`
+Generated_source1\.txt: # 1b # GENERATED = `0`
+Generated_source1\.txt: # 2a # GENERATED = `0`
+Generated_source1\.txt: # 2b # GENERATED = `0`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `0`
+Generated_source2\.txt: # 1b # GENERATED = `0`
+Generated_source2\.txt: # 2a # GENERATED = `0`
+Generated_source2\.txt: # 2b # GENERATED = `0`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `0`
+Generated_source3\.txt: # 1b # GENERATED = `0`
+Generated_source3\.txt: # 2a # GENERATED = `0`
+Generated_source3\.txt: # 2b # GENERATED = `0`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-OLD-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-OLD-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9.cmake b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9.cmake
new file mode 100644
index 000000000..53f73d9c9
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-OLD-Test9.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(CMP0118-Common-Test9.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-stderr.txt
new file mode 100644
index 000000000..e2a2cf547
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-stderr.txt
@@ -0,0 +1,10 @@
+^prop: `0`
+CMake Error at CMP0118-Common-Test1\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test1-build/GeneratedMain\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test1\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1.cmake
new file mode 100644
index 000000000..3c82f8edb
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test1.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test1.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-stderr.txt
new file mode 100644
index 000000000..bce768131
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-stderr.txt
@@ -0,0 +1,51 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test10\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test10-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test10\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10.cmake
new file mode 100644
index 000000000..c639c409d
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test10.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test10.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-stderr.txt
new file mode 100644
index 000000000..00c47e9e6
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-stderr.txt
@@ -0,0 +1,90 @@
+^((CMake Warning \(dev\) at subdir-Common-Test11/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+
+(CMake Warning \(dev\) at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_subdirectory\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test11\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test11-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test11\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11.cmake
new file mode 100644
index 000000000..4c9735d6e
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test11.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test11.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-stderr.txt
new file mode 100644
index 000000000..e6c429c74
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12-stderr.txt
@@ -0,0 +1,51 @@
+^CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test12/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12.cmake
new file mode 100644
index 000000000..79fa00a4a
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test12.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test12.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-stderr.txt
new file mode 100644
index 000000000..6d59cb47e
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13-stderr.txt
@@ -0,0 +1,74 @@
+^CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+CMake Error at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(add_custom_command\):
+ TARGET 'custom[4-6]' was not created in this directory\.
++
+((CMake Warning \(dev\) at subdir-Common-Test13/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+
+(CMake Warning \(dev\) at CMP0118-Common-Test13\.cmake:[0-9]+ \(add_subdirectory\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test13\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13.cmake
new file mode 100644
index 000000000..27f71c797
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test13.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test13.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-stderr.txt
new file mode 100644
index 000000000..5b7994c5f
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-stderr.txt
@@ -0,0 +1,51 @@
+^Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test14\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test14-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test14\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14.cmake
new file mode 100644
index 000000000..056f0ad66
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test14.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test14.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-stderr.txt
new file mode 100644
index 000000000..c975c235e
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-stderr.txt
@@ -0,0 +1,90 @@
+^((CMake Warning \(dev\) at subdir-Common-Test15/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+
+(CMake Warning \(dev\) at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_subdirectory\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source0\.txt: # 1a # GENERATED = `1`
+Generated_source0\.txt: # 1b # GENERATED = `1`
+Generated_source0\.txt: # 2a # GENERATED = `1`
+Generated_source0\.txt: # 2b # GENERATED = `1`
+Generated_source0\.txt: # 3a # GENERATED = `0`
+Generated_source0\.txt: # 3b # GENERATED = `0`
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test15\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test15-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test15\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15.cmake
new file mode 100644
index 000000000..acc8bf6f6
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test15.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test15.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test2-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test2-stderr.txt
new file mode 100644
index 000000000..403ce5a56
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test2-stderr.txt
@@ -0,0 +1 @@
+^prop: `1`$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test2.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test2.cmake
new file mode 100644
index 000000000..5a679749f
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test2.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test2.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-stderr.txt
new file mode 100644
index 000000000..142d8a076
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3-stderr.txt
@@ -0,0 +1,87 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3.cmake
new file mode 100644
index 000000000..7cdfacbb5
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test3.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-stderr.txt
new file mode 100644
index 000000000..d4ef667fc
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b-stderr.txt
@@ -0,0 +1,87 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `1`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test3b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test3b-build/Generated_with_full_path3\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test3b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b.cmake
new file mode 100644
index 000000000..6dfc16ab5
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test3b.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test3b.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-stderr.txt
new file mode 100644
index 000000000..ceeb570ed
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4-stderr.txt
@@ -0,0 +1,212 @@
+^CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4.cmake
new file mode 100644
index 000000000..9d432a42b
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test4.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-stderr.txt
new file mode 100644
index 000000000..f8484d0b5
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b-stderr.txt
@@ -0,0 +1,212 @@
+^CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test4b\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4b-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4b-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4b-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4b-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test4b\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test4b-build/Generated_with_full_path1\.txt|CMP0118-WARN-Test4b-build/Generated_with_relative_path1\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test4b\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b.cmake
new file mode 100644
index 000000000..2e2c2bd1b
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test4b.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test4b.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-stderr.txt
new file mode 100644
index 000000000..0556391ef
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5-stderr.txt
@@ -0,0 +1,213 @@
+^Generated_with_full_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Attempt to set property 'GENERATED' with the following non-boolean value
+ \(which will be interpreted as "0"\):
+
+ Junk-value
+
+ That exact value will not be retrievable\. A value of "0" will be returned
+ instead\.
+
+ This will be an error under policy CMP0118\.
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_relative_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Attempt to set property 'GENERATED' with the following non-boolean value
+ \(which will be interpreted as "0"\):
+
+ Junk-value
+
+ That exact value will not be retrievable\. A value of "0" will be returned
+ instead\.
+
+ This will be an error under policy CMP0118\.
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_relative_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_relative_path3\.txt: # 3b # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 1a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 1b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2a # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 2b # GENERATED = `1`
+Generated_with_full_source_path1\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path1\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path2\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path2\.txt: # 3b # GENERATED = `0`
+CMake Warning \(dev\) at CMP0118-Common-Test5\.cmake:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Attempt to set property 'GENERATED' with the following non-boolean value
+ \(which will be interpreted as "0"\):
+
+ Junk-value
+
+ That exact value will not be retrievable\. A value of "0" will be returned
+ instead\.
+
+ This will be an error under policy CMP0118\.
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++
+Generated_with_full_source_path3\.txt: # 1a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 1b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 2b # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3a # GENERATED = `0`
+Generated_with_full_source_path3\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test5\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/(Generated_with_full_source_path[1-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_relative_path[2-3]\.txt|CMP0118-WARN-Test5-build/Generated_with_full_path[2-3]\.txt)
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test5\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5.cmake
new file mode 100644
index 000000000..87e965eb9
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test5.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test5.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-stderr.txt
new file mode 100644
index 000000000..7d588a2d6
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-stderr.txt
@@ -0,0 +1,45 @@
+^Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test6\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test6-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test6\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6.cmake
new file mode 100644
index 000000000..6f1edbc16
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test6.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test6.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-stderr.txt
new file mode 100644
index 000000000..8421061ce
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-stderr.txt
@@ -0,0 +1,100 @@
+^((CMake Warning \(dev\) at subdir-Common-Test7/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+
+(CMake Warning \(dev\) at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_subdirectory\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source1\.txt: # 1a # GENERATED = `1`
+Generated_source1\.txt: # 1b # GENERATED = `1`
+Generated_source1\.txt: # 2a # GENERATED = `1`
+Generated_source1\.txt: # 2b # GENERATED = `1`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `0`
+Generated_source2\.txt: # 1b # GENERATED = `0`
+Generated_source2\.txt: # 2a # GENERATED = `0`
+Generated_source2\.txt: # 2b # GENERATED = `0`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `0`
+Generated_source3\.txt: # 1b # GENERATED = `0`
+Generated_source3\.txt: # 2a # GENERATED = `0`
+Generated_source3\.txt: # 2b # GENERATED = `0`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test7\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test7-build/Generated_source[2-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test7\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7.cmake
new file mode 100644
index 000000000..86af20d5a
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test7.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test7.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-stderr.txt
new file mode 100644
index 000000000..e0f17e675
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-stderr.txt
@@ -0,0 +1,45 @@
+^Generated_source1\.txt: # 1a # GENERATED = `0`
+Generated_source1\.txt: # 1b # GENERATED = `0`
+Generated_source1\.txt: # 2a # GENERATED = `0`
+Generated_source1\.txt: # 2b # GENERATED = `0`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `1`
+Generated_source2\.txt: # 1b # GENERATED = `1`
+Generated_source2\.txt: # 2a # GENERATED = `1`
+Generated_source2\.txt: # 2b # GENERATED = `1`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `1`
+Generated_source3\.txt: # 1b # GENERATED = `1`
+Generated_source3\.txt: # 2a # GENERATED = `1`
+Generated_source3\.txt: # 2b # GENERATED = `1`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `1`
+Generated_source5\.txt: # 1b # GENERATED = `1`
+Generated_source5\.txt: # 2a # GENERATED = `1`
+Generated_source5\.txt: # 2b # GENERATED = `1`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `1`
+Generated_source6\.txt: # 1b # GENERATED = `1`
+Generated_source6\.txt: # 2a # GENERATED = `1`
+Generated_source6\.txt: # 2b # GENERATED = `1`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test8\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test8-build/Generated_source4\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test8\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8.cmake
new file mode 100644
index 000000000..6a0bb4cce
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test8.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test8.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-result.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-stderr.txt b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-stderr.txt
new file mode 100644
index 000000000..80f3edf36
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-stderr.txt
@@ -0,0 +1,84 @@
+^((CMake Warning \(dev\) at subdir-Common-Test9/CMakeLists\.txt:[0-9]+ \(set_property\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+
+(CMake Warning \(dev\) at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_subdirectory\):
+ Policy CMP0118 is not set: The GENERATED source file property is now
+ visible in all directories\. Run "cmake --help-policy CMP0118" for policy
+ details\. Use the cmake_policy command to set the policy and suppress this
+ warning\.
+
+ Unsetting property 'GENERATED' will not be allowed under policy CMP0118!
+
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
++)+)+
+Generated_source1\.txt: # 1a # GENERATED = `0`
+Generated_source1\.txt: # 1b # GENERATED = `0`
+Generated_source1\.txt: # 2a # GENERATED = `0`
+Generated_source1\.txt: # 2b # GENERATED = `0`
+Generated_source1\.txt: # 3a # GENERATED = `0`
+Generated_source1\.txt: # 3b # GENERATED = `0`
+Generated_source2\.txt: # 1a # GENERATED = `0`
+Generated_source2\.txt: # 1b # GENERATED = `0`
+Generated_source2\.txt: # 2a # GENERATED = `0`
+Generated_source2\.txt: # 2b # GENERATED = `0`
+Generated_source2\.txt: # 3a # GENERATED = `0`
+Generated_source2\.txt: # 3b # GENERATED = `0`
+Generated_source3\.txt: # 1a # GENERATED = `0`
+Generated_source3\.txt: # 1b # GENERATED = `0`
+Generated_source3\.txt: # 2a # GENERATED = `0`
+Generated_source3\.txt: # 2b # GENERATED = `0`
+Generated_source3\.txt: # 3a # GENERATED = `0`
+Generated_source3\.txt: # 3b # GENERATED = `0`
+Generated_source4\.txt: # 1a # GENERATED = `0`
+Generated_source4\.txt: # 1b # GENERATED = `0`
+Generated_source4\.txt: # 2a # GENERATED = `0`
+Generated_source4\.txt: # 2b # GENERATED = `0`
+Generated_source4\.txt: # 3a # GENERATED = `0`
+Generated_source4\.txt: # 3b # GENERATED = `0`
+Generated_source5\.txt: # 1a # GENERATED = `0`
+Generated_source5\.txt: # 1b # GENERATED = `0`
+Generated_source5\.txt: # 2a # GENERATED = `0`
+Generated_source5\.txt: # 2b # GENERATED = `0`
+Generated_source5\.txt: # 3a # GENERATED = `0`
+Generated_source5\.txt: # 3b # GENERATED = `0`
+Generated_source6\.txt: # 1a # GENERATED = `0`
+Generated_source6\.txt: # 1b # GENERATED = `0`
+Generated_source6\.txt: # 2a # GENERATED = `0`
+Generated_source6\.txt: # 2b # GENERATED = `0`
+Generated_source6\.txt: # 3a # GENERATED = `0`
+Generated_source6\.txt: # 3b # GENERATED = `0`
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at CMP0118-Common-Test9\.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+[ \t]*.*Tests/RunCMake/CMP0118/CMP0118-WARN-Test9-build/Generated_source[4-6]\.txt
+Call Stack \(most recent call first\):
+ CMP0118-WARN-Test9\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9.cmake b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9.cmake
new file mode 100644
index 000000000..c48c64e8e
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMP0118-WARN-Test9.cmake
@@ -0,0 +1 @@
+include(CMP0118-Common-Test9.cmake)
diff --git a/Tests/RunCMake/CMP0118/CMakeLists.txt b/Tests/RunCMake/CMP0118/CMakeLists.txt
new file mode 100644
index 000000000..957fe03fa
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.19)
+cmake_policy(SET CMP0115 NEW)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-Common.cmake b/Tests/RunCMake/CMP0118/GenInSubdir-Common.cmake
new file mode 100644
index 000000000..6012c7995
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-Common.cmake
@@ -0,0 +1,2 @@
+add_custom_target(top)
+add_subdirectory(GenInSubdir)
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-NEW.cmake b/Tests/RunCMake/CMP0118/GenInSubdir-NEW.cmake
new file mode 100644
index 000000000..373e73d31
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 NEW)
+include(GenInSubdir-Common.cmake)
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-OLD-result.txt b/Tests/RunCMake/CMP0118/GenInSubdir-OLD-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-OLD-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-OLD-stderr.txt b/Tests/RunCMake/CMP0118/GenInSubdir-OLD-stderr.txt
new file mode 100644
index 000000000..d3aa54630
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-OLD-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Error at GenInSubdir-Common.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+ [^
+]*/Tests/RunCMake/CMP0118/GenInSubdir-OLD-build/GenInSubdir/sub.txt
+Call Stack \(most recent call first\):
+ GenInSubdir-OLD.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-OLD.cmake b/Tests/RunCMake/CMP0118/GenInSubdir-OLD.cmake
new file mode 100644
index 000000000..48be27ef6
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0118 OLD)
+include(GenInSubdir-Common.cmake)
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-WARN-result.txt b/Tests/RunCMake/CMP0118/GenInSubdir-WARN-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-WARN-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-WARN-stderr.txt b/Tests/RunCMake/CMP0118/GenInSubdir-WARN-stderr.txt
new file mode 100644
index 000000000..5eb8a34b6
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-WARN-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Error at GenInSubdir-Common.cmake:[0-9]+ \(add_custom_target\):
+ Cannot find source file:
+
+ [^
+]*/Tests/RunCMake/CMP0118/GenInSubdir-WARN-build/GenInSubdir/sub.txt
+Call Stack \(most recent call first\):
+ GenInSubdir-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir-WARN.cmake b/Tests/RunCMake/CMP0118/GenInSubdir-WARN.cmake
new file mode 100644
index 000000000..8e7e39536
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(GenInSubdir-Common.cmake)
diff --git a/Tests/RunCMake/CMP0118/GenInSubdir/CMakeLists.txt b/Tests/RunCMake/CMP0118/GenInSubdir/CMakeLists.txt
new file mode 100644
index 000000000..3f1ce8dab
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/GenInSubdir/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_custom_command(
+ OUTPUT sub.txt
+ COMMAND ${CMAKE_COMMAND} -E touch sub.txt
+ VERBATIM
+ )
+add_custom_target(gen DEPENDS sub.txt)
+
+add_dependencies(top gen)
+target_sources(top PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/sub.txt)
diff --git a/Tests/RunCMake/CMP0118/RunCMakeTest.cmake b/Tests/RunCMake/CMP0118/RunCMakeTest.cmake
new file mode 100644
index 000000000..f7f135e61
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/RunCMakeTest.cmake
@@ -0,0 +1,59 @@
+include(RunCMake)
+
+run_cmake(GenInSubdir-OLD)
+run_cmake(GenInSubdir-WARN)
+run_cmake(GenInSubdir-NEW)
+
+run_cmake(CMP0118-OLD-Test1)
+run_cmake(CMP0118-OLD-Test2)
+run_cmake(CMP0118-OLD-Test3)
+run_cmake(CMP0118-OLD-Test3b)
+run_cmake(CMP0118-OLD-Test4)
+run_cmake(CMP0118-OLD-Test4b)
+run_cmake(CMP0118-OLD-Test5)
+run_cmake(CMP0118-OLD-Test6)
+run_cmake(CMP0118-OLD-Test7)
+run_cmake(CMP0118-OLD-Test8)
+run_cmake(CMP0118-OLD-Test9)
+run_cmake(CMP0118-OLD-Test10)
+run_cmake(CMP0118-OLD-Test11)
+run_cmake(CMP0118-OLD-Test12)
+run_cmake(CMP0118-OLD-Test13)
+run_cmake(CMP0118-OLD-Test14)
+run_cmake(CMP0118-OLD-Test15)
+
+run_cmake(CMP0118-WARN-Test1)
+run_cmake(CMP0118-WARN-Test2)
+run_cmake(CMP0118-WARN-Test3)
+run_cmake(CMP0118-WARN-Test3b)
+run_cmake(CMP0118-WARN-Test4)
+run_cmake(CMP0118-WARN-Test4b)
+run_cmake(CMP0118-WARN-Test5)
+run_cmake(CMP0118-WARN-Test6)
+run_cmake(CMP0118-WARN-Test7)
+run_cmake(CMP0118-WARN-Test8)
+run_cmake(CMP0118-WARN-Test9)
+run_cmake(CMP0118-WARN-Test10)
+run_cmake(CMP0118-WARN-Test11)
+run_cmake(CMP0118-WARN-Test12)
+run_cmake(CMP0118-WARN-Test13)
+run_cmake(CMP0118-WARN-Test14)
+run_cmake(CMP0118-WARN-Test15)
+
+run_cmake(CMP0118-NEW-Test1)
+run_cmake(CMP0118-NEW-Test2)
+run_cmake(CMP0118-NEW-Test3)
+run_cmake(CMP0118-NEW-Test3b)
+run_cmake(CMP0118-NEW-Test4)
+run_cmake(CMP0118-NEW-Test4b)
+run_cmake(CMP0118-NEW-Test5)
+run_cmake(CMP0118-NEW-Test6)
+run_cmake(CMP0118-NEW-Test7)
+run_cmake(CMP0118-NEW-Test8)
+run_cmake(CMP0118-NEW-Test9)
+run_cmake(CMP0118-NEW-Test10)
+run_cmake(CMP0118-NEW-Test11)
+run_cmake(CMP0118-NEW-Test12)
+run_cmake(CMP0118-NEW-Test13)
+run_cmake(CMP0118-NEW-Test14)
+run_cmake(CMP0118-NEW-Test15)
diff --git a/Tests/RunCMake/CMP0118/source.cpp.in b/Tests/RunCMake/CMP0118/source.cpp.in
new file mode 100644
index 000000000..678cd7a70
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/source.cpp.in
@@ -0,0 +1,5 @@
+int func();
+int main()
+{
+ return func();
+}
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test10/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test10/CMakeLists.txt
new file mode 100644
index 000000000..6bc99cb44
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test10/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test11/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test11/CMakeLists.txt
new file mode 100644
index 000000000..fbd7e6f63
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test11/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test12/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test12/CMakeLists.txt
new file mode 100644
index 000000000..916725c82
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test12/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_custom_command(TARGET custom4 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ BYPRODUCT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+)
+add_custom_command(TARGET custom5 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ BYPRODUCT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+)
+add_custom_command(TARGET custom6 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ BYPRODUCT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test13/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test13/CMakeLists.txt
new file mode 100644
index 000000000..f2929aa33
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test13/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_custom_command(TARGET custom4 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ BYPRODUCT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+)
+add_custom_command(TARGET custom5 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ BYPRODUCT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+)
+add_custom_command(TARGET custom6 PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ BYPRODUCT "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test14/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test14/CMakeLists.txt
new file mode 100644
index 000000000..7397db9c7
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test14/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_custom_target(custom4_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+)
+add_custom_target(custom5_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+)
+add_custom_target(custom6_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test15/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test15/CMakeLists.txt
new file mode 100644
index 000000000..314e427e5
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test15/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_custom_target(custom4_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+)
+add_custom_target(custom5_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+)
+add_custom_target(custom6_source_generator ALL
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/Source.txt.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test6/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test6/CMakeLists.txt
new file mode 100644
index 000000000..fa307d151
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test6/CMakeLists.txt
@@ -0,0 +1,16 @@
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test7/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test7/CMakeLists.txt
new file mode 100644
index 000000000..6362f78ab
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test7/CMakeLists.txt
@@ -0,0 +1,16 @@
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test8/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test8/CMakeLists.txt
new file mode 100644
index 000000000..55debd1a6
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test8/CMakeLists.txt
@@ -0,0 +1,30 @@
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "1")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "1")
diff --git a/Tests/RunCMake/CMP0118/subdir-Common-Test9/CMakeLists.txt b/Tests/RunCMake/CMP0118/subdir-Common-Test9/CMakeLists.txt
new file mode 100644
index 000000000..cdb888403
--- /dev/null
+++ b/Tests/RunCMake/CMP0118/subdir-Common-Test9/CMakeLists.txt
@@ -0,0 +1,30 @@
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source4.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source5.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Generated_source6.txt"
+ CONTENT "int func();\nint main(){ return func(); }"
+)
+
+
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source1.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source2.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source3.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source4.txt"
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source5.txt"
+ DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
+ PROPERTY GENERATED "0")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/../Generated_source6.txt"
+ TARGET_DIRECTORY custom1
+ PROPERTY GENERATED "0")
diff --git a/Tests/RunCMake/CMP0119/AltExtC.zzz b/Tests/RunCMake/CMP0119/AltExtC.zzz
new file mode 100644
index 000000000..5b240eb3d
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/AltExtC.zzz
@@ -0,0 +1,4 @@
+int main(void) {
+ int class = 0;
+ return class;
+}
diff --git a/Tests/RunCMake/CMP0119/AltExtCXX.zzz b/Tests/RunCMake/CMP0119/AltExtCXX.zzz
new file mode 100644
index 000000000..3c521ed28
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/AltExtCXX.zzz
@@ -0,0 +1,3 @@
+int main() {
+ return static_cast<int>(0);
+}
diff --git a/Tests/RunCMake/CMP0119/CMP0119-Common.cmake b/Tests/RunCMake/CMP0119/CMP0119-Common.cmake
new file mode 100644
index 000000000..f45895bcf
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-Common.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_executable(AltExtC AltExtC.zzz)
+set_property(SOURCE AltExtC.zzz PROPERTY LANGUAGE C)
diff --git a/Tests/RunCMake/CMP0119/CMP0119-NEW.cmake b/Tests/RunCMake/CMP0119/CMP0119-NEW.cmake
new file mode 100644
index 000000000..df0ed4890
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-NEW.cmake
@@ -0,0 +1,6 @@
+cmake_policy(SET CMP0119 NEW)
+include(CMP0119-Common.cmake)
+
+enable_language(CXX)
+add_executable(AltExtCXX AltExtCXX.zzz)
+set_property(SOURCE AltExtCXX.zzz PROPERTY LANGUAGE CXX)
diff --git a/Tests/RunCMake/CMP0119/CMP0119-OLD-build-result.txt b/Tests/RunCMake/CMP0119/CMP0119-OLD-build-result.txt
new file mode 100644
index 000000000..d197c913c
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-OLD-build-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/CMP0119/CMP0119-OLD-build-stderr.txt b/Tests/RunCMake/CMP0119/CMP0119-OLD-build-stderr.txt
new file mode 100644
index 000000000..8d98f9deb
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-OLD-build-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/CMP0119/CMP0119-OLD.cmake b/Tests/RunCMake/CMP0119/CMP0119-OLD.cmake
new file mode 100644
index 000000000..9eaa20061
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0119 OLD)
+include(CMP0119-Common.cmake)
diff --git a/Tests/RunCMake/CMP0119/CMP0119-WARN-build-result.txt b/Tests/RunCMake/CMP0119/CMP0119-WARN-build-result.txt
new file mode 100644
index 000000000..d197c913c
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-WARN-build-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/CMP0119/CMP0119-WARN-build-stderr.txt b/Tests/RunCMake/CMP0119/CMP0119-WARN-build-stderr.txt
new file mode 100644
index 000000000..8d98f9deb
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-WARN-build-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/CMP0119/CMP0119-WARN.cmake b/Tests/RunCMake/CMP0119/CMP0119-WARN.cmake
new file mode 100644
index 000000000..00281e9b7
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/CMP0119-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0119-Common.cmake)
diff --git a/Tests/RunCMake/CMP0119/CMakeLists.txt b/Tests/RunCMake/CMP0119/CMakeLists.txt
new file mode 100644
index 000000000..ab1a20c7e
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/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/CMP0119/RunCMakeTest.cmake b/Tests/RunCMake/CMP0119/RunCMakeTest.cmake
new file mode 100644
index 000000000..e547ef5a2
--- /dev/null
+++ b/Tests/RunCMake/CMP0119/RunCMakeTest.cmake
@@ -0,0 +1,17 @@
+include(RunCMake)
+
+function(run_CMP0119 status)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0119-${status}-build)
+ run_cmake(CMP0119-${status})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(CMP0119-${status}-build "${CMAKE_COMMAND}" --build . --config Debug)
+endfunction()
+
+if(NOT RunCMake_GENERATOR MATCHES "Visual Studio|Xcode" AND
+ NOT CMAKE_C_COMPILER_ID MATCHES "(Borland|Embarcadero|Watcom)")
+ run_CMP0119(WARN)
+ run_CMP0119(OLD)
+endif()
+if((CMAKE_C_COMPILER_ID MATCHES "(GNU|Clang|MSVC|Borland|Embarcadero|Intel|TI)"))
+ run_CMP0119(NEW)
+endif()
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 8dcfe84f5..91fe6ca71 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -125,6 +125,12 @@ if(CMake_TEST_CUDA)
endif()
add_RunCMake_test(CMP0106)
add_RunCMake_test(CMP0111)
+add_RunCMake_test(CMP0115)
+if(CMAKE_GENERATOR MATCHES "Ninja")
+ add_RunCMake_test(CMP0116)
+endif()
+add_RunCMake_test(CMP0118)
+add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
# The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
@@ -175,6 +181,10 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
)
endif()
+add_RunCMake_test(ABI -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
+set_property(TEST RunCMake.ABI APPEND
+ PROPERTY LABELS "CUDA")
+
add_RunCMake_test(AndroidTestUtilities)
if(CMake_TEST_APPLE_SILICON)
add_RunCMake_test(AppleSilicon)
@@ -187,6 +197,9 @@ if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND)
set(autogen_with_qt5 TRUE)
endif ()
add_RunCMake_test(Autogen -Dwith_qt5=${autogen_with_qt5})
+
+add_RunCMake_test(ArtifactOutputDirs)
+
if(NOT DEFINED CMake_TEST_BuildDepends_GNU_AS
AND CMAKE_C_COMPILER_ID STREQUAL "GNU"
AND CMAKE_GENERATOR MATCHES "^Ninja"
@@ -198,14 +211,16 @@ if(NOT DEFINED CMake_TEST_BuildDepends_GNU_AS
set(CMake_TEST_BuildDepends_GNU_AS "${_gnu_as}")
endif()
endif()
+
add_RunCMake_test(BuildDepends
+ -DMSVC_VERSION=${MSVC_VERSION}
+ -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
-DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS}
)
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
add_RunCMake_test(Byproducts)
endif()
add_RunCMake_test(CMakeRoleGlobalProperty)
-add_RunCMake_test(CMakeRelease -DCMake_TEST_JQ=${CMake_TEST_JQ})
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
add_RunCMake_test(CompilerChange)
endif()
@@ -224,6 +239,9 @@ add_RunCMake_test(FileAPI -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
add_RunCMake_test(FindBoost)
add_RunCMake_test(FindLua)
add_RunCMake_test(FindOpenGL)
+if(CMake_TEST_FindOpenSSL)
+ add_RunCMake_test(FindOpenSSL)
+endif()
if(CMake_TEST_UseSWIG)
add_RunCMake_test(FindSWIG)
add_RunCMake_test(UseSWIG -DCMake_TEST_FindPython=${CMake_TEST_FindPython})
@@ -253,11 +271,12 @@ add_RunCMake_test(Graphviz)
add_RunCMake_test(TargetPropertyGeneratorExpressions)
add_RunCMake_test(Languages)
add_RunCMake_test(LinkStatic)
-if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|XL|XLClang)$")
+if(CMAKE_CXX_COMPILER_ID MATCHES "^(Cray|PGI|NVHPC|XL|XLClang)$")
add_RunCMake_test(MetaCompileFeatures)
endif()
if(MSVC)
add_RunCMake_test(MSVCRuntimeLibrary)
+ add_RunCMake_test(MSVCRuntimeTypeInfo)
add_RunCMake_test(MSVCWarningFlags)
endif()
add_RunCMake_test(ObjectLibrary)
@@ -275,6 +294,7 @@ add_RunCMake_test(ToolchainFile)
add_RunCMake_test(find_dependency)
add_RunCMake_test(CompileDefinitions)
add_RunCMake_test(CompileFeatures)
+add_RunCMake_test(Policy)
add_RunCMake_test(PolicyScope)
add_RunCMake_test(WriteBasicConfigVersionFile)
add_RunCMake_test(WriteCompilerDetectionHeader)
@@ -315,7 +335,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)
add_RunCMake_test(continue)
add_executable(color_warning color_warning.c)
add_executable(fake_build_command fake_build_command.c)
@@ -338,6 +358,9 @@ add_RunCMake_test(ctest_upload)
add_RunCMake_test(ctest_fixtures)
add_RunCMake_test(file)
add_RunCMake_test(file-CHMOD)
+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)
@@ -511,6 +534,7 @@ endif()
if(XCODE_VERSION)
add_RunCMake_test(XcodeProject -DXCODE_VERSION=${XCODE_VERSION})
+ add_RunCMake_test(XcodeProject-Embed)
# 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.
@@ -571,7 +595,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)"
endif()
-add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCYGWIN=${CYGWIN} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE})
+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(CommandLineTar)
if(CMAKE_PLATFORM_NO_VERSIONED_SONAME OR (NOT CMAKE_SHARED_LIBRARY_SONAME_FLAG AND NOT CMAKE_SHARED_LIBRARY_SONAME_C_FLAG))
@@ -780,6 +805,12 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
add_RunCMake_test("UnityBuild")
add_RunCMake_test(CMakePresets -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA})
+add_RunCMake_test(CMakePresetsBuild -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA})
+add_RunCMake_test(CMakePresetsTest -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA})
+
+if(${CMAKE_GENERATOR} MATCHES "Make|Ninja")
+ add_RunCMake_test(TransformDepfile)
+endif()
if(WIN32)
add_RunCMake_test(Win32GenEx)
diff --git a/Tests/RunCMake/CMakePresets/CMakePresets.json.in b/Tests/RunCMake/CMakePresets/CMakePresets.json.in
index e65c1a920..c6f943cb0 100644
--- a/Tests/RunCMake/CMakePresets/CMakePresets.json.in
+++ b/Tests/RunCMake/CMakePresets/CMakePresets.json.in
@@ -128,7 +128,13 @@
{
"name": "Good Spaces",
"generator": "@RunCMake_GENERATOR@",
- "binaryDir": "${sourceDir}/build"
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "GOOD_SPACES": {
+ "type": "STRING",
+ "value": "1"
+ }
+ }
},
{
"name": "GoodWindowsBackslash",
diff --git a/Tests/RunCMake/CMakePresets/GoodSpaces-stdout.txt b/Tests/RunCMake/CMakePresets/GoodSpaces-stdout.txt
new file mode 100644
index 000000000..d106c4578
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodSpaces-stdout.txt
@@ -0,0 +1,3 @@
+Preset CMake variables:
+
+ GOOD_SPACES:STRING="1"
diff --git a/Tests/RunCMake/CMakePresets/GoodSpacesEq-stdout.txt b/Tests/RunCMake/CMakePresets/GoodSpacesEq-stdout.txt
new file mode 100644
index 000000000..d106c4578
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodSpacesEq-stdout.txt
@@ -0,0 +1,3 @@
+Preset CMake variables:
+
+ GOOD_SPACES:STRING="1"
diff --git a/Tests/RunCMake/CMakePresets/GoodSpacesEq.cmake b/Tests/RunCMake/CMakePresets/GoodSpacesEq.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodSpacesEq.cmake
diff --git a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
index 1758f334d..60d6adbd9 100644
--- a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
@@ -1,5 +1,5 @@
^Not searching for unused variables given on the command line\.
-Available presets:
+Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
index 1758f334d..60d6adbd9 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
@@ -1,5 +1,5 @@
^Not searching for unused variables given on the command line\.
-Available presets:
+Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
index 1758f334d..60d6adbd9 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
@@ -1,5 +1,5 @@
^Not searching for unused variables given on the command line\.
-Available presets:
+Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
index 1758f334d..60d6adbd9 100644
--- a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
+++ b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
@@ -1,5 +1,5 @@
^Not searching for unused variables given on the command line\.
-Available presets:
+Available configure presets:
"zzzzzz" - Sleepy
"aaaaaaaa" - Screaming
diff --git a/Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt
index aef30d2af..a53682da2 100644
--- a/Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt
+++ b/Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt
@@ -1 +1,2 @@
-^CMake Error: No preset specified for --preset$
+^CMake Error: No preset specified for --preset
+CMake Error: Run 'cmake --help' for all supported options.$
diff --git a/Tests/RunCMake/CMakePresets/NoPresetArgumentEq-result.txt b/Tests/RunCMake/CMakePresets/NoPresetArgumentEq-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetArgumentEq-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoPresetArgumentEq-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetArgumentEq-stderr.txt
new file mode 100644
index 000000000..a53682da2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetArgumentEq-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: No preset specified for --preset
+CMake Error: Run 'cmake --help' for all supported options.$
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
index 1f399fe10..dfc56eeb7 100644
--- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -9,21 +9,7 @@ endif()
set(RunCMake-check-file check.cmake)
-function(validate_schema file expected_result)
- execute_process(
- COMMAND "${PYTHON_EXECUTABLE}" "${RunCMake_SOURCE_DIR}/validate_schema.py" "${file}"
- RESULT_VARIABLE _result
- OUTPUT_VARIABLE _output
- ERROR_VARIABLE _error
- )
- if(NOT _result STREQUAL expected_result)
- string(REPLACE "\n" "\n" _output_p "${_output}")
- string(REPLACE "\n" "\n" _error_p "${_error}")
- string(APPEND RunCMake_TEST_FAILED "Expected result of validating ${file}: ${expected_result}\nActual result: ${_result}\nOutput:\n${_output_p}\nError:\n${_error_p}")
- endif()
-
- set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
-endfunction()
+include("${RunCMake_SOURCE_DIR}/validate_schema.cmake")
function(run_cmake_presets name)
set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
@@ -158,7 +144,8 @@ run_cmake_presets(GoodBinaryUp)
set(CMakePresets_SOURCE_ARG "../GoodBinaryRelative")
run_cmake_presets(GoodBinaryRelative)
unset(CMakePresets_SOURCE_ARG)
-run_cmake_presets(GoodSpaces "--preset=Good Spaces")
+run_cmake_presets(GoodSpaces "--preset" "Good Spaces")
+run_cmake_presets(GoodSpacesEq "--preset=Good Spaces")
if(WIN32)
run_cmake_presets(GoodWindowsBackslash)
endif()
@@ -221,7 +208,8 @@ endif()
# Test bad command line arguments
run_cmake_presets(NoSuchPreset)
-run_cmake_presets(NoPresetArgument --preset=)
+run_cmake_presets(NoPresetArgument --preset)
+run_cmake_presets(NoPresetArgumentEq --preset= -DA=B)
run_cmake_presets(UseHiddenPreset)
# Test CMakeUserPresets.json
diff --git a/Tests/RunCMake/CMakePresets/validate_schema.cmake b/Tests/RunCMake/CMakePresets/validate_schema.cmake
new file mode 100644
index 000000000..68b638f16
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/validate_schema.cmake
@@ -0,0 +1,19 @@
+function(validate_schema file expected_result)
+ if (NOT CMakePresets_VALIDATE_SCRIPT_PATH)
+ set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/validate_schema.py")
+ endif()
+
+ execute_process(
+ COMMAND "${PYTHON_EXECUTABLE}" "${CMakePresets_VALIDATE_SCRIPT_PATH}" "${file}"
+ RESULT_VARIABLE _result
+ OUTPUT_VARIABLE _output
+ ERROR_VARIABLE _error
+ )
+ if(NOT _result STREQUAL expected_result)
+ string(REPLACE "\n" "\n " _output_p "${_output}")
+ string(REPLACE "\n" "\n " _error_p "${_error}")
+ string(APPEND RunCMake_TEST_FAILED "Expected result of validating ${file}: ${expected_result}\nActual result: ${_result}\nOutput:\n ${_output_p}\nError:\n ${_error_p}\n")
+ endif()
+
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
diff --git a/Tests/RunCMake/CMakePresetsBuild/CMakeLists.txt.in b/Tests/RunCMake/CMakePresetsBuild/CMakeLists.txt.in
new file mode 100644
index 000000000..129184a89
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/CMakeLists.txt.in
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19)
+project("@CASE_NAME@" NONE)
+include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake")
diff --git a/Tests/RunCMake/CMakePresetsBuild/Good-build-build-other-check.cmake b/Tests/RunCMake/CMakePresetsBuild/Good-build-build-other-check.cmake
new file mode 100644
index 000000000..b2699db83
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Good-build-build-other-check.cmake
@@ -0,0 +1,5 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_environment_variable("TEST_ENV_" "other")
+
+include("${RunCMake_SOURCE_DIR}/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsBuild/Good-build-macros-check.cmake b/Tests/RunCMake/CMakePresetsBuild/Good-build-macros-check.cmake
new file mode 100644
index 000000000..7801c3da5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Good-build-macros-check.cmake
@@ -0,0 +1,14 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+if(RunCMake_GENERATOR STREQUAL "NMake Makefiles JOM")
+ # JOM removes the '$' and content following it.
+else()
+ test_environment_variable("TEST_DOLLAR" "x\\$x")
+endif()
+test_environment_variable("TEST_GENERATOR" "${RunCMake_GENERATOR}")
+test_environment_variable("TEST_PRESET_NAME" "xmacrosx")
+test_environment_variable("TEST_SOURCE_DIR_" "x[^\n]*[/\\\\]Tests[/\\\\]RunCMake[/\\\\]CMakePresetsBuild[/\\\\]Goodx")
+test_environment_variable("TEST_SOURCE_DIR_NAME" "xGoodx")
+test_environment_variable("TEST_SOURCE_PARENT_DIR" "x[^\n]*[/\\\\]Tests[/\\\\]RunCMake[/\\\\]CMakePresetsBuildx")
+
+include("${RunCMake_SOURCE_DIR}/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsBuild/Good-build-noEnvironment-check.cmake b/Tests/RunCMake/CMakePresetsBuild/Good-build-noEnvironment-check.cmake
new file mode 100644
index 000000000..94a54ca9a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Good-build-noEnvironment-check.cmake
@@ -0,0 +1,6 @@
+string(FIND "${actual_stdout}" "TEST_ENV_" TEST_ENV_POS)
+if (NOT TEST_ENV_POS EQUAL -1)
+ message(FATAL_ERROR "Found TEST_ENV_ in environment")
+endif()
+
+include("${RunCMake_SOURCE_DIR}/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsBuild/Good-build-withEnvironment-check.cmake b/Tests/RunCMake/CMakePresetsBuild/Good-build-withEnvironment-check.cmake
new file mode 100644
index 000000000..9c6b5c204
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Good-build-withEnvironment-check.cmake
@@ -0,0 +1,8 @@
+include("${RunCMake_SOURCE_DIR}/TestVariable.cmake")
+
+test_environment_variable("TEST_ENV_" "Environment variable")
+test_environment_variable("TEST_ENV_OVERRIDE_" "Overridden")
+test_environment_variable("TEST_ENV_OVERRIDE_REF" "xOverriddenx")
+test_environment_variable("TEST_ENV_REF" "xEnvironment variablex")
+
+include("${RunCMake_SOURCE_DIR}/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsBuild/Good.cmake b/Tests/RunCMake/CMakePresetsBuild/Good.cmake
new file mode 100644
index 000000000..491d3678a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Good.cmake
@@ -0,0 +1,3 @@
+add_custom_target(good ALL)
+add_custom_command(TARGET good PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E environment)
diff --git a/Tests/RunCMake/CMakePresetsBuild/Good.json.in b/Tests/RunCMake/CMakePresetsBuild/Good.json.in
new file mode 100644
index 000000000..fd43c4e60
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Good.json.in
@@ -0,0 +1,78 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}",
+ "environment": {
+ "TEST_ENV_": "Environment variable",
+ "TEST_ENV_OVERRIDE_": "Environment variable",
+ "TEST_ENV_OVERRIDE_REF": "x$env{TEST_ENV_OVERRIDE_}x"
+ }
+ },
+ {
+ "name": "other",
+ "inherits": "default",
+ "environment": {
+ "TEST_ENV_": "other"
+ }
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "build-default",
+ "hidden": true,
+ "inherits": [],
+ "configurePreset": "default",
+ "vendor": {},
+ "displayName": "",
+ "description": "",
+ "inheritConfigureEnvironment": true,
+ "environment": {},
+ "jobs": 0,
+ "targets": [],
+ "configuration": "",
+ "verbose": true,
+ "nativeToolOptions": []
+ },
+ {
+ "name": "build-other",
+ "configurePreset": "other"
+ },
+ {
+ "name": "withEnvironment",
+ "inherits": "build-default",
+ "environment": {
+ "TEST_ENV_OVERRIDE_": "Overridden",
+ "TEST_ENV_REF": "x$env{TEST_ENV_}x",
+ "TEST_ENV_OVERRIDE_REF": "x$env{TEST_ENV_OVERRIDE_}x"
+ }
+ },
+ {
+ "name": "noEnvironment",
+ "inherits": "build-default",
+ "inheritConfigureEnvironment": false
+ },
+ {
+ "name": "macros",
+ "inherits": "build-default",
+ "inheritConfigureEnvironment": false,
+ "environment": {
+ "TEST_SOURCE_DIR_": "x${sourceDir}x",
+ "TEST_SOURCE_PARENT_DIR": "x${sourceParentDir}x",
+ "TEST_SOURCE_DIR_NAME": "x${sourceDirName}x",
+ "TEST_PRESET_NAME": "x${presetName}x",
+ "TEST_GENERATOR": "x${generator}x",
+ "TEST_DOLLAR": "x${dollar}x"
+ }
+ },
+ {
+ "name": "vendorObject",
+ "configurePreset": "default",
+ "vendor": {
+ "example.com": "value"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-result.txt b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-stderr.txt
new file mode 100644
index 000000000..7c3255d0b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-badConfigurePreset-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: No such configure preset in [^
+]*/Tests/RunCMake/CMakePresetsBuild/Invalid: "dne"
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-result.txt b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-stderr.txt
new file mode 100644
index 000000000..f10c7b85e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-hidden-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Cannot use hidden build preset in [^
+]*/Tests/RunCMake/CMakePresetsBuild/Invalid: "hidden"
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-result.txt b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-stderr.txt
new file mode 100644
index 000000000..a3b951f7b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid-build-vendorMacro-stderr.txt
@@ -0,0 +1 @@
+CMake Error: Could not evaluate build preset "vendorMacro": Invalid macro expansion
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid.cmake b/Tests/RunCMake/CMakePresetsBuild/Invalid.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid.cmake
diff --git a/Tests/RunCMake/CMakePresetsBuild/Invalid.json.in b/Tests/RunCMake/CMakePresetsBuild/Invalid.json.in
new file mode 100644
index 000000000..c22fdec6c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/Invalid.json.in
@@ -0,0 +1,23 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "hidden",
+ "hidden": true
+ },
+ {
+ "name": "vendorMacro",
+ "configurePreset": "default",
+ "environment": {
+ "TEST": "$vendor{bad.TEST}"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-result.txt b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt
new file mode 100644
index 000000000..303632e54
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-build-badConfigurePreset-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset: Invalid "configurePreset" field
diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-result.txt b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt
new file mode 100644
index 000000000..303632e54
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset-configure-default-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset: Invalid "configurePreset" field
diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.cmake b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.cmake
diff --git a/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.json.in b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.json.in
new file mode 100644
index 000000000..c0429d524
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/InvalidConfigurePreset.json.in
@@ -0,0 +1,16 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "badConfigurePreset",
+ "configurePreset": "dne"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt b/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt
new file mode 100644
index 000000000..4d30707d4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/ListPresets-build-x-stdout.txt
@@ -0,0 +1,5 @@
+Available build presets:
+
+ "build-default" - build-default displayName
+ "empty"
+ "display" - display displayName
diff --git a/Tests/RunCMake/CMakePresetsBuild/ListPresets.cmake b/Tests/RunCMake/CMakePresetsBuild/ListPresets.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/ListPresets.cmake
diff --git a/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in b/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in
new file mode 100644
index 000000000..3f5e02c25
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/ListPresets.json.in
@@ -0,0 +1,31 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "build-default",
+ "configurePreset": "default",
+ "displayName": "build-default displayName",
+ "description": "build-default description"
+ },
+ {
+ "name": "empty",
+ "inherits": "build-default"
+ },
+ {
+ "name": "display",
+ "inherits": "build-default",
+ "displayName": "display displayName"
+ },
+ {
+ "name": "hidden",
+ "hidden": true
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-result.txt b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt
new file mode 100644
index 000000000..fcb37bc43
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset-build-noConfigurePreset-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset: Invalid preset
diff --git a/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.cmake b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.cmake
diff --git a/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.json.in b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.json.in
new file mode 100644
index 000000000..81b2cdebc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/NoConfigurePreset.json.in
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "noConfigurePreset"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-result.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt
new file mode 100644
index 000000000..d6ae62d6a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported-build-x-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported: File version must be 2 or higher for build and test preset support.
diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported.json.in b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported.json.in
new file mode 100644
index 000000000..0028239b5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/PresetsUnsupported.json.in
@@ -0,0 +1,7 @@
+{
+ "version": 1,
+ "configurePresets": [
+ ],
+ "buildPresets": [
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
new file mode 100644
index 000000000..2559b12a7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
@@ -0,0 +1,76 @@
+include(RunCMake)
+
+# Presets do not support legacy VS generator name architecture suffix.
+if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ")
+ set(RunCMake_GENERATOR "${CMAKE_MATCH_1}")
+endif()
+
+function(run_cmake_build_presets name CMakePresetsBuild_CONFIGURE_PRESETS CMakePresetsBuild_BUILD_PRESETS)
+ set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build")
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+
+ set(RunCMake_TEST_NO_CLEAN TRUE)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ set(CASE_NAME "${name}")
+ set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}")
+ configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY)
+
+ if(NOT CMakePresetsBuild_FILE)
+ set(CMakePresetsBuild_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in")
+ endif()
+ if(EXISTS "${CMakePresetsBuild_FILE}")
+ configure_file("${CMakePresetsBuild_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY)
+ endif()
+
+ if(NOT CMakeUserPresets_FILE)
+ set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in")
+ endif()
+ if(EXISTS "${CMakeUserPresets_FILE}")
+ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY)
+ endif()
+
+ if (NOT CMakePresetsBuild_BUILD_ONLY)
+ foreach(CONFIGURE_PRESET ${CMakePresetsBuild_CONFIGURE_PRESETS})
+ run_cmake_command("${name}-configure-${CONFIGURE_PRESET}"
+ "${CMAKE_COMMAND}" "--preset" "${CONFIGURE_PRESET}")
+ endforeach()
+ endif()
+
+ set(eq 0)
+ foreach(BUILD_PRESET ${CMakePresetsBuild_BUILD_PRESETS})
+ if (EXISTS "${RunCMake_SOURCE_DIR}/${name}-build-${BUILD_PRESET}-check.cmake")
+ set(RunCMake-check-file "${name}-build-${BUILD_PRESET}-check.cmake")
+ else()
+ set(RunCMake-check-file "check.cmake")
+ endif()
+
+ if(eq)
+ run_cmake_command(${name}-build-${BUILD_PRESET}
+ ${CMAKE_COMMAND} "--build" "--preset=${BUILD_PRESET}" ${ARGN})
+ set(eq 0)
+ else()
+ run_cmake_command(${name}-build-${BUILD_PRESET}
+ ${CMAKE_COMMAND} "--build" "--preset" "${BUILD_PRESET}" ${ARGN})
+ set(eq 1)
+ endif()
+ endforeach()
+endfunction()
+
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
+
+run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject")
+run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset")
+
+set(CMakePresetsBuild_BUILD_ONLY 1)
+run_cmake_build_presets(ListPresets "x" "x" "--list-presets")
+run_cmake_build_presets(NoConfigurePreset "x" "noConfigurePreset")
+run_cmake_build_presets(Invalid "x" "hidden;vendorMacro")
+
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
+run_cmake_build_presets(PresetsUnsupported "x" "x")
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
+set(CMakePresetsBuild_BUILD_ONLY 0)
diff --git a/Tests/RunCMake/CMakePresetsBuild/TestVariable.cmake b/Tests/RunCMake/CMakePresetsBuild/TestVariable.cmake
new file mode 100644
index 000000000..3113dcc7c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/TestVariable.cmake
@@ -0,0 +1,14 @@
+function(test_environment_variable name expected_value)
+ string(REGEX MATCH "${name}=([^\n]*)" REGEX_RESULT "${actual_stdout}")
+ if(NOT REGEX_RESULT)
+ string(APPEND RunCMake_TEST_FAILED "Environment variable '${name}' is not defined.\n")
+ else()
+ set(actual_value "${CMAKE_MATCH_1}")
+ if(NOT "${actual_value}" MATCHES "${expected_value}")
+ string(REPLACE "\n" "\n " _actual "${expected_value}")
+ string(REPLACE "\n" "\n " _expect "${actual_value}")
+ string(APPEND RunCMake_TEST_FAILED "Expected value of environment variable '${name}':\n ${_expect}\nActual value:\n ${_actual}\n")
+ endif()
+ endif()
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
+endfunction()
diff --git a/Tests/RunCMake/CMakePresetsBuild/check.cmake b/Tests/RunCMake/CMakePresetsBuild/check.cmake
new file mode 100644
index 000000000..e79c4f12a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsBuild/check.cmake
@@ -0,0 +1,3 @@
+set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.py")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.cmake")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsTest/CMakeLists.txt.in b/Tests/RunCMake/CMakePresetsTest/CMakeLists.txt.in
new file mode 100644
index 000000000..129184a89
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/CMakeLists.txt.in
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19)
+project("@CASE_NAME@" NONE)
+include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake")
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-indexFile.txt b/Tests/RunCMake/CMakePresetsTest/Good-indexFile.txt
new file mode 100644
index 000000000..4ac231444
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-indexFile.txt
@@ -0,0 +1 @@
+2,,2
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt
new file mode 100644
index 000000000..c281c81ac
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-config-debug-stdout.txt
@@ -0,0 +1,5 @@
+Test project [^
+]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
+ Start 6: debug-only
+.*
+100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt
new file mode 100644
index 000000000..66bfd2274
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-config-release-stdout.txt
@@ -0,0 +1,5 @@
+Test project [^
+]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
+ Start 6: release-only
+.*
+100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt
new file mode 100644
index 000000000..5e990de1a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-exclude-stdout.txt
@@ -0,0 +1,7 @@
+Test project [^
+]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
+ Start 3: testc
+.*
+ Start 4: testd
+.*
+100% tests passed, 0 tests failed out of 2
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt
new file mode 100644
index 000000000..2df6fcbd8
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-index-stdout.txt
@@ -0,0 +1,7 @@
+Test project [^
+]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
+ Start 1: testa
+.*
+ Start 3: testc
+.*
+100% tests passed, 0 tests failed out of 2
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt
new file mode 100644
index 000000000..1366876c1
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-indexFile-stdout.txt
@@ -0,0 +1,7 @@
+Test project [^
+]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
+ Start 2: testb
+.*
+ Start 4: testd
+.*
+100% tests passed, 0 tests failed out of 2
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt
new file mode 100644
index 000000000..8b4845ef0
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-noEnvironment-stdout.txt
@@ -0,0 +1,8 @@
+Test project [^
+]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
+.*
+ Start 5: test-env
+.*
+5: TEST_ENV_REF=xx
+.*
+100% tests passed, 0 tests failed out of 1
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-showOnly-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Good-test-showOnly-stdout.txt
new file mode 100644
index 000000000..67ddd4fbf
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-test-showOnly-stdout.txt
@@ -0,0 +1,8 @@
+Test project [^
+]*/Tests/RunCMake/CMakePresetsTest/Good/build/default
+ Test #1: testa
+ Test #2: testb
+ Test #3: testc
+ Test #4: testd
+
+Total Tests: 4
diff --git a/Tests/RunCMake/CMakePresetsTest/Good-withEnvironment-check.cmake b/Tests/RunCMake/CMakePresetsTest/Good-withEnvironment-check.cmake
new file mode 100644
index 000000000..0c1955615
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good-withEnvironment-check.cmake
@@ -0,0 +1,8 @@
+include("${RunCMake_SOURCE_DIR}/../CMakePresetsBuild/TestVariable.cmake")
+
+test_environment_variable("TEST_ENV" "Environment variable")
+test_environment_variable("TEST_ENV_OVERRIDE" "Override")
+test_environment_variable("TEST_ENV_OVERRIDE_REF" "xOverridex")
+test_environment_variable("TEST_ENV_REF" "xEnvironment variablex")
+
+include("${RunCMake_SOURCE_DIR}/check.cmake")
diff --git a/Tests/RunCMake/CMakePresetsTest/Good.cmake b/Tests/RunCMake/CMakePresetsTest/Good.cmake
new file mode 100644
index 000000000..0a6cf57f3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good.cmake
@@ -0,0 +1,27 @@
+enable_testing()
+add_test(testa ${CMAKE_COMMAND} -E echo testa)
+add_test(testb ${CMAKE_COMMAND} -E echo testb)
+add_test(testc ${CMAKE_COMMAND} -E echo testc)
+add_test(testd ${CMAKE_COMMAND} -E echo testd)
+
+set_tests_properties(testa testb testc testd
+ PROPERTIES LABELS "echo")
+set_property(TEST testa testb
+ APPEND PROPERTY LABELS ab)
+set_property(TEST testb testc
+ APPEND PROPERTY LABELS bc)
+set_property(TEST testc testd
+ APPEND PROPERTY LABELS cd)
+
+add_test(test-env ${CMAKE_COMMAND} -E environment | sort)
+set_tests_properties(test-env PROPERTIES LABELS "env")
+
+add_test(NAME debug-only
+ COMMAND ${CMAKE_COMMAND} -E echo debug-only
+ CONFIGURATIONS Debug)
+add_test(NAME release-only
+ COMMAND ${CMAKE_COMMAND} -E echo release-only
+ CONFIGURATIONS Release)
+
+set_tests_properties(debug-only release-only
+ PROPERTIES LABELS "config")
diff --git a/Tests/RunCMake/CMakePresetsTest/Good.json.in b/Tests/RunCMake/CMakePresetsTest/Good.json.in
new file mode 100644
index 000000000..57be5a503
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Good.json.in
@@ -0,0 +1,175 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}",
+ "environment": {
+ "TEST_ENV": "Environment variable",
+ "TEST_ENV_OVERRIDE": "Overridden environment variable"
+ }
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "build-default-debug",
+ "configurePreset": "default",
+ "configuration": "Debug"
+ },
+ {
+ "name": "build-default-release",
+ "inherits": "build-default-debug",
+ "configuration": "Release"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "minimal",
+ "configurePreset": "default"
+ },
+ {
+ "name": "defaults",
+ "hidden": false,
+ "inherits": [],
+ "vendor": {},
+ "displayName": "",
+ "description": "",
+ "environment": {},
+ "configurePreset": "default",
+ "inheritConfigureEnvironment": true,
+ "configuration": "",
+ "overwriteConfigurationFile": [],
+ "output": {
+ "shortProgress": false,
+ "verbosity": "default",
+ "debug": false,
+ "outputOnFailure": false,
+ "quiet": false,
+ "outputLogFile": "",
+ "labelSummary": true,
+ "subprojectSummary": true
+ },
+ "filter": {
+ "include": {
+ "name": "",
+ "label": "",
+ "useUnion": false,
+ "index": ""
+ },
+ "exclude": {
+ "name": "",
+ "label": "",
+ "fixtures": {
+ "any": "",
+ "setup": "",
+ "cleanup": ""
+ }
+ }
+ },
+ "execution": {
+ "stopOnFailure": false,
+ "enableFailover": false,
+ "jobs": 0,
+ "resourceSpecFile": "",
+ "showOnly": "human",
+ "repeat": {
+ "mode": "until-pass",
+ "count": 1
+ },
+ "interactiveDebugging": false,
+ "scheduleRandom": false,
+ "noTestsAction": "default"
+ }
+ },
+ {
+ "name": "noEnvironment",
+ "configurePreset": "default",
+ "inheritConfigureEnvironment": false,
+ "environment": {
+ "TEST_ENV_REF": "x$env{TEST_ENV}x"
+ },
+ "filter": {
+ "include": {
+ "name": "test-env"
+ }
+ },
+ "output": {
+ "verbosity": "verbose"
+ }
+ },
+ {
+ "name": "withEnvironment",
+ "inherits": "noEnvironment",
+ "inheritConfigureEnvironment": true,
+ "environment": {
+ "TEST_ENV_OVERRIDE": "Override",
+ "TEST_ENV_OVERRIDE_REF": "x$env{TEST_ENV_OVERRIDE}x",
+ "TEST_ENV_REF": "x$env{TEST_ENV}x"
+ }
+ },
+ {
+ "name": "config-debug",
+ "inherits": "minimal",
+ "configuration": "Debug",
+ "filter": {
+ "include": {
+ "label": "config"
+ }
+ }
+ },
+ {
+ "name": "config-release",
+ "inherits": "minimal",
+ "configuration": "Release",
+ "filter": {
+ "include": {
+ "label": "config"
+ }
+ }
+ },
+ {
+ "name": "exclude",
+ "inherits": "minimal",
+ "filter": {
+ "exclude": {
+ "name": "test-env",
+ "label": "(ab|config)"
+ }
+ }
+ },
+ {
+ "name": "index",
+ "inherits": "minimal",
+ "filter": {
+ "include": {
+ "index": {
+ "end": 4,
+ "stride": 2
+ }
+ }
+ }
+ },
+ {
+ "name": "indexFile",
+ "inherits": "minimal",
+ "filter": {
+ "include": {
+ "index": "${sourceDir}/Good-indexFile.txt"
+ }
+ }
+ },
+ {
+ "name": "showOnly",
+ "inherits": "minimal",
+ "filter": {
+ "include": {
+ "label": "echo"
+ }
+ },
+ "execution": {
+ "showOnly": "human"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-result.txt b/Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-stderr.txt
new file mode 100644
index 000000000..9cf998722
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid-test-badConfigurePreset-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: No such configure preset in [^
+]*/Tests/RunCMake/CMakePresetsTest/Invalid: "dne"
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-result.txt b/Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-stderr.txt b/Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-stderr.txt
new file mode 100644
index 000000000..41b1b4e04
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid-test-hidden-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Cannot use hidden test preset in [^
+]*/Tests/RunCMake/CMakePresetsTest/Invalid: "hidden"
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-result.txt b/Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-stderr.txt b/Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-stderr.txt
new file mode 100644
index 000000000..ed5bb98e2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid-test-vendorMacro-stderr.txt
@@ -0,0 +1 @@
+CMake Error: Could not evaluate test preset "vendorMacro": Invalid macro expansion
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid.cmake b/Tests/RunCMake/CMakePresetsTest/Invalid.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid.cmake
diff --git a/Tests/RunCMake/CMakePresetsTest/Invalid.json.in b/Tests/RunCMake/CMakePresetsTest/Invalid.json.in
new file mode 100644
index 000000000..cfcf4b7ec
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/Invalid.json.in
@@ -0,0 +1,23 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "hidden",
+ "hidden": true
+ },
+ {
+ "name": "vendorMacro",
+ "configurePreset": "default",
+ "environment": {
+ "TEST": "$vendor{bad.TEST}"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-result.txt b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt
new file mode 100644
index 000000000..3d7cdd075
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-configure-default-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset: Invalid "configurePreset" field
diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-result.txt b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt
new file mode 100644
index 000000000..3d7cdd075
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset-test-badConfigurePreset-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset: Invalid "configurePreset" field
diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.cmake b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.cmake
diff --git a/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.json.in b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.json.in
new file mode 100644
index 000000000..e305c4240
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/InvalidConfigurePreset.json.in
@@ -0,0 +1,16 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "badConfigurePreset",
+ "configurePreset": "dne"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/ListPresets-test-x-stdout.txt b/Tests/RunCMake/CMakePresetsTest/ListPresets-test-x-stdout.txt
new file mode 100644
index 000000000..46ffbcfb6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/ListPresets-test-x-stdout.txt
@@ -0,0 +1,12 @@
+Available test presets:
+
+ "minimal"
+ "defaults"
+ "noEnvironment"
+ "withEnvironment"
+ "config-debug"
+ "config-release"
+ "exclude"
+ "index"
+ "indexFile"
+ "showOnly"
diff --git a/Tests/RunCMake/CMakePresetsTest/ListPresets.cmake b/Tests/RunCMake/CMakePresetsTest/ListPresets.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/ListPresets.cmake
diff --git a/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-result.txt b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt
new file mode 100644
index 000000000..b167f68ef
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset-test-noConfigurePreset-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset: Invalid preset
diff --git a/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.cmake b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.cmake
diff --git a/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.json.in b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.json.in
new file mode 100644
index 000000000..4591cc8b9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoConfigurePreset.json.in
@@ -0,0 +1,15 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "noConfigurePreset"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-result.txt b/Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-result.txt
new file mode 100644
index 000000000..45a4fb75d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-stderr.txt b/Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-stderr.txt
new file mode 100644
index 000000000..eafba1c69
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoTestsAction-test-noTestsAction-stderr.txt
@@ -0,0 +1 @@
+No tests were found!!!
diff --git a/Tests/RunCMake/CMakePresetsTest/NoTestsAction.cmake b/Tests/RunCMake/CMakePresetsTest/NoTestsAction.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoTestsAction.cmake
diff --git a/Tests/RunCMake/CMakePresetsTest/NoTestsAction.json.in b/Tests/RunCMake/CMakePresetsTest/NoTestsAction.json.in
new file mode 100644
index 000000000..20a50d6ce
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/NoTestsAction.json.in
@@ -0,0 +1,19 @@
+{
+ "version": 2,
+ "configurePresets": [
+ {
+ "name": "default",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/${presetName}"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "noTestsAction",
+ "configurePreset": "default",
+ "execution": {
+ "noTestsAction": "error"
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-result.txt b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt
new file mode 100644
index 000000000..eb0ec1a22
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported-test-x-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error: Could not read presets from [^
+]*Tests/RunCMake/CMakePresetsTest/PresetsUnsupported: File version must be 2 or higher for build and test preset support.
diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported.json.in b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported.json.in
new file mode 100644
index 000000000..ff1b00057
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/PresetsUnsupported.json.in
@@ -0,0 +1,7 @@
+{
+ "version": 1,
+ "configurePresets": [
+ ],
+ "testPresets": [
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
new file mode 100644
index 000000000..c93dff36f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
@@ -0,0 +1,104 @@
+include(RunCMake)
+
+# Presets do not support legacy VS generator name architecture suffix.
+if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ")
+ set(RunCMake_GENERATOR "${CMAKE_MATCH_1}")
+endif()
+
+function(run_cmake_test_presets name CMakePresetsTest_CONFIGURE_PRESETS CMakePresetsTest_BUILD_PRESETS CMakePresetsTest_TEST_PRESETS)
+ set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build")
+ set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+
+ set(RunCMake_TEST_NO_CLEAN TRUE)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ set(CASE_NAME "${name}")
+ set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}")
+ configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY)
+
+ if(NOT CMakePresetsTest_FILE)
+ set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in")
+ endif()
+ if(EXISTS "${CMakePresetsTest_FILE}")
+ configure_file("${CMakePresetsTest_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY)
+ endif()
+
+ if(NOT CMakeUserPresets_FILE)
+ set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in")
+ endif()
+ if(EXISTS "${CMakeUserPresets_FILE}")
+ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY)
+ endif()
+
+ foreach(ASSET ${CMakePresetsTest_ASSETS})
+ configure_file("${RunCMake_SOURCE_DIR}/${ASSET}" "${RunCMake_TEST_SOURCE_DIR}" COPYONLY)
+ endforeach()
+
+ if (NOT CMakePresetsTest_NO_CONFIGURE)
+ foreach(CONFIGURE_PRESET ${CMakePresetsTest_CONFIGURE_PRESETS})
+ run_cmake_command("${name}-configure-${CONFIGURE_PRESET}"
+ "${CMAKE_COMMAND}" "--preset" "${CONFIGURE_PRESET}")
+ endforeach()
+ endif()
+
+ if (NOT CMakePresetsTest_NO_BUILD)
+ foreach(BUILD_PRESET ${CMakePresetsTest_BUILD_PRESETS})
+ run_cmake_command("${name}-build-${BUILD_PRESET}"
+ "${CMAKE_COMMAND}" "--build" "--preset" "${BUILD_PRESET}")
+ endforeach()
+ endif()
+
+ set(eq 0)
+ foreach(TEST_PRESET ${CMakePresetsTest_TEST_PRESETS})
+ if (EXISTS "${RunCMake_SOURCE_DIR}/${name}-test-${TEST_PRESET}-check.cmake")
+ set(RunCMake-check-file "${name}-test-${TEST_PRESET}-check.cmake")
+ else()
+ set(RunCMake-check-file "check.cmake")
+ endif()
+
+ if(eq)
+ run_cmake_command(${name}-test-${TEST_PRESET}
+ ${CMAKE_CTEST_COMMAND} "--preset=${TEST_PRESET}" ${ARGN})
+ set(eq 0)
+ else()
+ run_cmake_command(${name}-test-${TEST_PRESET}
+ ${CMAKE_CTEST_COMMAND} "--preset" "${TEST_PRESET}" ${ARGN})
+ set(eq 1)
+ endif()
+ endforeach()
+endfunction()
+
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
+set(CMakePresetsTest_NO_BUILD 1)
+
+set(CMakePresetsTest_ASSETS "Good-indexFile.txt")
+set(GoodTestPresets
+ "minimal;defaults;noEnvironment;withEnvironment"
+ "config-debug;config-release"
+ "exclude;index;indexFile;showOnly")
+run_cmake_test_presets(Good
+ "default"
+ ""
+ "${GoodTestPresets}")
+unset(CMakePresetsTest_ASSETS)
+
+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")
+unset(CMakePresetsTest_FILE)
+
+run_cmake_test_presets(NoConfigurePreset "" "" "noConfigurePreset")
+run_cmake_test_presets(NoTestsAction "default" "" "noTestsAction")
+run_cmake_test_presets(Invalid "" "" "hidden;vendorMacro")
+
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 1)
+run_cmake_test_presets(PresetsUnsupported "" "" "x")
+set(CMakePresets_SCHEMA_EXPECTED_RESULT 0)
+set(CMakePresetsTest_NO_CONFIGURE 0)
+
+set(CMakePresetsTest_NO_BUILD 0)
diff --git a/Tests/RunCMake/CMakePresetsTest/check.cmake b/Tests/RunCMake/CMakePresetsTest/check.cmake
new file mode 100644
index 000000000..e79c4f12a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresetsTest/check.cmake
@@ -0,0 +1,3 @@
+set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.py")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.cmake")
+include("${RunCMake_SOURCE_DIR}/../CMakePresets/check.cmake")
diff --git a/Tests/RunCMake/CMakeRelease/FileTable-stdout.txt b/Tests/RunCMake/CMakeRelease/FileTable-stdout.txt
deleted file mode 100644
index 011673fa2..000000000
--- a/Tests/RunCMake/CMakeRelease/FileTable-stdout.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-^-- query: \.version \| \.major , \.minor , \.patch , \.suffix, \.string
-1
-2
-3
-"rc4"
-"@version@"
--- query: \.files\[\]\.name
-"cmake-@version@-Linux-aarch64\.sh"
-"cmake-@version@-Linux-aarch64\.tar\.gz"
-"cmake-@version@-Linux-x86_64\.sh"
-"cmake-@version@-Linux-x86_64\.tar\.gz"
-"cmake-@version@-macos-universal\.dmg"
-"cmake-@version@-macos-universal\.tar\.gz"
-"cmake-@version@-macos10\.10-universal\.dmg"
-"cmake-@version@-macos10\.10-universal\.tar\.gz"
-"cmake-@version@-win32-x86\.msi"
-"cmake-@version@-win32-x86\.zip"
-"cmake-@version@-win64-x64\.msi"
-"cmake-@version@-win64-x64\.zip"
-"cmake-@version@\.tar\.gz"
-"cmake-@version@\.zip"
--- query: \.files\[\] \| select\(\.os\[\] \| \. == "source"\) \| \.name
-"cmake-@version@\.tar\.gz"
-"cmake-@version@\.zip"
--- query: \.files\[\] \| select\(\(\.os\[\] \| \. == "macOS"\) and \(\.class == "volume"\)\) \| \.name
-"cmake-@version@-macos-universal\.dmg"
--- query: \.files\[\] \| select\(\(\.os\[\] \| \. == "macos10\.10"\) and \(\.class == "archive"\)\) \| \.name
-"cmake-@version@-macos10\.10-universal\.tar\.gz"
--- query: \.files\[\] \| select\(\(\.os\[\] \| \. == "windows"\) and \(\.architecture\[\] \| \. == "i386"\) and \(\.class == "installer"\)\) \| \.name
-"cmake-@version@-win32-x86\.msi"
--- query: \.files\[\] \| select\(\.architecture\[\] \| \. == "x86_64"\) \| \.name
-"cmake-@version@-Linux-x86_64\.sh"
-"cmake-@version@-Linux-x86_64\.tar\.gz"
-"cmake-@version@-macos-universal\.dmg"
-"cmake-@version@-macos-universal\.tar\.gz"
-"cmake-@version@-macos10\.10-universal\.dmg"
-"cmake-@version@-macos10\.10-universal\.tar\.gz"
-"cmake-@version@-win64-x64\.msi"
-"cmake-@version@-win64-x64\.zip"
--- query: \.files\[\] \| select\(\[\.macOSmin\] \| inside\(\["10\.10", "10\.11", "10\.12"\]\)\) \| \.name
-"cmake-@version@-macos10\.10-universal\.dmg"
-"cmake-@version@-macos10\.10-universal\.tar\.gz"
--- query: \.hashFiles\[\] \| select\(\.algorithm\[\] \| \. == "SHA-256"\) \| \.name
-"cmake-@version@-SHA-256\.txt"$
diff --git a/Tests/RunCMake/CMakeRelease/FileTable.cmake b/Tests/RunCMake/CMakeRelease/FileTable.cmake
deleted file mode 100644
index f46535c70..000000000
--- a/Tests/RunCMake/CMakeRelease/FileTable.cmake
+++ /dev/null
@@ -1,21 +0,0 @@
-set(version "@version@")
-set(version_major "1")
-set(version_minor "2")
-set(version_patch "3")
-set(maybe_version_suffix "\"suffix\": \"rc4\",")
-configure_file("${CMAKE_CURRENT_LIST_DIR}/../../../Utilities/Release/files-v1.json.in" "files-v1.json" @ONLY)
-
-foreach(query
- ".version | .major , .minor , .patch , .suffix, .string"
- ".files[].name"
- ".files[] | select(.os[] | . == \"source\") | .name"
- ".files[] | select((.os[] | . == \"macOS\") and (.class == \"volume\")) | .name"
- ".files[] | select((.os[] | . == \"macos10.10\") and (.class == \"archive\")) | .name"
- ".files[] | select((.os[] | . == \"windows\") and (.architecture[] | . == \"i386\") and (.class == \"installer\")) | .name"
- ".files[] | select(.architecture[] | . == \"x86_64\") | .name"
- ".files[] | select([.macOSmin] | inside([\"10.10\", \"10.11\", \"10.12\"])) | .name"
- ".hashFiles[] | select(.algorithm[] | . == \"SHA-256\") | .name"
- )
- message(STATUS "query: ${query}")
- execute_process(COMMAND ${JQ} "${query}" files-v1.json)
-endforeach()
diff --git a/Tests/RunCMake/CMakeRelease/RunCMakeTest.cmake b/Tests/RunCMake/CMakeRelease/RunCMakeTest.cmake
deleted file mode 100644
index 9a08ff3a1..000000000
--- a/Tests/RunCMake/CMakeRelease/RunCMakeTest.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-include(RunCMake)
-
-if(CMake_TEST_JQ)
- set(JQ "${CMake_TEST_JQ}")
-else()
- find_program(JQ NAMES jq)
-endif()
-if(JQ)
- run_cmake_script(FileTable -DJQ=${JQ})
-endif()
diff --git a/Tests/RunCMake/CPack/CPackTestHelpers.cmake b/Tests/RunCMake/CPack/CPackTestHelpers.cmake
index 24f54c656..3ec4c691e 100644
--- a/Tests/RunCMake/CPack/CPackTestHelpers.cmake
+++ b/Tests/RunCMake/CPack/CPackTestHelpers.cmake
@@ -21,6 +21,12 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK
# TODO this should be executed only once per ctest run (not per generator)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ # Set permissions to those expected by the test
+ file(CHMOD "${RunCMake_TEST_BINARY_DIR}"
+ PERMISSIONS
+ OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
if(EXISTS "${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${GENERATOR_TYPE}-Prerequirements.cmake")
include("${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${GENERATOR_TYPE}-Prerequirements.cmake")
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 530bcdf5a..15bfb60ee 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -21,8 +21,8 @@ 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")
run_cpack_test_package_target(MINIMAL "RPM.MINIMAL;DEB.MINIMAL;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External" false "MONOLITHIC;COMPONENT")
-run_cpack_test_package_target(THREADED_ALL "TXZ" false "MONOLITHIC;COMPONENT")
-run_cpack_test_package_target(THREADED "TXZ" false "MONOLITHIC;COMPONENT")
+run_cpack_test_package_target(THREADED_ALL "TXZ;DEB" false "MONOLITHIC;COMPONENT")
+run_cpack_test_package_target(THREADED "TXZ;DEB" false "MONOLITHIC;COMPONENT")
run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false "MONOLITHIC")
run_cpack_test(PARTIALLY_RELOCATABLE_WARNING "RPM.PARTIALLY_RELOCATABLE_WARNING" false "COMPONENT")
run_cpack_test(PER_COMPONENT_FIELDS "RPM.PER_COMPONENT_FIELDS;DEB.PER_COMPONENT_FIELDS" false "COMPONENT")
diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake b/Tests/RunCMake/CPack/VerifyResult.cmake
index 345b37fac..0ab545a28 100644
--- a/Tests/RunCMake/CPack/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/VerifyResult.cmake
@@ -79,6 +79,11 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0)
"which does not match:${msg_expected}\n"
"${output_error_message}")
endif()
+ elseif(foundFilescount_ EQUAL 0)
+ message(FATAL_ERROR
+ "Found no files for file No. '${file_no_}'!"
+ " Globbing expression: '${EXPECTED_FILE_${file_no_}}'"
+ "${output_error_message}")
else()
message(FATAL_ERROR
"Found more than one file for file No. '${file_no_}'!"
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
index cf2e8ac6b..cf4aa510a 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
@@ -1,6 +1,6 @@
set(whitespaces_ "[\t\n\r ]*")
-set(EXPECTED_FILES_COUNT "5")
+set(EXPECTED_FILES_COUNT "6")
set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
if(GENERATOR_TYPE STREQUAL "RPM")
@@ -39,3 +39,6 @@ elseif(GENERATOR_TYPE STREQUAL "DEB")
set(EXPECTED_FILE_5 "TestDinfo-pkg-libs-dbgsym.ddeb")
set(EXPECTED_FILE_CONTENT_5 ".*/usr/lib/debug/.build-id/.*\.debug.*")
endif()
+
+set(EXPECTED_FILE_6 "TestDinfo-pkg*-appheaders.${PKG}")
+set(EXPECTED_FILE_CONTENT_6_LIST "/include;/include/test_lib.hpp")
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
index 161a36a85..9ff1f8a04 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
@@ -1,7 +1,7 @@
set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
-# PGI compiler doesn't add build id to binaries by default
-if(CMAKE_CXX_COMPILER_ID STREQUAL "PGI")
+# Some compilers do not add build id to binaries by default.
+if(CMAKE_CXX_COMPILER_ID MATCHES "^(IntelLLVM|PGI|NVHPC)$")
string(APPEND CMAKE_EXE_LINKER_FLAGS "-Wl,--build-id")
string(APPEND CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id")
endif()
@@ -23,6 +23,7 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
add_executable(test_prog "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
target_link_libraries(test_prog test_lib)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/test_lib.hpp" DESTINATION include COMPONENT appheaders)
install(TARGETS test_prog DESTINATION foo COMPONENT applications)
install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers)
install(TARGETS test_lib DESTINATION bas COMPONENT libs)
@@ -40,6 +41,10 @@ set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON)
set(CPACK_DEBIAN_PACKAGE_NAME "Debuginfo")
set(CPACK_DEBIAN_LIBS_DEBUGINFO_PACKAGE ON)
+# Test that a component with debug info requested but without any debug info produces none
+set(CPACK_RPM_APPHEADERS_DEBUGINFO_PACKAGE ON)
+set(CPACK_DEBIAN_APPHEADERS_DEBUGINFO_PACKAGE ON)
+
# test debuginfo package rename
set(CPACK_RPM_DEBUGINFO_FILE_NAME
"@cpack_component@-DebugInfoPackage.rpm")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt b/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt
new file mode 100644
index 000000000..37360e8f2
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt
@@ -0,0 +1,6 @@
+CPack Warning: Adding file to tar:
+#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/Linux/DEB/extra-0.1.1-Linux/bas
+#missing file: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/conffiles
+CPack Warning: Adding file to tar:
+#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/Linux/DEB/extra-0.1.1-Linux/foo
+#missing file: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/conffiles
diff --git a/Tests/RunCMake/CPack/tests/THREADED/DEB-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/THREADED/DEB-Prerequirements.cmake
new file mode 100644
index 000000000..7b2692cbf
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/THREADED/DEB-Prerequirements.cmake
@@ -0,0 +1 @@
+set(CPACK_DEBIAN_COMPRESSION_TYPE xz)
diff --git a/Tests/RunCMake/CPack/tests/THREADED/test.cmake b/Tests/RunCMake/CPack/tests/THREADED/test.cmake
index 78fc9e93e..9e82e8cc0 100644
--- a/Tests/RunCMake/CPack/tests/THREADED/test.cmake
+++ b/Tests/RunCMake/CPack/tests/THREADED/test.cmake
@@ -1,6 +1,6 @@
install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
-set(CPACK_ARCHIVE_THREADS 2)
+set(CPACK_THREADS 2)
if(PACKAGING_TYPE STREQUAL "COMPONENT")
set(CPACK_COMPONENTS_ALL test)
diff --git a/Tests/RunCMake/CPack/tests/THREADED_ALL/DEB-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/THREADED_ALL/DEB-Prerequirements.cmake
new file mode 100644
index 000000000..7b2692cbf
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/THREADED_ALL/DEB-Prerequirements.cmake
@@ -0,0 +1 @@
+set(CPACK_DEBIAN_COMPRESSION_TYPE xz)
diff --git a/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake b/Tests/RunCMake/CPack/tests/THREADED_ALL/test.cmake
index 34051b85b..6f3720131 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_ARCHIVE_THREADS 0)
+set(CPACK_THREADS 0)
if(PACKAGING_TYPE STREQUAL "COMPONENT")
set(CPACK_COMPONENTS_ALL test)
diff --git a/Tests/RunCMake/CTest/RunCMakeTest.cmake b/Tests/RunCMake/CTest/RunCMakeTest.cmake
index ffc8f7893..b81f319f5 100644
--- a/Tests/RunCMake/CTest/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTest/RunCMakeTest.cmake
@@ -5,6 +5,7 @@ run_cmake(BeforeProject)
unset(RunCMake_TEST_OPTIONS)
run_cmake(NotOn)
+run_cmake(Site)
function(run_CMakeCTestArguments)
run_cmake_with_options(CMakeCTestArguments "-DCMAKE_CTEST_ARGUMENTS=--quiet\\;--output-log\\;output-log.txt")
diff --git a/Tests/RunCMake/CTest/Site.cmake b/Tests/RunCMake/CTest/Site.cmake
new file mode 100644
index 000000000..2c96f2335
--- /dev/null
+++ b/Tests/RunCMake/CTest/Site.cmake
@@ -0,0 +1,5 @@
+include(CTest)
+get_property(site CACHE SITE PROPERTY VALUE)
+if(NOT "${site}" STREQUAL "${SITE}")
+ message(FATAL_ERROR "SITE is not a cache entry")
+endif()
diff --git a/Tests/RunCMake/CTestCommandLine/BadCTestTestfile-stderr.txt b/Tests/RunCMake/CTestCommandLine/BadCTestTestfile-stderr.txt
index 97e2a10c1..b27da430a 100644
--- a/Tests/RunCMake/CTestCommandLine/BadCTestTestfile-stderr.txt
+++ b/Tests/RunCMake/CTestCommandLine/BadCTestTestfile-stderr.txt
@@ -1,4 +1,6 @@
^CMake Error at CTestTestfile.cmake:[0-9]+ \(subdirs\):
subdirs called with incorrect number of arguments
+
-Errors while running CTest$
+Errors while running CTest
+Output from these tests are in: .*/Testing/Temporary/LastTest.log
+Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.$
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index e05ad791c..6cf1476ca 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -380,3 +380,20 @@ run_MemCheckSan(Leak "simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode
run_MemCheckSan(Memory "simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55")
run_MemCheckSan(Thread "report_bugs=1:history_size=5:exitcode=55")
run_MemCheckSan(UndefinedBehavior "simulate_sanitizer=1")
+
+run_cmake_command(test-dir-invalid-arg ${CMAKE_CTEST_COMMAND} --test-dir)
+run_cmake_command(test-dir-non-existing-dir ${CMAKE_CTEST_COMMAND} --test-dir non-existing-dir)
+
+function(run_testDir)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/testDir)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/sub")
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/sub/CTestTestfile.cmake" "
+ add_test(Test1 \"${CMAKE_COMMAND}\" -E true)
+ add_test(Test2 \"${CMAKE_COMMAND}\" -E true)
+ ")
+ run_cmake_command(testDir ${CMAKE_CTEST_COMMAND} --test-dir "${RunCMake_TEST_BINARY_DIR}/sub")
+endfunction()
+run_testDir()
diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt
index 759378390..a993ac6e0 100644
--- a/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt
+++ b/Tests/RunCMake/CTestCommandLine/repeat-until-fail-ctest-stderr.txt
@@ -1 +1,3 @@
-^Errors while running CTest$
+^Errors while running CTest
+Output from these tests are in: .*/Testing/Temporary/LastTest.log
+Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.$
diff --git a/Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-result.txt b/Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-stderr.txt
new file mode 100644
index 000000000..15908a718
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-dir-invalid-arg-stderr.txt
@@ -0,0 +1 @@
+CMake Error: '--test-dir' requires an argument
diff --git a/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-result.txt b/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stderr.txt
new file mode 100644
index 000000000..017ccb006
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stderr.txt
@@ -0,0 +1 @@
+Failed to change working directory to ".*/non-existing-dir" : No such file or directory
diff --git a/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stdout.txt
new file mode 100644
index 000000000..ddcd23808
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-dir-non-existing-dir-stdout.txt
@@ -0,0 +1 @@
+Internal ctest changing into directory: .*/non-existing-dir
diff --git a/Tests/RunCMake/CheckModules/CMP0075-stderr.txt b/Tests/RunCMake/CheckModules/CMP0075-stderr.txt
index 960fe9444..97833f582 100644
--- a/Tests/RunCMake/CheckModules/CMP0075-stderr.txt
+++ b/Tests/RunCMake/CheckModules/CMP0075-stderr.txt
@@ -47,4 +47,15 @@ CMake Warning \(dev\) at [^
Call Stack \(most recent call first\):
CMP0075.cmake:41 \(check_include_files\)
CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.$
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+CMake Deprecation Warning at CMP0075.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0075 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/ClangTidy/OBJC-Build-stdout.txt b/Tests/RunCMake/ClangTidy/OBJC-Build-stdout.txt
new file mode 100644
index 000000000..571ec020b
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJC-Build-stdout.txt
@@ -0,0 +1 @@
+Tests[/\]RunCMake[/\]ClangTidy[/\]main\.m:0:0: warning: message \[checker\]
diff --git a/Tests/RunCMake/ClangTidy/OBJC-launch-Build-stdout.txt b/Tests/RunCMake/ClangTidy/OBJC-launch-Build-stdout.txt
new file mode 100644
index 000000000..571ec020b
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJC-launch-Build-stdout.txt
@@ -0,0 +1 @@
+Tests[/\]RunCMake[/\]ClangTidy[/\]main\.m:0:0: warning: message \[checker\]
diff --git a/Tests/RunCMake/ClangTidy/OBJC-launch.cmake b/Tests/RunCMake/ClangTidy/OBJC-launch.cmake
new file mode 100644
index 000000000..43e852164
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJC-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(OBJC.cmake)
diff --git a/Tests/RunCMake/ClangTidy/OBJC.cmake b/Tests/RunCMake/ClangTidy/OBJC.cmake
new file mode 100644
index 000000000..43eae3012
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJC.cmake
@@ -0,0 +1,3 @@
+enable_language(OBJC)
+set(CMAKE_OBJC_CLANG_TIDY "${PSEUDO_TIDY}" -some -args)
+add_executable(main main.m)
diff --git a/Tests/RunCMake/ClangTidy/OBJCXX-Build-stdout.txt b/Tests/RunCMake/ClangTidy/OBJCXX-Build-stdout.txt
new file mode 100644
index 000000000..cbc7629d6
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJCXX-Build-stdout.txt
@@ -0,0 +1 @@
+Tests[/\]RunCMake[/\]ClangTidy[/\]main\.mm:0:0: warning: message \[checker\]
diff --git a/Tests/RunCMake/ClangTidy/OBJCXX-launch-Build-stdout.txt b/Tests/RunCMake/ClangTidy/OBJCXX-launch-Build-stdout.txt
new file mode 100644
index 000000000..cbc7629d6
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJCXX-launch-Build-stdout.txt
@@ -0,0 +1 @@
+Tests[/\]RunCMake[/\]ClangTidy[/\]main\.mm:0:0: warning: message \[checker\]
diff --git a/Tests/RunCMake/ClangTidy/OBJCXX-launch.cmake b/Tests/RunCMake/ClangTidy/OBJCXX-launch.cmake
new file mode 100644
index 000000000..5a54bffeb
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJCXX-launch.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(OBJCXX.cmake)
diff --git a/Tests/RunCMake/ClangTidy/OBJCXX.cmake b/Tests/RunCMake/ClangTidy/OBJCXX.cmake
new file mode 100644
index 000000000..ccc5c2c93
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/OBJCXX.cmake
@@ -0,0 +1,3 @@
+enable_language(OBJCXX)
+set(CMAKE_OBJCXX_CLANG_TIDY "${PSEUDO_TIDY}" -some -args)
+add_executable(main main.mm)
diff --git a/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake b/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake
index 2f41e503c..ee41d9475 100644
--- a/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake
@@ -16,8 +16,16 @@ endfunction()
run_tidy(C)
run_tidy(CXX)
+if (APPLE)
+ run_tidy(OBJC)
+ run_tidy(OBJCXX)
+endif()
if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
run_tidy(C-launch)
run_tidy(CXX-launch)
+ if (APPLE)
+ run_tidy(OBJC-launch)
+ run_tidy(OBJCXX-launch)
+ endif()
endif()
run_tidy(C-bad)
diff --git a/Tests/RunCMake/ClangTidy/main.m b/Tests/RunCMake/ClangTidy/main.m
new file mode 100644
index 000000000..8488f4e58
--- /dev/null
+++ b/Tests/RunCMake/ClangTidy/main.m
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/Server/buildsystem1/main.cpp b/Tests/RunCMake/ClangTidy/main.mm
index 766b7751b..f8b643afb 100644
--- a/Tests/Server/buildsystem1/main.cpp
+++ b/Tests/RunCMake/ClangTidy/main.mm
@@ -1,4 +1,3 @@
-
int main()
{
return 0;
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 e73d76020..16f8be8b0 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 94fc15732..e7b9aaaf2 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 e73d76020..16f8be8b0 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 8ed4fee99..d1241f46d 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 c81008786..d52b16583 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 94fc15732..e7b9aaaf2 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 c81008786..d52b16583 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 8ed4fee99..d1241f46d 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 40d9bec84..2dd9bc424 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[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 40d9bec84..2dd9bc424 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> \[options\] \[-- \[native-options\]\]
+Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/C-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/C-no-arg-stderr.txt
index 0570d8fca..5992dcd61 100644
--- a/Tests/RunCMake/CommandLine/C-no-arg-stderr.txt
+++ b/Tests/RunCMake/CommandLine/C-no-arg-stderr.txt
@@ -1,2 +1,2 @@
^CMake Error: -C must be followed by a file name.
-CMake Error: Problem processing arguments. Aborting.$
+CMake Error: Run 'cmake --help' for all supported options.$
diff --git a/Tests/RunCMake/CommandLine/D-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/D-no-arg-stderr.txt
index 5e43bcace..8503767ab 100644
--- a/Tests/RunCMake/CommandLine/D-no-arg-stderr.txt
+++ b/Tests/RunCMake/CommandLine/D-no-arg-stderr.txt
@@ -1,2 +1,2 @@
^CMake Error: -D must be followed with VAR=VALUE.
-CMake Error: Problem processing arguments. Aborting.$
+CMake Error: Run 'cmake --help' for all supported options.$
diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
index e24e131b7..c76c92d9e 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}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$
+^{"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":{.*}}$
diff --git a/Tests/RunCMake/CommandLine/E_server-arg-stderr.txt b/Tests/RunCMake/CommandLine/E_server-arg-stderr.txt
deleted file mode 100644
index 4dcbab93d..000000000
--- a/Tests/RunCMake/CommandLine/E_server-arg-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^CMake Error: Unknown argument for server mode$
diff --git a/Tests/RunCMake/CommandLine/E_server-pipe-stderr.txt b/Tests/RunCMake/CommandLine/E_server-pipe-stderr.txt
deleted file mode 100644
index 7193ba63b..000000000
--- a/Tests/RunCMake/CommandLine/E_server-pipe-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^CMake Error: No pipe given after --pipe=$
diff --git a/Tests/RunCMake/CommandLine/E_server-result.txt b/Tests/RunCMake/CommandLine/E_server-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_server-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_server-stderr.txt b/Tests/RunCMake/CommandLine/E_server-stderr.txt
new file mode 100644
index 000000000..0cd0e5613
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_server-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: CMake server mode has been removed in favor of the file-api\.$
diff --git a/Tests/RunCMake/CommandLine/InvalidArg1-result.txt b/Tests/RunCMake/CommandLine/InvalidArg1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/InvalidArg1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/InvalidArg1-stderr.txt b/Tests/RunCMake/CommandLine/InvalidArg1-stderr.txt
new file mode 100644
index 000000000..6b825bbe1
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/InvalidArg1-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Unknown argument -invalid
+CMake Error: Run 'cmake --help' for all supported options.$
diff --git a/Tests/RunCMake/CommandLine/InvalidArg2-result.txt b/Tests/RunCMake/CommandLine/InvalidArg2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/InvalidArg2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/InvalidArg2-stderr.txt b/Tests/RunCMake/CommandLine/InvalidArg2-stderr.txt
new file mode 100644
index 000000000..eb1488cc0
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/InvalidArg2-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Unknown argument --invalid
+CMake Error: Run 'cmake --help' for all supported options.$
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index b23c8c26d..51754fc61 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.1)
include(RunCMake)
run_cmake_command(NoArgs ${CMAKE_COMMAND})
+run_cmake_command(InvalidArg1 ${CMAKE_COMMAND} -invalid)
+run_cmake_command(InvalidArg2 ${CMAKE_COMMAND} --invalid)
run_cmake_command(Wizard ${CMAKE_COMMAND} -i)
run_cmake_command(C-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -C)
run_cmake_command(C-no-file ${CMAKE_COMMAND} -B DummyBuildDir -C nosuchcachefile.txt)
@@ -25,8 +27,7 @@ run_cmake_command(E_compare_files-ignore-eol-nonexistent ${CMAKE_COMMAND} -E com
run_cmake_command(E_compare_files-invalid-arguments ${CMAKE_COMMAND} -E compare_files file1.txt file2.txt file3.txt)
run_cmake_command(E_echo_append ${CMAKE_COMMAND} -E echo_append)
run_cmake_command(E_rename-no-arg ${CMAKE_COMMAND} -E rename)
-run_cmake_command(E_server-arg ${CMAKE_COMMAND} -E server --extra-arg)
-run_cmake_command(E_server-pipe ${CMAKE_COMMAND} -E server --pipe=)
+run_cmake_command(E_server ${CMAKE_COMMAND} -E server)
run_cmake_command(E_true ${CMAKE_COMMAND} -E true)
run_cmake_command(E_true-extraargs ${CMAKE_COMMAND} -E true ignored)
run_cmake_command(E_false ${CMAKE_COMMAND} -E false)
@@ -202,8 +203,8 @@ function(run_BuildDir)
run_cmake_command(BuildDir--build--parallel-large ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build BuildDir-build --parallel 4294967293)
- # No default jobs for Xcode and FreeBSD build command
- if(NOT RunCMake_GENERATOR MATCHES "Xcode" AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ # No default jobs for FreeBSD build command
+ if(NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
run_cmake_command(BuildDir--build-jobs-no-number ${CMAKE_COMMAND} -E chdir ..
${CMAKE_COMMAND} --build BuildDir-build -j)
run_cmake_command(BuildDir--build-jobs-no-number-trailing--target ${CMAKE_COMMAND} -E chdir ..
@@ -672,6 +673,10 @@ set(RunCMake_TEST_OPTIONS -Wno-error=deprecated)
run_cmake(Wno-error_deprecated)
unset(RunCMake_TEST_OPTIONS)
+set(RunCMake_TEST_OPTIONS -Werror=deprecated -Wno-error=deprecated)
+run_cmake(Wno-error_deprecated)
+unset(RunCMake_TEST_OPTIONS)
+
# Dev warnings should be on by default
run_cmake(Wdev)
@@ -790,7 +795,7 @@ function(run_llvm_rc)
"test.tmp was not deleted")
endif()
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir")
- run_cmake_command(llvm_rc_full_run ${CMAKE_COMMAND} -E cmake_llvm_rc ${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir/source_file test.tmp ${CMAKE_COMMAND} -E echo "This is a test" ++ ${CMAKE_COMMAND} -E copy test.tmp SOURCE_DIR/llvmrc.result )
+ run_cmake_command(llvm_rc_full_run ${CMAKE_COMMAND} -E cmake_llvm_rc ${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir/source_file test.tmp ${CMAKE_COMMAND} -E echo "This is a test" ++ ${LLVM_RC} -bad /FO SOURCE_DIR/llvmrc.result test.tmp )
if(EXISTS ${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir/test.tmp)
message(SEND_ERROR "${test} - FAILED:\n"
"test.tmp was not deleted")
diff --git a/Tests/RunCMake/CommandLine/U-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/U-no-arg-stderr.txt
index c34ef947c..20715cf89 100644
--- a/Tests/RunCMake/CommandLine/U-no-arg-stderr.txt
+++ b/Tests/RunCMake/CommandLine/U-no-arg-stderr.txt
@@ -1,2 +1,2 @@
^CMake Error: -U must be followed with VAR.
-CMake Error: Problem processing arguments. Aborting.$
+CMake Error: Run 'cmake --help' for all supported options.$
diff --git a/Tests/RunCMake/CommandLine/W_bad-arg1-stderr.txt b/Tests/RunCMake/CommandLine/W_bad-arg1-stderr.txt
index 0c0f61347..139511b80 100644
--- a/Tests/RunCMake/CommandLine/W_bad-arg1-stderr.txt
+++ b/Tests/RunCMake/CommandLine/W_bad-arg1-stderr.txt
@@ -1,2 +1,2 @@
CMake Error: -W must be followed with \[no-\]<name>.
-CMake Error: Problem processing arguments. Aborting.
+CMake Error: Run 'cmake --help' for all supported options.
diff --git a/Tests/RunCMake/CommandLine/W_bad-arg2-stderr.txt b/Tests/RunCMake/CommandLine/W_bad-arg2-stderr.txt
index cc643df95..5d416fca0 100644
--- a/Tests/RunCMake/CommandLine/W_bad-arg2-stderr.txt
+++ b/Tests/RunCMake/CommandLine/W_bad-arg2-stderr.txt
@@ -1,2 +1,2 @@
CMake Error: No warning name provided.
-CMake Error: Problem processing arguments. Aborting.
+CMake Error: Run 'cmake --help' for all supported options.
diff --git a/Tests/RunCMake/CommandLine/W_bad-arg3-stderr.txt b/Tests/RunCMake/CommandLine/W_bad-arg3-stderr.txt
index cc643df95..5d416fca0 100644
--- a/Tests/RunCMake/CommandLine/W_bad-arg3-stderr.txt
+++ b/Tests/RunCMake/CommandLine/W_bad-arg3-stderr.txt
@@ -1,2 +1,2 @@
CMake Error: No warning name provided.
-CMake Error: Problem processing arguments. Aborting.
+CMake Error: Run 'cmake --help' for all supported options.
diff --git a/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt b/Tests/RunCMake/CommandLine/build-no-dir-stderr.txt
index 8d518f609..9b4d26bc2 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> \[options\] \[-- \[native-options\]\]
+^Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
diff --git a/Tests/RunCMake/CommandLine/cmake_depends-check.cmake b/Tests/RunCMake/CommandLine/cmake_depends-check.cmake
index 031478b7b..e0e3054ac 100644
--- a/Tests/RunCMake/CommandLine/cmake_depends-check.cmake
+++ b/Tests/RunCMake/CommandLine/cmake_depends-check.cmake
@@ -3,8 +3,9 @@ if(EXISTS "${depend_make}")
file(READ "${depend_make}" depend_make_content)
string(REGEX REPLACE "\n+$" "" depend_make_content "${depend_make_content}")
if(NOT depend_make_content MATCHES "
-CMakeFiles/DepTarget.dir/test.c.o: .*/Tests/RunCMake/CommandLine/cmake_depends/test.c
-CMakeFiles/DepTarget.dir/test.c.o: .*/Tests/RunCMake/CommandLine/cmake_depends/test.h$")
+CMakeFiles/DepTarget.dir/test.c.o: \\\\
+ .*/Tests/RunCMake/CommandLine/cmake_depends/test.c \\\\
+ .*/Tests/RunCMake/CommandLine/cmake_depends/test.h$")
string(REPLACE "\n" "\n " depend_make_content " ${depend_make_content}")
set(RunCMake_TEST_FAILED "depend.make does not have expected content:\n${depend_make_content}")
endif()
diff --git a/Tests/RunCMake/DependencyGraph/RunCMakeTest.cmake b/Tests/RunCMake/DependencyGraph/RunCMakeTest.cmake
index cb0d541b7..891e13825 100644
--- a/Tests/RunCMake/DependencyGraph/RunCMakeTest.cmake
+++ b/Tests/RunCMake/DependencyGraph/RunCMakeTest.cmake
@@ -10,7 +10,8 @@ function(check_files dir)
set(actual)
foreach(i IN LISTS glob)
if(NOT i MATCHES "(\\.manifest$)|(\\.exp$)|(\\.tds$)")
- list(APPEND actual ${i})
+ get_filename_component(real_path ${i} REALPATH)
+ list(APPEND actual ${real_path})
endif()
endforeach()
list(REMOVE_DUPLICATES actual)
diff --git a/Tests/RunCMake/ExportCompileCommands/Properties.cmake b/Tests/RunCMake/ExportCompileCommands/Properties.cmake
new file mode 100644
index 000000000..c7a38b798
--- /dev/null
+++ b/Tests/RunCMake/ExportCompileCommands/Properties.cmake
@@ -0,0 +1,22 @@
+enable_language(C)
+
+add_library(Unset STATIC empty.c)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+add_library(SetOn STATIC empty.c)
+set(CMAKE_EXPORT_COMPILE_COMMANDS OFF)
+add_library(SetOff STATIC empty.c)
+
+get_property(_set TARGET Unset PROPERTY EXPORT_COMPILE_COMMANDS)
+if(_set)
+ message(SEND_ERROR "EXPORT_COMPILE_COMMANDS property should be unset for Unset target (got \"${_set}\")")
+endif()
+
+get_property(_on TARGET SetOn PROPERTY EXPORT_COMPILE_COMMANDS)
+if(NOT _on STREQUAL "ON")
+ message(SEND_ERROR "EXPORT_COMPILE_COMMANDS property should be \"ON\" for SetOn target (got \"${_on}\")")
+endif()
+
+get_property(_off TARGET SetOff PROPERTY EXPORT_COMPILE_COMMANDS)
+if(NOT _off STREQUAL "OFF")
+ message(SEND_ERROR "EXPORT_COMPILE_COMMANDS property should be \"OFF\" for SetOff target (got \"${_off}\")")
+endif()
diff --git a/Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand-check.cmake b/Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand-check.cmake
new file mode 100644
index 000000000..d69874210
--- /dev/null
+++ b/Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand-check.cmake
@@ -0,0 +1,32 @@
+if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/compile_commands.json")
+ set(RunCMake_TEST_FAILED "compile_commands.json not generated")
+ return()
+endif()
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/compile_commands.json" compile_commands)
+
+macro(check_error)
+ if(error)
+ message(SEND_ERROR "Unexpected error \"${error}\"\nFor: ${compile_commands}")
+ endif()
+endmacro()
+
+string(JSON num_commands ERROR_VARIABLE error LENGTH "${compile_commands}")
+check_error()
+
+# Only one of the targets has the EXPORT_COMPILE_COMMANDS property enabled.
+if(NOT num_commands STREQUAL 1)
+ message(SEND_ERROR "Expected 1 compile command, got ${num_commands} for ${compile_commands}")
+endif()
+
+# Get the compile command generated.
+string(JSON result ERROR_VARIABLE error GET "${compile_commands}" 0)
+check_error()
+string(JSON result ERROR_VARIABLE error GET "${result}" file)
+check_error()
+
+# And ensure the correct target is in that compile command.
+cmake_path(COMPARE "${result}" EQUAL "${RunCMake_TEST_SOURCE_DIR}/expected_file.c" good)
+if(NOT good)
+ message(SEND_ERROR "Expected \"${result}\" in \"${RunCMake_TEST_SOURCE_DIR}/expected_file.c\"")
+endif()
diff --git a/Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand.cmake b/Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand.cmake
new file mode 100644
index 000000000..46c8845bc
--- /dev/null
+++ b/Tests/RunCMake/ExportCompileCommands/PropertiesGenerateCommand.cmake
@@ -0,0 +1,7 @@
+enable_language(C)
+
+add_library(Unset STATIC empty.c)
+add_library(ToBeSet STATIC expected_file.c)
+
+# Only one target with EXPORT_COMPILE_COMMANDS property.
+set_property(TARGET ToBeSet PROPERTY EXPORT_COMPILE_COMMANDS TRUE)
diff --git a/Tests/RunCMake/ExportCompileCommands/RunCMakeTest.cmake b/Tests/RunCMake/ExportCompileCommands/RunCMakeTest.cmake
index 9e7e73219..b69163782 100644
--- a/Tests/RunCMake/ExportCompileCommands/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExportCompileCommands/RunCMakeTest.cmake
@@ -1,4 +1,12 @@
include(RunCMake)
+if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
+else()
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+endif()
+
run_cmake_with_options(BeforeProject -DCMAKE_PROJECT_INCLUDE_BEFORE=BeforeProjectBEFORE.cmake)
run_cmake(CustomCompileRule)
+run_cmake(Properties)
+run_cmake(PropertiesGenerateCommand)
diff --git a/Tests/RunCMake/ExportCompileCommands/expected_file.c b/Tests/RunCMake/ExportCompileCommands/expected_file.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/ExportCompileCommands/expected_file.c
diff --git a/Tests/RunCMake/ExternalData/BadArguments-stderr.txt b/Tests/RunCMake/ExternalData/BadArguments-stderr.txt
new file mode 100644
index 000000000..44efe7ebd
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadArguments-stderr.txt
@@ -0,0 +1,7 @@
+CMake Warning \(dev\) at .*/Modules/ExternalData.cmake:[0-9]+ \(message\):
+ Ignoring unrecognized arguments passed to ExternalData_add_target:
+ `UNKNOWN_ARGUMENT`
+Call Stack \(most recent call first\):
+ BadArguments.cmake:[0-9]+ \(ExternalData_Add_Target\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/ExternalData/BadArguments.cmake b/Tests/RunCMake/ExternalData/BadArguments.cmake
new file mode 100644
index 000000000..dad00076f
--- /dev/null
+++ b/Tests/RunCMake/ExternalData/BadArguments.cmake
@@ -0,0 +1,5 @@
+include(ExternalData)
+set(ExternalData_URL_TEMPLATES
+ "file:///path/to/%(algo)/%(hash)"
+ )
+ExternalData_Add_Target(Data UNKNOWN_ARGUMENT)
diff --git a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
index b5ab22d1a..b4cc95e6f 100644
--- a/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalData/RunCMakeTest.cmake
@@ -2,6 +2,7 @@ include(RunCMake)
run_cmake(BadAlgoMap1)
run_cmake(BadAlgoMap2)
+run_cmake(BadArguments)
run_cmake(BadCustom1)
run_cmake(BadCustom2)
run_cmake(BadCustom3)
diff --git a/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake
new file mode 100644
index 000000000..887da0f65
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake
@@ -0,0 +1,19 @@
+file(TIMESTAMP "${STAMP_DIR}/proj1-configure" PROJ1_CONFIGURE_TIMESTAMP_AFTER "%s")
+# When BUILD_ALWAYS is set, the build stamp is never created.
+file(TIMESTAMP "${STAMP_DIR}/proj2-configure" PROJ2_CONFIGURE_TIMESTAMP_AFTER "%s")
+file(TIMESTAMP "${STAMP_DIR}/proj2-build" PROJ2_BUILD_TIMESTAMP_AFTER "%s")
+
+if(NOT PROJ1_CONFIGURE_TIMESTAMP_BEFORE EQUAL PROJ1_CONFIGURE_TIMESTAMP_AFTER)
+ set(RunCMake_TEST_FAILED "Unexpected rebuild of proj1 configure step (${PROJ1_CONFIGURE_TIMESTAMP_BEFORE} != ${PROJ1_CONFIGURE_TIMESTAMP_AFTER})")
+ return()
+endif()
+
+if(NOT PROJ2_CONFIGURE_TIMESTAMP_BEFORE EQUAL PROJ2_CONFIGURE_TIMESTAMP_AFTER)
+ set(RunCMake_TEST_FAILED "Unexpected rebuild of proj2 configure step (${PROJ2_CONFIGURE_TIMESTAMP_BEFORE} != ${PROJ2_CONFIGURE_TIMESTAMP_AFTER})")
+ return()
+endif()
+
+if(PROJ2_BUILD_TIMESTAMP_BEFORE EQUAL PROJ2_BUILD_TIMESTAMP_AFTER)
+ set(RunCMake_TEST_FAILED "proj2 build step did not rebuild (${PROJ2_BUILD_TIMESTAMP_BEFORE} != ${PROJ2_BUILD_TIMESTAMP_AFTER})")
+ return()
+endif()
diff --git a/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake
new file mode 100644
index 000000000..6dbf0f414
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/CONFIGURE_HANDLED_BY_BUILD.cmake
@@ -0,0 +1,28 @@
+include(ExternalProject)
+
+# Given this setup, on the first build, both configure steps and both build
+# steps will run. On a noop rebuild, only the build steps will run. Without
+# CONFIGURE_HANDLED_BY_BUILD, the configure step of proj2 would also run on a
+# noop rebuild.
+
+ExternalProject_Add(proj1
+ DOWNLOAD_COMMAND ""
+ SOURCE_DIR ""
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo "Doing something"
+ # file(TIMESTAMP) gives back the timestamp in seconds so we sleep a second to
+ # make sure we get a different timestamp on the stamp file
+ BUILD_COMMAND ${CMAKE_COMMAND} -E sleep 1.125
+ INSTALL_COMMAND ""
+ BUILD_ALWAYS ON
+ STAMP_DIR "stamp"
+)
+ExternalProject_Add(proj2
+ DOWNLOAD_COMMAND ""
+ SOURCE_DIR ""
+ CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo "Doing something"
+ BUILD_COMMAND ${CMAKE_COMMAND} -E sleep 1.125
+ INSTALL_COMMAND ""
+ CONFIGURE_HANDLED_BY_BUILD ON
+ DEPENDS proj1
+ STAMP_DIR "stamp"
+)
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags.cmake b/Tests/RunCMake/ExternalProject/FetchGitTags.cmake
new file mode 100644
index 000000000..37d1b4088
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/FetchGitTags.cmake
@@ -0,0 +1,67 @@
+find_package(Git QUIET REQUIRED)
+
+include(ExternalProject)
+
+set(srcRepo ${CMAKE_CURRENT_BINARY_DIR}/srcRepo)
+set(srcDir ${CMAKE_CURRENT_BINARY_DIR}/src)
+set(binDir ${CMAKE_CURRENT_BINARY_DIR}/build)
+file(MAKE_DIRECTORY ${srcRepo})
+file(MAKE_DIRECTORY ${srcDir})
+
+file(GLOB entries ${srcRepo}/*)
+file(REMOVE_RECURSE ${entries} ${binDir})
+file(TOUCH ${srcRepo}/firstFile.txt)
+configure_file(${CMAKE_CURRENT_LIST_DIR}/FetchGitTags/CMakeLists.txt
+ ${srcDir}/CMakeLists.txt COPYONLY)
+
+function(execGitCommand)
+ execute_process(
+ WORKING_DIRECTORY ${srcRepo}
+ COMMAND ${GIT_EXECUTABLE} ${ARGN}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+endfunction()
+
+function(configureAndBuild tag)
+ execute_process(COMMAND ${CMAKE_COMMAND}
+ -G ${CMAKE_GENERATOR} -T "${CMAKE_GENERATOR_TOOLSET}"
+ -A "${CMAKE_GENERATOR_PLATFORM}"
+ -D repoDir:PATH=${srcRepo}
+ -D gitTag:STRING=${tag}
+ -B ${binDir}
+ -S ${srcDir}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+
+ execute_process(COMMAND ${CMAKE_COMMAND} --build ${binDir} --target fetcher
+ WORKING_DIRECTORY ${binDir}
+ COMMAND_ECHO STDOUT
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+endfunction()
+
+# Setup a fresh source repo with a predictable default branch across all
+# git versions
+execGitCommand(-c init.defaultBranch=master init)
+execGitCommand(config --add user.email "testauthor@cmake.org")
+execGitCommand(config --add user.name testauthor)
+
+# Create the initial repo structure
+execGitCommand(add firstFile.txt)
+execGitCommand(commit -m "First file")
+
+message(STATUS "First configure-and-build")
+configureAndBuild(master)
+
+# Create a tagged commit that is not on any branch. With git 2.20 or later,
+# this commit won't be fetched without the --tags option.
+file(TOUCH ${srcRepo}/secondFile.txt)
+execGitCommand(add secondFile.txt)
+execGitCommand(commit -m "Second file")
+execGitCommand(tag -a -m "Adding tag" tag_of_interest)
+execGitCommand(reset --hard HEAD~1)
+
+message(STATUS "Second configure-and-build")
+configureAndBuild(tag_of_interest)
diff --git a/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt b/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt
new file mode 100644
index 000000000..d9a380c03
--- /dev/null
+++ b/Tests/RunCMake/ExternalProject/FetchGitTags/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.19)
+project(FetchTags LANGUAGES NONE)
+
+include(ExternalProject)
+
+# repoDir and gitTag are expected to be set as cache variables
+
+ExternalProject_Add(fetcher
+ GIT_REPOSITORY ${repoDir}
+ GIT_TAG ${gitTag}
+ GIT_REMOTE_UPDATE_STRATEGY CHECKOUT
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+)
diff --git a/Tests/RunCMake/ExternalProject/IncludeScope-Add-stderr.txt b/Tests/RunCMake/ExternalProject/IncludeScope-Add-stderr.txt
deleted file mode 100644
index ff3e5c18e..000000000
--- a/Tests/RunCMake/ExternalProject/IncludeScope-Add-stderr.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
- error: ExternalProject module must be explicitly included before using
- ExternalProject_Add function
-Call Stack \(most recent call first\):
- .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_parse_arguments\)
- IncludeScope-Add.cmake:[0-9]+ \(ExternalProject_Add\)
- CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/IncludeScope-Add.cmake b/Tests/RunCMake/ExternalProject/IncludeScope-Add.cmake
deleted file mode 100644
index 1061ffddc..000000000
--- a/Tests/RunCMake/ExternalProject/IncludeScope-Add.cmake
+++ /dev/null
@@ -1,12 +0,0 @@
-function(IncludeScope_IncludeOnly)
- include(ExternalProject)
-endfunction()
-
-IncludeScope_IncludeOnly()
-
-ExternalProject_Add(MyProj
- SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
-)
diff --git a/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step-stderr.txt b/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step-stderr.txt
deleted file mode 100644
index cbad4be61..000000000
--- a/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step-stderr.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
- error: ExternalProject module must be explicitly included before using
- ExternalProject_Add_Step function
-Call Stack \(most recent call first\):
- .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_parse_arguments\)
- IncludeScope-Add_Step.cmake:[0-9]+ \(ExternalProject_Add_Step\)
- CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step.cmake b/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step.cmake
deleted file mode 100644
index 2a820f8f2..000000000
--- a/Tests/RunCMake/ExternalProject/IncludeScope-Add_Step.cmake
+++ /dev/null
@@ -1,13 +0,0 @@
-function(IncludeScope_DefineProj)
- include(ExternalProject)
- ExternalProject_Add(MyProj
- SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- )
-endfunction()
-
-IncludeScope_DefineProj()
-
-ExternalProject_Add_Step(MyProj extraStep COMMENT "Foo")
diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
index 598671f82..3205dd54c 100644
--- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake
@@ -8,8 +8,6 @@ unset(ENV{https_proxy})
run_cmake(BadIndependentStep1)
run_cmake(BadIndependentStep2)
-run_cmake(IncludeScope-Add)
-run_cmake(IncludeScope-Add_Step)
run_cmake(NoOptions)
run_cmake(SourceEmpty)
run_cmake(SourceMissing)
@@ -151,3 +149,42 @@ endif()
if(doSubstitutionTest)
__ep_test_with_build(Substitutions)
endif()
+
+function(__ep_test_CONFIGURE_HANDLED_BY_BUILD)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CONFIGURE_HANDLED_BY_BUILD-build)
+ run_cmake(CONFIGURE_HANDLED_BY_BUILD)
+
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(BUILD_CONFIG --config Debug)
+ set(STAMP_DIR "${RunCMake_TEST_BINARY_DIR}/stamp/Debug")
+ else()
+ set(BUILD_CONFIG "")
+ set(STAMP_DIR "${RunCMake_TEST_BINARY_DIR}/stamp")
+ endif()
+
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(CONFIGURE_HANDLED_BY_BUILD-build ${CMAKE_COMMAND} --build . ${BUILD_CONFIG})
+
+ # Calculate timestamps before rebuilding so we can compare before and after in
+ # CONFIGURE_HANDLED_BY_BUILD-rebuild-check.cmake
+
+ file(TIMESTAMP "${STAMP_DIR}/proj1-configure" PROJ1_CONFIGURE_TIMESTAMP_BEFORE "%s")
+ # When BUILD_ALWAYS is set, the build stamp is never created.
+ file(TIMESTAMP "${STAMP_DIR}/proj2-configure" PROJ2_CONFIGURE_TIMESTAMP_BEFORE "%s")
+ file(TIMESTAMP "${STAMP_DIR}/proj2-build" PROJ2_BUILD_TIMESTAMP_BEFORE "%s")
+
+ run_cmake_command(CONFIGURE_HANDLED_BY_BUILD-rebuild ${CMAKE_COMMAND} --build . ${BUILD_CONFIG})
+endfunction()
+
+if(NOT RunCMake_GENERATOR MATCHES "Visual Studio 9 ")
+ __ep_test_CONFIGURE_HANDLED_BY_BUILD()
+endif()
+
+find_package(Git QUIET)
+if(GIT_EXECUTABLE)
+ # Note that there appear to be differences in where git writes its output to
+ # on some platforms. It may go to stdout or stderr, so force it to be merged.
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ run_cmake(FetchGitTags)
+ set(RunCMake_TEST_OUTPUT_MERGE FALSE)
+endif()
diff --git a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
index 4449ff1b9..ae3d17959 100644
--- a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
@@ -24,6 +24,7 @@ function(check_python case)
file(GLOB index ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/index-*.json)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} "${RunCMake_SOURCE_DIR}/${case}-check.py" "${index}" "${CMAKE_CXX_COMPILER_ID}"
+ "${RunCMake_TEST_BINARY_DIR}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE output
@@ -50,7 +51,9 @@ run_cmake(ClientStateful)
function(run_object object)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${object}-build)
+ list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0118=NEW)
run_cmake(${object})
+ list(POP_BACK RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(${object}-SharedStateless ${CMAKE_COMMAND} .)
run_cmake_command(${object}-ClientStateless ${CMAKE_COMMAND} .)
@@ -60,3 +63,4 @@ endfunction()
run_object(codemodel-v2)
run_object(cache-v2)
run_object(cmakeFiles-v1)
+run_object(toolchains-v1)
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index c66757f84..df2410a41 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -608,7 +608,7 @@ def gen_check_targets(c, g, inSource):
read_codemodel_json_data("targets/generated_exe.json"),
]
- if cxx_compiler_id in ['Clang', 'AppleClang', 'GNU', 'Intel', 'MSVC', 'Embarcadero'] and g["name"] != "Xcode":
+ if cxx_compiler_id in ['Clang', 'AppleClang', 'GNU', 'Intel', 'IntelLLVM', 'MSVC', 'Embarcadero'] and g["name"] != "Xcode":
for e in expected:
if e["name"] == "cxx_exe":
if matches(g["name"], "^(Visual Studio |Ninja Multi-Config)"):
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_tgt.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_tgt.json
index a7106fc83..483ae79f7 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_tgt.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_tgt.json
@@ -7,7 +7,7 @@
"isGeneratorProvided": null,
"sources": [
{
- "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/custom_tgt$",
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/custom_tgt(-(Debug|Release|RelWithDebInfo|MinSizeRel))?$",
"isGenerated": true,
"sourceGroupName": "",
"compileGroupLanguage": null,
@@ -27,7 +27,7 @@
]
},
{
- "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(custom/)?CMakeFiles/([0-9a-f]+/)?custom_tgt\\.rule$",
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(custom/)?CMakeFiles/([0-9a-f]+/)?custom_tgt(-\\(CONFIG\\))?\\.rule$",
"isGenerated": true,
"sourceGroupName": "CMake Rules",
"compileGroupLanguage": null,
@@ -45,13 +45,13 @@
{
"name": "",
"sourcePaths": [
- "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/custom_tgt$"
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/custom_tgt(-(Debug|Release|RelWithDebInfo|MinSizeRel))?$"
]
},
{
"name": "CMake Rules",
"sourcePaths": [
- "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(custom/)?CMakeFiles/([0-9a-f]+/)?custom_tgt\\.rule$"
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(custom/)?CMakeFiles/([0-9a-f]+/)?custom_tgt(-\\(CONFIG\\))?\\.rule$"
]
}
],
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-check.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-check.cmake
new file mode 100644
index 000000000..ce38461be
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-check.cmake
@@ -0,0 +1,11 @@
+set(expect
+ query
+ query/client-foo
+ query/client-foo/query.json
+ reply
+ reply/index-[0-9.T-]+.json
+ reply/toolchains-v1-[0-9a-f]+.json
+ )
+check_api("^${expect}$")
+
+check_python(toolchains-v1)
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-prep.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-prep.cmake
new file mode 100644
index 000000000..ca62edfaa
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateful-prep.cmake
@@ -0,0 +1,4 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/query.json" [[
+{ "requests": [ { "kind": "toolchains", "version" : 1 } ] }
+]])
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-check.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-check.cmake
new file mode 100644
index 000000000..4676dd8dd
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-check.cmake
@@ -0,0 +1,11 @@
+set(expect
+ query
+ query/client-foo
+ query/client-foo/toolchains-v1
+ reply
+ reply/index-[0-9.T-]+.json
+ reply/toolchains-v1-[0-9a-f]+.json
+ )
+check_api("^${expect}$")
+
+check_python(toolchains-v1)
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-prep.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-prep.cmake
new file mode 100644
index 000000000..7edff93ea
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1-ClientStateless-prep.cmake
@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/toolchains-v1" "")
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-check.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-check.cmake
new file mode 100644
index 000000000..8e83758f9
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-check.cmake
@@ -0,0 +1,10 @@
+set(expect
+ query
+ query/toolchains-v1
+ reply
+ reply/index-[0-9.T-]+.json
+ reply/toolchains-v1-[0-9a-f]+.json
+ )
+check_api("^${expect}$")
+
+check_python(toolchains-v1)
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-prep.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-prep.cmake
new file mode 100644
index 000000000..2db73a122
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1-SharedStateless-prep.cmake
@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/toolchains-v1" "")
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-check.py b/Tests/RunCMake/FileAPI/toolchains-v1-check.py
new file mode 100644
index 000000000..a0e50c244
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1-check.py
@@ -0,0 +1,86 @@
+from check_index import *
+import os
+
+class ExpectedVar(object):
+ def __init__(self, name):
+ self.name = name
+
+class ExpectedList(object):
+ def __init__(self, name):
+ self.name = name
+
+EXPECTED_TOOLCHAIN = {
+ "language": "CXX",
+ "compiler": {
+ "path": ExpectedVar("CMAKE_CXX_COMPILER"),
+ "id": ExpectedVar("CMAKE_CXX_COMPILER_ID"),
+ "version": ExpectedVar("CMAKE_CXX_COMPILER_VERSION"),
+ "target": ExpectedVar("CMAKE_CXX_COMPILER_TARGET"),
+ "implicit": {
+ "includeDirectories": \
+ ExpectedList("CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES"),
+ "linkDirectories": \
+ ExpectedList("CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES"),
+ "linkFrameworkDirectories": \
+ ExpectedList(
+ "CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"),
+ "linkLibraries": \
+ ExpectedList("CMAKE_CXX_IMPLICIT_LINK_LIBRARIES"),
+ }
+ },
+ "sourceFileExtensions": \
+ ExpectedList("CMAKE_CXX_SOURCE_FILE_EXTENSIONS"),
+}
+
+def check_objects(o):
+ assert is_list(o)
+ assert len(o) == 1
+ check_index_object(o[0], "toolchains", 1, 0, check_object_toolchains)
+
+def check_object_toolchains(o):
+ assert sorted(o.keys()) == ["kind", "toolchains", "version"]
+ # The "kind" and "version" members are handled by check_index_object.
+ toolchains = o["toolchains"]
+ assert is_list(toolchains)
+
+ # Other platform-specific toolchains may exist (like RC on Windows).
+ has_cxx_toolchain = False
+ for toolchain in toolchains:
+ assert is_dict(toolchain)
+ assert "language" in toolchain
+ if toolchain["language"] == "CXX":
+ check_object_toolchain(toolchain, EXPECTED_TOOLCHAIN)
+ has_cxx_toolchain = True
+
+ assert has_cxx_toolchain
+
+def check_object_toolchain(o, expected):
+ expected_keys = [
+ key for (key, value) in expected.items()
+ if is_string(value) or is_dict(value)
+ or (type(value) in (ExpectedVar, ExpectedList)
+ and variables[value.name]["defined"])]
+ assert sorted(o.keys()) == sorted(expected_keys)
+
+ for key in expected_keys:
+ value = expected[key]
+ if is_string(value):
+ assert o[key] == value
+ elif is_dict(value):
+ check_object_toolchain(o[key], value)
+ elif type(value) == ExpectedVar:
+ assert o[key] == variables[value.name]["value"]
+ elif type(value) == ExpectedList:
+ expected_items = filter(
+ None, variables[value.name]["value"].split(";"))
+ check_list_match(lambda a, b: a == b, o[key], expected_items)
+ else:
+ assert False
+
+with open(os.path.join(sys.argv[3], "toolchain_variables.json")) as f:
+ variables = json.load(f)
+
+assert is_dict(variables)
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_objects(index["objects"])
diff --git a/Tests/RunCMake/FileAPI/toolchains-v1.cmake b/Tests/RunCMake/FileAPI/toolchains-v1.cmake
new file mode 100644
index 000000000..367aadef5
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/toolchains-v1.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+
+set(variable_suffixes
+ COMPILER COMPILER_ID COMPILER_VERSION COMPILER_TARGET
+ IMPLICIT_INCLUDE_DIRECTORIES IMPLICIT_LINK_DIRECTORIES
+ IMPLICIT_LINK_FRAMEWORK_DIRECTORIES IMPLICIT_LINK_LIBRARIES
+ SOURCE_FILE_EXTENSIONS)
+set(language CXX)
+set(json "{}")
+
+foreach(variable_suffix ${variable_suffixes})
+ set(variable "CMAKE_${language}_${variable_suffix}")
+ string(JSON json SET "${json}" "${variable}" "{}")
+ if(DEFINED "${variable}")
+ string(JSON json SET "${json}" "${variable}" "defined" "true")
+ string(JSON json SET "${json}" "${variable}" "value" "\"${${variable}}\"")
+ else()
+ string(JSON json SET "${json}" "${variable}" "defined" "false")
+ endif()
+endforeach()
+
+file(WRITE ${CMAKE_BINARY_DIR}/toolchain_variables.json "${json}")
diff --git a/Tests/RunCMake/File_Configure/AtOnly.cmake b/Tests/RunCMake/File_Configure/AtOnly.cmake
new file mode 100644
index 000000000..cc5304a1f
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/AtOnly.cmake
@@ -0,0 +1,12 @@
+set(file_name ${CMAKE_CURRENT_BINARY_DIR}/atonly.txt)
+set(var_a "a")
+set(var_b "b")
+file(CONFIGURE
+ OUTPUT ${file_name}
+ CONTENT "-->@var_a@<-- -->${var_b}<--"
+ @ONLY
+)
+file(READ ${file_name} file_content)
+if(NOT file_content STREQUAL "-->a<-- -->${var_b}<--")
+ message(FATAL_ERROR "@ONLY doesn't work")
+endif()
diff --git a/Tests/RunCMake/File_Configure/BadArg-stderr.txt b/Tests/RunCMake/File_Configure/BadArg-stderr.txt
deleted file mode 100644
index 5423a2822..000000000
--- a/Tests/RunCMake/File_Configure/BadArg-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at BadArg.cmake:[0-9]+ \(file\):
- file Incorrect arguments to CONFIGURE subcommand.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/BadArgContent-result.txt b/Tests/RunCMake/File_Configure/BadArgContent-result.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/BadArgContent-result.txt
diff --git a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
new file mode 100644
index 000000000..a6ea314d5
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArgContent.cmake:[0-9]+ \(file\):
+ file CONFIGURE CONTENT option needs a value.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/BadArgContent.cmake b/Tests/RunCMake/File_Configure/BadArgContent.cmake
new file mode 100644
index 000000000..282dc1846
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/BadArgContent.cmake
@@ -0,0 +1 @@
+file(CONFIGURE CONTENT)
diff --git a/Tests/RunCMake/File_Configure/BadArgOutput-result.txt b/Tests/RunCMake/File_Configure/BadArgOutput-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/BadArgOutput-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
new file mode 100644
index 000000000..b5a924c13
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArgOutput.cmake:[0-9]+ \(file\):
+ file CONFIGURE OUTPUT option needs a value.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/BadArg.cmake b/Tests/RunCMake/File_Configure/BadArgOutput.cmake
index 7c7fcda63..7c7fcda63 100644
--- a/Tests/RunCMake/File_Configure/BadArg.cmake
+++ b/Tests/RunCMake/File_Configure/BadArgOutput.cmake
diff --git a/Tests/RunCMake/File_Configure/EscapeQuotes.cmake b/Tests/RunCMake/File_Configure/EscapeQuotes.cmake
new file mode 100644
index 000000000..1136c873f
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/EscapeQuotes.cmake
@@ -0,0 +1,12 @@
+set(file_name ${CMAKE_CURRENT_BINARY_DIR}/escape_quotes.txt)
+set(var "\t")
+set(ref "${var}")
+file(CONFIGURE
+ CONTENT "-->@ref@<--"
+ OUTPUT ${file_name}
+ ESCAPE_QUOTES
+)
+file(READ ${file_name} file_content)
+if(NOT file_content MATCHES "^-->\t<--$")
+ message(FATAL_ERROR "ESCAPE_QUOTES doesn't work")
+endif()
diff --git a/Tests/RunCMake/File_Configure/NewLineStyle-ValidArg.cmake b/Tests/RunCMake/File_Configure/NewLineStyle-ValidArg.cmake
index e38487366..5e35e5cd7 100644
--- a/Tests/RunCMake/File_Configure/NewLineStyle-ValidArg.cmake
+++ b/Tests/RunCMake/File_Configure/NewLineStyle-ValidArg.cmake
@@ -1,10 +1,13 @@
set(file_name ${CMAKE_CURRENT_BINARY_DIR}/NewLineStyle.txt)
function(test_eol style in out)
+ if (style)
+ set(newline_stle NEWLINE_STYLE ${style})
+ endif()
file(CONFIGURE
OUTPUT ${file_name}
CONTENT "@in@"
- NEWLINE_STYLE ${style}
+ ${newline_stle}
)
file(READ ${file_name} new HEX)
if(NOT "${new}" STREQUAL "${out}")
@@ -18,3 +21,9 @@ test_eol(CRLF "c" "630d0a")
test_eol(UNIX "d" "640a")
test_eol(LF "e" "650a")
+
+if (WIN32)
+ test_eol("" "a\nb" "610d0a62")
+elseif(UNIX)
+ test_eol("" "a\nb" "610a62")
+endif()
diff --git a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
index e79de795f..502298518 100644
--- a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
@@ -1,10 +1,14 @@
include(RunCMake)
run_cmake(AngleBracketsContent)
-run_cmake(BadArg)
+run_cmake(BadArgOutput)
+run_cmake(BadArgContent)
run_cmake(BadArgGeneratorExpressionOutput)
+run_cmake(UnrecognizedArgs)
run_cmake(DirOutput)
run_cmake(NewLineStyle-NoArg)
run_cmake(NewLineStyle-ValidArg)
run_cmake(NewLineStyle-WrongArg)
run_cmake(SubDir)
+run_cmake(AtOnly)
+run_cmake(EscapeQuotes)
diff --git a/Tests/RunCMake/File_Configure/UnrecognizedArgs-result.txt b/Tests/RunCMake/File_Configure/UnrecognizedArgs-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/UnrecognizedArgs-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/UnrecognizedArgs-stderr.txt b/Tests/RunCMake/File_Configure/UnrecognizedArgs-stderr.txt
new file mode 100644
index 000000000..1dd1a20a7
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/UnrecognizedArgs-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at UnrecognizedArgs.cmake:[0-9]+ \(file\):
+ file CONFIGURE Unrecognized argument: "INPUT"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Configure/UnrecognizedArgs.cmake b/Tests/RunCMake/File_Configure/UnrecognizedArgs.cmake
new file mode 100644
index 000000000..93ea7b511
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/UnrecognizedArgs.cmake
@@ -0,0 +1 @@
+file(CONFIGURE INPUT)
diff --git a/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake b/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake
new file mode 100644
index 000000000..0000ef971
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/CustomFilePermissions.cmake
@@ -0,0 +1,15 @@
+file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/customfilepermissions.txt")
+
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/customfilepermissions.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt"
+ FILE_PERMISSIONS
+ OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ GROUP_EXECUTE
+ WORLD_EXECUTE
+ )
+
+add_custom_target(checkCustomFilePermissions ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/customfilepermissions.txt
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/CustomFilePermissionsVerify.cmake"
+ )
diff --git a/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake
new file mode 100644
index 000000000..a87e916d5
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/CustomFilePermissionsVerify.cmake
@@ -0,0 +1,36 @@
+if(NOT EXISTS "${generatedFile}")
+ message(SEND_ERROR "Missing file:\n ${generatedFile}")
+endif()
+
+if (UNIX)
+ find_program(STAT_EXECUTABLE NAMES stat)
+ if(NOT STAT_EXECUTABLE)
+ return()
+ endif()
+
+ if (CMAKE_HOST_SYSTEM_NAME MATCHES "FreeBSD")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${generatedFile}"
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ elseif (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${generatedFile}"
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ else()
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${generatedFile}"
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ endif()
+
+ if (NOT output EQUAL "711")
+ message(SEND_ERROR "file generate has different permissions source "
+ "permissions: \"${output}\" desired permissions: \"711\"")
+ endif()
+
+endif()
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-Default.cmake b/Tests/RunCMake/File_Generate/NewLineStyle-Default.cmake
new file mode 100644
index 000000000..9df8ffe3a
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-Default.cmake
@@ -0,0 +1,35 @@
+function(generate_from_file in out)
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/file_ip.txt "${in}")
+ file(GENERATE
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/file_op.txt
+ INPUT ${CMAKE_CURRENT_BINARY_DIR}/file_ip.txt
+ )
+
+ add_custom_target(verifyContentFromFile ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/file_op.txt
+ -DexpectedContent=${out}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyContent.cmake"
+ )
+endfunction()
+
+function(generate_from_content in out)
+ file(GENERATE
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/content_op.txt
+ CONTENT ${in}
+ )
+
+ add_custom_target(verifyContentFromContent ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/content_op.txt
+ -DexpectedContent=${out}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyContent.cmake"
+ )
+endfunction()
+
+if (WIN32)
+ generate_from_file("a" "610d0a") # 62->b, 0d0a->\r\n
+elseif(UNIX)
+ generate_from_file("a" "610a") # 62->b, 0a->\n
+endif()
+generate_from_content("a" "61")
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-result.txt b/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-stderr.txt b/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-stderr.txt
new file mode 100644
index 000000000..44e32d028
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at NewLineStyle-InvalidArg.cmake:[0-9]+ \(file\):
+ file GENERATE NEWLINE_STYLE sets an unknown style, only LF, CRLF, UNIX,
+ DOS, and WIN32 are supported
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg.cmake b/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg.cmake
new file mode 100644
index 000000000..578cf2162
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-InvalidArg.cmake
@@ -0,0 +1,7 @@
+file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ CONTENT "int main() { return 0; }\n"
+ NEWLINE_STYLE FOO
+ )
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-result.txt b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
new file mode 100644
index 000000000..bc71f2f59
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at NewLineStyle-NoArg.cmake:[0-9]+ \(file\):
+ file Incorrect arguments to GENERATE subcommand.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg.cmake b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg.cmake
new file mode 100644
index 000000000..9bd2ffa44
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg.cmake
@@ -0,0 +1,7 @@
+file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ CONTENT "int main() { return 0; }\n"
+ NEWLINE_STYLE
+ )
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-Unix.cmake b/Tests/RunCMake/File_Generate/NewLineStyle-Unix.cmake
new file mode 100644
index 000000000..7c26217ca
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-Unix.cmake
@@ -0,0 +1,33 @@
+function(generate_from_file in out)
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/file_ip.txt "${in}")
+ file(GENERATE
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/file_op.txt
+ INPUT ${CMAKE_CURRENT_BINARY_DIR}/file_ip.txt
+ NEWLINE_STYLE UNIX
+ )
+
+ add_custom_target(verifyContentFromFile ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/file_op.txt
+ -DexpectedContent=${out}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyContent.cmake"
+ )
+endfunction()
+
+function(generate_from_content in out)
+ file(GENERATE
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/content_op.txt
+ CONTENT ${in}
+ NEWLINE_STYLE UNIX
+ )
+
+ add_custom_target(verifyContentFromContent ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/content_op.txt
+ -DexpectedContent=${out}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyContent.cmake"
+ )
+endfunction()
+
+generate_from_file("a" "610a") # 62->b, 0a->\n
+generate_from_content("a" "610a")
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-Win32.cmake b/Tests/RunCMake/File_Generate/NewLineStyle-Win32.cmake
new file mode 100644
index 000000000..394ef7585
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-Win32.cmake
@@ -0,0 +1,33 @@
+function(generate_from_file in out)
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/file_ip.txt "${in}")
+ file(GENERATE
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/file_op.txt
+ INPUT ${CMAKE_CURRENT_BINARY_DIR}/file_ip.txt
+ NEWLINE_STYLE WIN32
+ )
+
+ add_custom_target(verifyContentFromFile ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/file_op.txt
+ -DexpectedContent=${out}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyContent.cmake"
+ )
+endfunction()
+
+function(generate_from_content in out)
+ file(GENERATE
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/content_op.txt
+ CONTENT ${in}
+ NEWLINE_STYLE WIN32
+ )
+
+ add_custom_target(verifyContentFromContent ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/content_op.txt
+ -DexpectedContent=${out}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/VerifyContent.cmake"
+ )
+endfunction()
+
+generate_from_file("a" "610d0a") # 62->b, 0d0a->\r\n
+generate_from_content("a" "610d0a")
diff --git a/Tests/RunCMake/File_Generate/NoSourcePermissions.cmake b/Tests/RunCMake/File_Generate/NoSourcePermissions.cmake
new file mode 100644
index 000000000..868a0459c
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NoSourcePermissions.cmake
@@ -0,0 +1,10 @@
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/nosourcepermissions.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt"
+ NO_SOURCE_PERMISSIONS
+ )
+
+add_custom_target(checkNoSourcePermission ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/nosourcepermissions.txt
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/NoSourcePermissionsVerify.cmake"
+ )
diff --git a/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake
new file mode 100644
index 000000000..7981ccce1
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/NoSourcePermissionsVerify.cmake
@@ -0,0 +1,36 @@
+if(NOT EXISTS "${generatedFile}")
+ message(SEND_ERROR "Missing generated file:\n ${generatedFile}")
+endif()
+
+if (UNIX)
+ find_program(STAT_EXECUTABLE NAMES stat)
+ if(NOT STAT_EXECUTABLE)
+ return()
+ endif()
+
+ if (CMAKE_HOST_SYSTEM_NAME MATCHES "FreeBSD")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${generatedFile}"
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${generatedFile}"
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ else()
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${generatedFile}"
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ endif()
+
+ if (NOT output EQUAL "644")
+ message(SEND_ERROR "generated file has different permissions than "
+ "desired, generated permissions: \"${output}\"")
+ endif()
+
+endif()
diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
index 48fb71c7c..be3bf04dd 100644
--- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
@@ -123,3 +123,35 @@ set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(AdjacentInOut-nowork ${CMAKE_COMMAND} --build .)
unset(RunCMake_TEST_BINARY_DIR)
unset(RunCMake_TEST_NO_CLEAN)
+
+run_cmake(SourcePermissions1)
+run_cmake(SourcePermissions2)
+run_cmake(SourcePermissions3)
+run_cmake(SourcePermissions4)
+run_cmake(SourcePermissions5)
+
+function(run_cmake_and_verify_after_build case)
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${case}-build")
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
+ else()
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+ run_cmake(${case})
+ run_cmake_command("${case}-build" ${CMAKE_COMMAND} --build .)
+ unset(RunCMake_TEST_NO_CLEAN)
+ unset(RunCMake_TEST_BINARY_DIR)
+endfunction()
+
+run_cmake_and_verify_after_build(NoSourcePermissions)
+run_cmake_and_verify_after_build(UseSourcePermissions)
+run_cmake_and_verify_after_build(CustomFilePermissions)
+
+run_cmake(NewLineStyle-NoArg)
+run_cmake(NewLineStyle-InvalidArg)
+run_cmake_and_verify_after_build(NewLineStyle-Default)
+run_cmake_and_verify_after_build(NewLineStyle-Unix)
+run_cmake_and_verify_after_build(NewLineStyle-Win32)
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions1-result.txt b/Tests/RunCMake/File_Generate/SourcePermissions1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions1-stderr.txt b/Tests/RunCMake/File_Generate/SourcePermissions1-stderr.txt
new file mode 100644
index 000000000..730800d81
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions1-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at SourcePermissions1.cmake:[0-9]+ \(file\):
+ file given both NO_SOURCE_PERMISSIONS and USE_SOURCE_PERMISSIONS. Only one
+ option allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions1.cmake b/Tests/RunCMake/File_Generate/SourcePermissions1.cmake
new file mode 100644
index 000000000..d25e66a00
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions1.cmake
@@ -0,0 +1,5 @@
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-sourcepermission1.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt"
+ NO_SOURCE_PERMISSIONS
+ USE_SOURCE_PERMISSIONS
+ )
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions2-result.txt b/Tests/RunCMake/File_Generate/SourcePermissions2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions2-stderr.txt b/Tests/RunCMake/File_Generate/SourcePermissions2-stderr.txt
new file mode 100644
index 000000000..e8184cc52
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions2-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at SourcePermissions2.cmake:[0-9]+ \(file\):
+ file given both NO_SOURCE_PERMISSIONS and FILE_PERMISSIONS. Only one
+ option allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions2.cmake b/Tests/RunCMake/File_Generate/SourcePermissions2.cmake
new file mode 100644
index 000000000..2a1e3ea02
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions2.cmake
@@ -0,0 +1,5 @@
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-sourcepermission2.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt"
+ NO_SOURCE_PERMISSIONS
+ FILE_PERMISSIONS OWNER_READ
+ )
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions3-result.txt b/Tests/RunCMake/File_Generate/SourcePermissions3-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions3-stderr.txt b/Tests/RunCMake/File_Generate/SourcePermissions3-stderr.txt
new file mode 100644
index 000000000..1143c7871
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions3-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at SourcePermissions3.cmake:[0-9]+ \(file\):
+ file given both USE_SOURCE_PERMISSIONS and FILE_PERMISSIONS. Only one
+ option allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions3.cmake b/Tests/RunCMake/File_Generate/SourcePermissions3.cmake
new file mode 100644
index 000000000..97e0deb4e
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions3.cmake
@@ -0,0 +1,5 @@
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-sourcepermission3.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt"
+ USE_SOURCE_PERMISSIONS
+ FILE_PERMISSIONS OWNER_READ
+ )
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions4-result.txt b/Tests/RunCMake/File_Generate/SourcePermissions4-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions4-stderr.txt b/Tests/RunCMake/File_Generate/SourcePermissions4-stderr.txt
new file mode 100644
index 000000000..84368cde8
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions4-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourcePermissions4.cmake:[0-9]+ \(file\):
+ file given USE_SOURCE_PERMISSIONS without a file INPUT.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions4.cmake b/Tests/RunCMake/File_Generate/SourcePermissions4.cmake
new file mode 100644
index 000000000..f4127a6a9
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions4.cmake
@@ -0,0 +1,4 @@
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-sourcepermission4.txt"
+ CONTENT "Input is content"
+ USE_SOURCE_PERMISSIONS
+ )
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions5-result.txt b/Tests/RunCMake/File_Generate/SourcePermissions5-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions5-stderr.txt b/Tests/RunCMake/File_Generate/SourcePermissions5-stderr.txt
new file mode 100644
index 000000000..d66d48834
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions5-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourcePermissions5.cmake:[0-9]+ \(file\):
+ file given invalid permission "GROUP_RWX","USER_ALL".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/SourcePermissions5.cmake b/Tests/RunCMake/File_Generate/SourcePermissions5.cmake
new file mode 100644
index 000000000..4eb4c3629
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/SourcePermissions5.cmake
@@ -0,0 +1,4 @@
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-sourcepermission5.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt"
+ FILE_PERMISSIONS OWNER_READ GROUP_RWX USER_ALL
+ )
diff --git a/Tests/RunCMake/File_Generate/UseSourcePermissions.cmake b/Tests/RunCMake/File_Generate/UseSourcePermissions.cmake
new file mode 100644
index 000000000..7cca9bf8f
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/UseSourcePermissions.cmake
@@ -0,0 +1,11 @@
+file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/usesourcepermissions.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt"
+ USE_SOURCE_PERMISSIONS
+ )
+
+add_custom_target(checkUseSourcePermissions ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DsourceFile=${CMAKE_CURRENT_SOURCE_DIR}/input.txt
+ -DgeneratedFile=${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/usesourcepermissions.txt
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/UseSourcePermissionsVerify.cmake"
+ )
diff --git a/Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake b/Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake
new file mode 100644
index 000000000..8b30f9679
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/UseSourcePermissionsVerify.cmake
@@ -0,0 +1,51 @@
+if(NOT EXISTS "${generatedFile}")
+ message(SEND_ERROR "Missing generated file:\n ${generatedFile}")
+endif()
+
+if (UNIX)
+ find_program(STAT_EXECUTABLE NAMES stat)
+ if(NOT STAT_EXECUTABLE)
+ return()
+ endif()
+
+ if (CMAKE_HOST_SYSTEM_NAME MATCHES "FreeBSD")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${sourceFile}"
+ OUTPUT_VARIABLE output1
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${generatedFile}"
+ OUTPUT_VARIABLE output2
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ elseif (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${sourceFile}"
+ OUTPUT_VARIABLE output1
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${generatedFile}"
+ OUTPUT_VARIABLE output2
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ else()
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${sourceFile}"
+ OUTPUT_VARIABLE output1
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${generatedFile}"
+ OUTPUT_VARIABLE output2
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ COMMAND_ERROR_IS_FATAL ANY
+ )
+ endif()
+
+ if (NOT output1 EQUAL output2)
+ message(SEND_ERROR "generated file has a different permissions source "
+ "permissions: \"${output1}\" generated permissions: \"${output2}\"")
+ endif()
+
+endif()
diff --git a/Tests/RunCMake/File_Generate/VerifyContent.cmake b/Tests/RunCMake/File_Generate/VerifyContent.cmake
new file mode 100644
index 000000000..8563708fc
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/VerifyContent.cmake
@@ -0,0 +1,4 @@
+file(READ ${generatedFile} actualContent HEX)
+if(NOT "${actualContent}" STREQUAL "${expectedContent}")
+ message(SEND_ERROR "Content mismatch actual: \"${actualContent}\" expected: \"${expectedContent}\"")
+endif()
diff --git a/Tests/RunCMake/FindOpenSSL/CMakeLists.txt b/Tests/RunCMake/FindOpenSSL/CMakeLists.txt
new file mode 100644
index 000000000..4fc11ae75
--- /dev/null
+++ b/Tests/RunCMake/FindOpenSSL/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19...3.20)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/FindOpenSSL/RunCMakeTest.cmake b/Tests/RunCMake/FindOpenSSL/RunCMakeTest.cmake
new file mode 100644
index 000000000..f941a858d
--- /dev/null
+++ b/Tests/RunCMake/FindOpenSSL/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(version)
+run_cmake(version-exact)
+run_cmake(version-range)
diff --git a/Tests/RunCMake/FindOpenSSL/version-exact.cmake b/Tests/RunCMake/FindOpenSSL/version-exact.cmake
new file mode 100644
index 000000000..29c2ce371
--- /dev/null
+++ b/Tests/RunCMake/FindOpenSSL/version-exact.cmake
@@ -0,0 +1,19 @@
+cmake_minimum_required (VERSION 3.19...3.20)
+
+find_package (OpenSSL REQUIRED COMPONENTS Crypto)
+# Store version without a possibly trailing letter.
+string (REGEX MATCH "^([0-9.]+)" version "${OPENSSL_VERSION}")
+
+# clean-up OpenSSL variables
+unset (OPENSSL_INCLUDE_DIR)
+unset (OPENSSL_CRYPTO_LIBRARY)
+unset (OPENSSL_CRYPTO_LIBRARIES)
+unset (OPENSSL_LIBRARIES)
+unset (OPENSSL_VERSION)
+unset (OPENSSL_FOUND)
+
+
+find_package (OpenSSL ${version} EXACT COMPONENTS Crypto)
+if (NOT OPENSSL_FOUND)
+ message (FATAL_ERROR "Failed to find OpenSSL with version ${version} EXACT")
+endif()
diff --git a/Tests/RunCMake/FindOpenSSL/version-range.cmake b/Tests/RunCMake/FindOpenSSL/version-range.cmake
new file mode 100644
index 000000000..939003206
--- /dev/null
+++ b/Tests/RunCMake/FindOpenSSL/version-range.cmake
@@ -0,0 +1,37 @@
+cmake_minimum_required (VERSION 3.19...3.20)
+
+find_package (OpenSSL REQUIRED COMPONENTS Crypto)
+# Store version without a possibly trailing letter.
+string (REGEX MATCH "^([0-9.]+)" version "${OPENSSL_VERSION}")
+
+# clean-up OpenSSL variables
+unset (OPENSSL_INCLUDE_DIR)
+unset (OPENSSL_CRYPTO_LIBRARY)
+unset (OPENSSL_CRYPTO_LIBRARIES)
+unset (OPENSSL_LIBRARIES)
+unset (OPENSSL_VERSION)
+unset (OPENSSL_FOUND)
+
+## Specify a range including current OpenSSL version
+string (REGEX MATCH "^([0-9]+)" upper_version "${version}")
+math (EXPR upper_version "${upper_version} + 1")
+
+find_package (OpenSSL 0.9...${upper_version}.0 COMPONENTS Crypto)
+if (NOT OPENSSL_FOUND)
+ message (FATAL_ERROR "Failed to find OpenSSL with version range 0.9...${upper_version}.0")
+endif()
+
+# clean-up OpenSSL variables
+unset (OPENSSL_INCLUDE_DIR)
+unset (OPENSSL_CRYPTO_LIBRARY)
+unset (OPENSSL_CRYPTO_LIBRARIES)
+unset (OPENSSL_LIBRARIES)
+unset (OPENSSL_VERSION)
+unset (OPENSSL_FOUND)
+
+## Specify a range excluding current OpenSSL version
+set (range 0.9...<${version})
+find_package (OpenSSL ${range} COMPONENTS Crypto)
+if (OPENSSL_FOUND)
+ message (FATAL_ERROR "Unexpectedly find OpenSSL with version range ${range}")
+endif()
diff --git a/Tests/RunCMake/FindOpenSSL/version.cmake b/Tests/RunCMake/FindOpenSSL/version.cmake
new file mode 100644
index 000000000..d06cd1f2b
--- /dev/null
+++ b/Tests/RunCMake/FindOpenSSL/version.cmake
@@ -0,0 +1,19 @@
+cmake_minimum_required (VERSION 3.19...3.20)
+
+find_package (OpenSSL REQUIRED COMPONENTS Crypto)
+# Store version without a possibly trailing letter.
+string (REGEX MATCH "^([0-9.]+)" version "${OPENSSL_VERSION}")
+
+# clean-up OpenSSL variables
+unset (OPENSSL_INCLUDE_DIR)
+unset (OPENSSL_CRYPTO_LIBRARY)
+unset (OPENSSL_CRYPTO_LIBRARIES)
+unset (OPENSSL_LIBRARIES)
+unset (OPENSSL_VERSION)
+unset (OPENSSL_FOUND)
+
+
+find_package (OpenSSL ${version} COMPONENTS Crypto)
+if (NOT OPENSSL_FOUND)
+ message (FATAL_ERROR "Failed to find OpenSSL with version ${version}")
+endif()
diff --git a/Tests/RunCMake/GNUInstallDirs/GetAbs-stderr.txt b/Tests/RunCMake/GNUInstallDirs/GetAbs-stderr.txt
new file mode 100644
index 000000000..ec9a2dd86
--- /dev/null
+++ b/Tests/RunCMake/GNUInstallDirs/GetAbs-stderr.txt
@@ -0,0 +1,12 @@
+^PROJ1_FULL_BINDIR='/usr/bin'
+CMake Warning \(dev\) at [^
+]*/Modules/GNUInstallDirs.cmake:[0-9]+ \(message\):
+ GNUInstallDirs_get_absolute_install_dir called without third argument.
+ Using \${dir} from the caller's scope for compatibility with CMake 3.19 and
+ below.
+Call Stack \(most recent call first\):
+ GetAbs.cmake:10 \(GNUInstallDirs_get_absolute_install_dir\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+PROJ2_FULL_BINDIR='/usr/bin'$
diff --git a/Tests/RunCMake/GNUInstallDirs/GetAbs.cmake b/Tests/RunCMake/GNUInstallDirs/GetAbs.cmake
new file mode 100644
index 000000000..7d5bfc859
--- /dev/null
+++ b/Tests/RunCMake/GNUInstallDirs/GetAbs.cmake
@@ -0,0 +1,11 @@
+set(CMAKE_SIZEOF_VOID_P 8)
+set(CMAKE_LIBRARY_ARCHITECTURE "arch")
+set(CMAKE_INSTALL_PREFIX /usr)
+include(GNUInstallDirs)
+
+GNUInstallDirs_get_absolute_install_dir(PROJ1_FULL_BINDIR CMAKE_INSTALL_BINDIR BINDIR)
+message("PROJ1_FULL_BINDIR='${PROJ1_FULL_BINDIR}'")
+
+set(dir BINDIR)
+GNUInstallDirs_get_absolute_install_dir(PROJ2_FULL_BINDIR CMAKE_INSTALL_BINDIR)
+message("PROJ2_FULL_BINDIR='${PROJ2_FULL_BINDIR}'")
diff --git a/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake b/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake
index 529e10a22..395ff30e6 100644
--- a/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake
@@ -21,4 +21,5 @@ foreach(case
unset(RunCMake-stderr-file)
endforeach()
+run_cmake(GetAbs)
run_cmake(NoSystem)
diff --git a/Tests/RunCMake/GenerateExportHeader/GEH.cmake b/Tests/RunCMake/GenerateExportHeader/GEH.cmake
index ae9a84c43..431d1ce40 100644
--- a/Tests/RunCMake/GenerateExportHeader/GEH.cmake
+++ b/Tests/RunCMake/GenerateExportHeader/GEH.cmake
@@ -103,7 +103,7 @@ add_executable(GenerateExportHeader exportheader_test.cpp)
target_link_libraries(GenerateExportHeader ${link_libraries})
if (WIN32 OR CYGWIN)
- if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND
+ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") AND
CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
set(_platform Win32-Clang)
elseif(MSVC AND COMPILER_HAS_DEPRECATED)
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
index 634911274..edeb6bde7 100644
--- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -35,6 +35,9 @@ run_cmake(TARGET_NAME_IF_EXISTS-no-arg)
run_cmake(TARGET_NAME_IF_EXISTS-empty-arg)
run_cmake(TARGET_NAME_IF_EXISTS)
run_cmake(TARGET_NAME_IF_EXISTS-not-a-target)
+run_cmake(TARGET_NAME_IF_EXISTS-alias-target)
+run_cmake(TARGET_NAME_IF_EXISTS-imported-target)
+run_cmake(TARGET_NAME_IF_EXISTS-imported-global-target)
run_cmake(REMOVE_DUPLICATES-empty)
run_cmake(REMOVE_DUPLICATES-1)
run_cmake(REMOVE_DUPLICATES-2)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target-check.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target-check.cmake
new file mode 100644
index 000000000..8ae2eccd1
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target-check.cmake
@@ -0,0 +1,5 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_NAME_IF_EXISTS-generated-alias.txt" content)
+
+if(NOT content STREQUAL aliasTarget)
+ set(RunCMake_TEST_FAILED "actual content:\n ${content}\nbut expected [[aliasTarget]]")
+endif()
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target.cmake
new file mode 100644
index 000000000..d3ef0f8b0
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-alias-target.cmake
@@ -0,0 +1,8 @@
+enable_language(CXX)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy_executable.cpp" "int main(int,char**) { return 0; }\n")
+add_executable(executableTarget "${CMAKE_CURRENT_BINARY_DIR}/dummy_executable.cpp")
+add_executable(aliasTarget ALIAS executableTarget)
+
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated-alias.txt CONTENT "$<TARGET_NAME_IF_EXISTS:aliasTarget>")
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target-check.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target-check.cmake
new file mode 100644
index 000000000..b14c9e164
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target-check.cmake
@@ -0,0 +1,5 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_NAME_IF_EXISTS-generated-imported-global.txt" content)
+
+if(NOT content STREQUAL importedGlobalTarget)
+ set(RunCMake_TEST_FAILED "actual content:\n ${content}\nbut expected [[importedGlobalTarget]]")
+endif()
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target.cmake
new file mode 100644
index 000000000..b68555826
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-global-target.cmake
@@ -0,0 +1,4 @@
+add_executable(importedGlobalTarget IMPORTED GLOBAL)
+
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated-imported-global.txt CONTENT "$<TARGET_NAME_IF_EXISTS:importedGlobalTarget>")
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target-check.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target-check.cmake
new file mode 100644
index 000000000..9615893ff
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target-check.cmake
@@ -0,0 +1,5 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_NAME_IF_EXISTS-generated-imported.txt" content)
+
+if(NOT content STREQUAL importedTarget)
+ set(RunCMake_TEST_FAILED "actual content:\n ${content}\nbut expected [[importedTarget]]")
+endif()
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target.cmake
new file mode 100644
index 000000000..200890768
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_NAME_IF_EXISTS-imported-target.cmake
@@ -0,0 +1,4 @@
+add_executable(importedTarget IMPORTED)
+
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_NAME_IF_EXISTS-generated-imported.txt CONTENT "$<TARGET_NAME_IF_EXISTS:importedTarget>")
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt
index 7fb39194a..2a53c5b50 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test1-stdout.txt
@@ -1,31 +1,35 @@
Test project .*
Start 1: TEST:basic\.case_foo!1
- 1/11 Test #1: TEST:basic\.case_foo!1 \.+ +Passed +[0-9.]+ sec
+ 1/13 Test #1: TEST:basic\.case_foo!1 \.+ +Passed +[0-9.]+ sec
Start 2: TEST:basic\.case_bar!1
- 2/11 Test #2: TEST:basic\.case_bar!1 \.+ +Passed +[0-9.]+ sec
+ 2/13 Test #2: TEST:basic\.case_bar!1 \.+ +Passed +[0-9.]+ sec
Start 3: TEST:basic\.disabled_case!1
- 3/11 Test #3: TEST:basic\.disabled_case!1 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
- Start 4: TEST:disabled\.case!1
- 4/11 Test #4: TEST:disabled\.case!1 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
- Start 5: TEST:typed/short\.case!1
- 5/11 Test #5: TEST:typed/short\.case!1 \.+ +Passed +[0-9.]+ sec
- Start 6: TEST:typed/float\.case!1
- 6/11 Test #6: TEST:typed/float\.case!1 \.+ +Passed +[0-9.]+ sec
- Start 7: TEST:value/test\.case/1!1
- 7/11 Test #7: TEST:value/test\.case/1!1 \.+ +Passed +[0-9.]+ sec
- Start 8: TEST:value/test\.case/"foo"!1
- 8/11 Test #8: TEST:value/test\.case/"foo"!1 \.+ +Passed +[0-9.]+ sec
- Start 9: TEST:param/special\.case/"semicolon;"!1
- 9/11 Test #9: TEST:param/special\.case/"semicolon;"!1 \.+ +Passed +[0-9.]+ sec
- Start 10: TEST:param/special\.case/"backslash\\"!1
-10/11 Test #10: TEST:param/special\.case/"backslash\\"!1 \.+ +Passed +[0-9.]+ sec
- Start 11: TEST:param/special\.case/"\$\{var\}"!1
-11/11 Test #11: TEST:param/special\.case/"\$\{var\}"!1 \.+ +Passed +[0-9.]+ sec
+ 3/13 Test #3: TEST:basic\.disabled_case!1 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
+ Start 4: TEST:basic\.DISABLEDnot_really_case!1
+ 4/13 Test #4: TEST:basic\.DISABLEDnot_really_case!1 \.+ +Passed +[0-9.]+ sec
+ Start 5: TEST:disabled\.case!1
+ 5/13 Test #5: TEST:disabled\.case!1 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
+ Start 6: TEST:DISABLEDnotreally\.case!1
+ 6/13 Test #6: TEST:DISABLEDnotreally\.case!1 \.+ +Passed +[0-9.]+ sec
+ Start 7: TEST:typed/short\.case!1
+ 7/13 Test #7: TEST:typed/short\.case!1 \.+ +Passed +[0-9.]+ sec
+ Start 8: TEST:typed/float\.case!1
+ 8/13 Test #8: TEST:typed/float\.case!1 \.+ +Passed +[0-9.]+ sec
+ Start 9: TEST:value/test\.case/1!1
+ 9/13 Test #9: TEST:value/test\.case/1!1 \.+ +Passed +[0-9.]+ sec
+ Start 10: TEST:value/test\.case/"foo"!1
+10/13 Test #10: TEST:value/test\.case/"foo"!1 \.+ +Passed +[0-9.]+ sec
+ Start 11: TEST:param/special\.case/"semicolon;"!1
+11/13 Test #11: TEST:param/special\.case/"semicolon;"!1 \.+ +Passed +[0-9.]+ sec
+ Start 12: TEST:param/special\.case/"backslash\\"!1
+12/13 Test #12: TEST:param/special\.case/"backslash\\"!1 \.+ +Passed +[0-9.]+ sec
+ Start 13: TEST:param/special\.case/"\$\{var\}"!1
+13/13 Test #13: TEST:param/special\.case/"\$\{var\}"!1 \.+ +Passed +[0-9.]+ sec
-100% tests passed, 0 tests failed out of 9
+100% tests passed, 0 tests failed out of 11
Total Test time \(real\) = +[0-9.]+ sec
The following tests did not run:
.*3 - TEST:basic\.disabled_case!1 \(Disabled\)
-.*4 - TEST:disabled\.case!1 \(Disabled\)
+.*5 - TEST:disabled\.case!1 \(Disabled\)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt
index 58c4d108a..5b68e10d2 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test2-stdout.txt
@@ -1,31 +1,35 @@
Test project .*
- Start 12: TEST:basic\.case_foo!2
- 1/11 Test #12: TEST:basic\.case_foo!2 \.+ +Passed +[0-9.]+ sec
- Start 13: TEST:basic\.case_bar!2
- 2/11 Test #13: TEST:basic\.case_bar!2 \.+ +Passed +[0-9.]+ sec
- Start 14: TEST:basic\.disabled_case!2
- 3/11 Test #14: TEST:basic\.disabled_case!2 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
- Start 15: TEST:disabled\.case!2
- 4/11 Test #15: TEST:disabled\.case!2 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
- Start 16: TEST:typed/short\.case!2
- 5/11 Test #16: TEST:typed/short\.case!2 \.+ +Passed +[0-9.]+ sec
- Start 17: TEST:typed/float\.case!2
- 6/11 Test #17: TEST:typed/float\.case!2 \.+ +Passed +[0-9.]+ sec
- Start 18: TEST:value/test\.case/1!2
- 7/11 Test #18: TEST:value/test\.case/1!2 \.+ +Passed +[0-9.]+ sec
- Start 19: TEST:value/test\.case/"foo"!2
- 8/11 Test #19: TEST:value/test\.case/"foo"!2 \.+ +Passed +[0-9.]+ sec
- Start 20: TEST:param/special\.case/"semicolon;"!2
- 9/11 Test #20: TEST:param/special\.case/"semicolon;"!2 \.+ +Passed +[0-9.]+ sec
- Start 21: TEST:param/special\.case/"backslash\\"!2
-10/11 Test #21: TEST:param/special\.case/"backslash\\"!2 \.+ +Passed +[0-9.]+ sec
- Start 22: TEST:param/special\.case/"\$\{var\}"!2
-11/11 Test #22: TEST:param/special\.case/"\$\{var\}"!2 \.+ +Passed +[0-9.]+ sec
+ Start 14: TEST:basic\.case_foo!2
+ 1/13 Test #14: TEST:basic\.case_foo!2 \.+ +Passed +[0-9.]+ sec
+ Start 15: TEST:basic\.case_bar!2
+ 2/13 Test #15: TEST:basic\.case_bar!2 \.+ +Passed +[0-9.]+ sec
+ Start 16: TEST:basic\.disabled_case!2
+ 3/13 Test #16: TEST:basic\.disabled_case!2 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
+ Start 17: TEST:basic\.DISABLEDnot_really_case!2
+ 4/13 Test #17: TEST:basic\.DISABLEDnot_really_case!2 \.+ +Passed +[0-9.]+ sec
+ Start 18: TEST:disabled\.case!2
+ 5/13 Test #18: TEST:disabled\.case!2 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
+ Start 19: TEST:DISABLEDnotreally\.case!2
+ 6/13 Test #19: TEST:DISABLEDnotreally\.case!2 \.+ +Passed +[0-9.]+ sec
+ Start 20: TEST:typed/short\.case!2
+ 7/13 Test #20: TEST:typed/short\.case!2 \.+ +Passed +[0-9.]+ sec
+ Start 21: TEST:typed/float\.case!2
+ 8/13 Test #21: TEST:typed/float\.case!2 \.+ +Passed +[0-9.]+ sec
+ Start 22: TEST:value/test\.case/1!2
+ 9/13 Test #22: TEST:value/test\.case/1!2 \.+ +Passed +[0-9.]+ sec
+ Start 23: TEST:value/test\.case/"foo"!2
+10/13 Test #23: TEST:value/test\.case/"foo"!2 \.+ +Passed +[0-9.]+ sec
+ Start 24: TEST:param/special\.case/"semicolon;"!2
+11/13 Test #24: TEST:param/special\.case/"semicolon;"!2 \.+ +Passed +[0-9.]+ sec
+ Start 25: TEST:param/special\.case/"backslash\\"!2
+12/13 Test #25: TEST:param/special\.case/"backslash\\"!2 \.+ +Passed +[0-9.]+ sec
+ Start 26: TEST:param/special\.case/"\$\{var\}"!2
+13/13 Test #26: TEST:param/special\.case/"\$\{var\}"!2 \.+ +Passed +[0-9.]+ sec
-100% tests passed, 0 tests failed out of 9
+100% tests passed, 0 tests failed out of 11
Total Test time \(real\) = +[0-9.]+ sec
The following tests did not run:
-.*14 - TEST:basic\.disabled_case!2 \(Disabled\)
-.*15 - TEST:disabled\.case!2 \(Disabled\)
+.*16 - TEST:basic\.disabled_case!2 \(Disabled\)
+.*18 - TEST:disabled\.case!2 \(Disabled\)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest.cmake b/Tests/RunCMake/GoogleTest/GoogleTest.cmake
index 6aa265876..8efd1171d 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest.cmake
+++ b/Tests/RunCMake/GoogleTest/GoogleTest.cmake
@@ -1,9 +1,12 @@
-project(test_include_dirs LANGUAGES CXX)
+enable_language(CXX)
include(GoogleTest)
enable_testing()
+include(xcode_sign_adhoc.cmake)
+
add_executable(fake_gtest fake_gtest.cpp)
+xcode_sign_adhoc(fake_gtest)
gtest_discover_tests(
fake_gtest
@@ -22,6 +25,7 @@ gtest_discover_tests(
)
add_executable(no_tests_defined no_tests_defined.cpp)
+xcode_sign_adhoc(no_tests_defined)
gtest_discover_tests(
no_tests_defined
@@ -33,6 +37,7 @@ gtest_discover_tests(
# 3.10.3 and later behavior, old behavior added in 3.10.1
# is not supported.
add_executable(property_timeout_test timeout_test.cpp)
+xcode_sign_adhoc(property_timeout_test)
target_compile_definitions(property_timeout_test PRIVATE sleepSec=10)
gtest_discover_tests(
@@ -50,6 +55,7 @@ gtest_discover_tests(
)
add_executable(skip_test skip_test.cpp)
+xcode_sign_adhoc(skip_test)
gtest_discover_tests(
skip_test
diff --git a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryMultiConfig.cmake b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryMultiConfig.cmake
index df784feeb..2fae1e233 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryMultiConfig.cmake
+++ b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryMultiConfig.cmake
@@ -1,9 +1,12 @@
-project(test_include_dirs LANGUAGES CXX)
+enable_language(CXX)
include(GoogleTest)
enable_testing()
+include(xcode_sign_adhoc.cmake)
+
add_executable(configuration_gtest configuration_gtest.cpp)
+xcode_sign_adhoc(configuration_gtest)
target_compile_definitions(configuration_gtest PRIVATE $<$<CONFIG:Debug>:DEBUG=1>)
gtest_discover_tests(
diff --git a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTimeout.cmake b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTimeout.cmake
index 20e9d657a..5c24d4118 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTimeout.cmake
+++ b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTimeout.cmake
@@ -1,9 +1,12 @@
-project(test_include_dirs LANGUAGES CXX)
+enable_language(CXX)
include(GoogleTest)
enable_testing()
+include(xcode_sign_adhoc.cmake)
+
add_executable(discovery_timeout_test timeout_test.cpp)
+xcode_sign_adhoc(discovery_timeout_test)
target_compile_definitions(discovery_timeout_test PRIVATE discoverySleepSec=10)
gtest_discover_tests(
discovery_timeout_test
diff --git a/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake b/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake
index fb91c0e66..53eedc041 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake
+++ b/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake
@@ -1,8 +1,10 @@
-project(test_include_dirs LANGUAGES CXX)
+enable_language(CXX)
include(GoogleTest)
enable_testing()
+include(xcode_sign_adhoc.cmake)
+
# This creates the folder structure for the paramterized tests
# to avoid handling missing folders in C++
#
@@ -15,6 +17,7 @@ enable_testing()
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/GoogleTestXMLSpecial/cases.case")
add_executable(xml_output xml_output.cpp)
+xcode_sign_adhoc(xml_output)
gtest_discover_tests(
xml_output
XML_OUTPUT_DIR ${CMAKE_BINARY_DIR}
diff --git a/Tests/RunCMake/GoogleTest/fake_gtest.cpp b/Tests/RunCMake/GoogleTest/fake_gtest.cpp
index a8127bf95..1956c37fe 100644
--- a/Tests/RunCMake/GoogleTest/fake_gtest.cpp
+++ b/Tests/RunCMake/GoogleTest/fake_gtest.cpp
@@ -12,8 +12,11 @@ int main(int argc, char** argv)
std::cout << " case_foo" << std::endl;
std::cout << " case_bar" << std::endl;
std::cout << " DISABLED_disabled_case" << std::endl;
+ std::cout << " DISABLEDnot_really_case" << std::endl;
std::cout << "DISABLED_disabled." << std::endl;
std::cout << " case" << std::endl;
+ std::cout << "DISABLEDnotreally." << std::endl;
+ std::cout << " case" << std::endl;
std::cout << "typed/0. # TypeParam = short" << std::endl;
std::cout << " case" << std::endl;
std::cout << "typed/1. # TypeParam = float" << std::endl;
diff --git a/Tests/RunCMake/GoogleTest/xcode_sign_adhoc.cmake b/Tests/RunCMake/GoogleTest/xcode_sign_adhoc.cmake
new file mode 100644
index 000000000..d2dc5305b
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/xcode_sign_adhoc.cmake
@@ -0,0 +1,8 @@
+function(xcode_sign_adhoc target)
+ if(CMAKE_GENERATOR STREQUAL "Xcode" AND
+ "${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64")
+ # Xcode runs POST_BUILD before signing, so let the linker use ad-hoc signing.
+ # See CMake Issue 21845.
+ target_link_options(${target} PRIVATE LINKER:-adhoc_codesign)
+ endif()
+endfunction()
diff --git a/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-NEW.cmake b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-NEW.cmake
new file mode 100644
index 000000000..c8b0a9110
--- /dev/null
+++ b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0117 NEW)
+include(CMP0117-common.cmake)
diff --git a/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-OLD.cmake b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-OLD.cmake
new file mode 100644
index 000000000..c0a61d0d8
--- /dev/null
+++ b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0117 OLD)
+include(CMP0117-common.cmake)
diff --git a/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-WARN.cmake b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-WARN.cmake
new file mode 100644
index 000000000..37d1b64c4
--- /dev/null
+++ b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(CMP0117-common.cmake)
diff --git a/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-common.cmake b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-common.cmake
new file mode 100644
index 000000000..5dda623e3
--- /dev/null
+++ b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMP0117-common.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+
+cmake_policy(GET CMP0117 cmp0117)
+if(cmp0117 STREQUAL "NEW")
+ if(" ${CMAKE_CXX_FLAGS} " MATCHES " ([/-]GR) ")
+ message(SEND_ERROR "CMAKE_CXX_FLAGS has '${CMAKE_MATCH_1}' under NEW behavior")
+ endif()
+else()
+ if(NOT " ${CMAKE_CXX_FLAGS} " MATCHES " /GR ")
+ message(SEND_ERROR "CMAKE_CXX_FLAGS does not have '/GR' under OLD behavior")
+ endif()
+endif()
diff --git a/Tests/RunCMake/MSVCRuntimeTypeInfo/CMakeLists.txt b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMakeLists.txt
new file mode 100644
index 000000000..3e470a29c
--- /dev/null
+++ b/Tests/RunCMake/MSVCRuntimeTypeInfo/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.14)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/MSVCRuntimeTypeInfo/RunCMakeTest.cmake b/Tests/RunCMake/MSVCRuntimeTypeInfo/RunCMakeTest.cmake
new file mode 100644
index 000000000..c870f5919
--- /dev/null
+++ b/Tests/RunCMake/MSVCRuntimeTypeInfo/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0117-WARN)
+run_cmake(CMP0117-OLD)
+run_cmake(CMP0117-NEW)
diff --git a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt b/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt
deleted file mode 100644
index 74d62a47d..000000000
--- a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-^CMake Error at CustomCommandDepfile-ERROR.cmake:1 \(add_custom_command\):
- add_custom_command Option DEPFILE not supported by [^
-]+
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake b/Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake
deleted file mode 100644
index bad795501..000000000
--- a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake
+++ /dev/null
@@ -1,8 +0,0 @@
-add_custom_command(
- OUTPUT hello.copy.c
- COMMAND "${CMAKE_COMMAND}" -E copy
- "${CMAKE_CURRENT_SOURCE_DIR}/hello.c"
- hello.copy.c
- WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
- DEPFILE "test.d"
- )
diff --git a/Tests/RunCMake/Make/MakefileConflict.cmake b/Tests/RunCMake/Make/MakefileConflict.cmake
new file mode 100644
index 000000000..6a8406f2f
--- /dev/null
+++ b/Tests/RunCMake/Make/MakefileConflict.cmake
@@ -0,0 +1,5 @@
+add_custom_target(Custom)
+
+# Write a file that GNU make will prefer over "Makefile"
+# if 'cmake --build' does not explicitly specify it.
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/GNUmakefile" "")
diff --git a/Tests/RunCMake/Make/RunCMakeTest.cmake b/Tests/RunCMake/Make/RunCMakeTest.cmake
index 5562acabd..c7717ec1d 100644
--- a/Tests/RunCMake/Make/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Make/RunCMakeTest.cmake
@@ -39,9 +39,16 @@ function(run_VerboseBuild)
endfunction()
run_VerboseBuild()
-run_cmake(CustomCommandDepfile-ERROR)
run_cmake(IncludeRegexSubdir)
+function(run_MakefileConflict)
+ run_cmake(MakefileConflict)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/MakefileConflict-build)
+ run_cmake_command(MakefileConflict-build ${CMAKE_COMMAND} --build . --target Custom)
+endfunction()
+run_MakefileConflict()
+
function(run_CMP0113 val)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0113-${val}-build)
run_cmake(CMP0113-${val})
diff --git a/Tests/RunCMake/Make/TargetMessages-OFF-build-check.cmake b/Tests/RunCMake/Make/TargetMessages-OFF-build-check.cmake
new file mode 100644
index 000000000..74a056408
--- /dev/null
+++ b/Tests/RunCMake/Make/TargetMessages-OFF-build-check.cmake
@@ -0,0 +1,3 @@
+
+set (CHECK_TARGET_MESSAGES OFF)
+include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
diff --git a/Tests/RunCMake/Make/TargetMessages-OFF-build-stdout.txt b/Tests/RunCMake/Make/TargetMessages-OFF-build-stdout.txt
index 77a582a68..8d98f9deb 100644
--- a/Tests/RunCMake/Make/TargetMessages-OFF-build-stdout.txt
+++ b/Tests/RunCMake/Make/TargetMessages-OFF-build-stdout.txt
@@ -1,5 +1 @@
-^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*
-)*Scanning dependencies of target CustomTarget(
-([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*)*$
+.*
diff --git a/Tests/RunCMake/Make/TargetMessages-ON-build-check.cmake b/Tests/RunCMake/Make/TargetMessages-ON-build-check.cmake
new file mode 100644
index 000000000..afd8efb7a
--- /dev/null
+++ b/Tests/RunCMake/Make/TargetMessages-ON-build-check.cmake
@@ -0,0 +1,3 @@
+
+set (CHECK_TARGET_MESSAGES ON)
+include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
diff --git a/Tests/RunCMake/Make/TargetMessages-ON-build-stdout.txt b/Tests/RunCMake/Make/TargetMessages-ON-build-stdout.txt
index a827624bc..8d98f9deb 100644
--- a/Tests/RunCMake/Make/TargetMessages-ON-build-stdout.txt
+++ b/Tests/RunCMake/Make/TargetMessages-ON-build-stdout.txt
@@ -1,8 +1 @@
-^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*
-)*Scanning dependencies of target CustomTarget(
-([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*)*
-Built target CustomTarget(
-([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*)*$
+.*
diff --git a/Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-check.cmake b/Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-check.cmake
new file mode 100644
index 000000000..74a056408
--- /dev/null
+++ b/Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-check.cmake
@@ -0,0 +1,3 @@
+
+set (CHECK_TARGET_MESSAGES OFF)
+include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
diff --git a/Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-stdout.txt b/Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-stdout.txt
index 77a582a68..8d98f9deb 100644
--- a/Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-stdout.txt
+++ b/Tests/RunCMake/Make/TargetMessages-VAR-OFF-build-stdout.txt
@@ -1,5 +1 @@
-^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*
-)*Scanning dependencies of target CustomTarget(
-([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*)*$
+.*
diff --git a/Tests/RunCMake/Make/TargetMessages-VAR-ON-build-check.cmake b/Tests/RunCMake/Make/TargetMessages-VAR-ON-build-check.cmake
new file mode 100644
index 000000000..afd8efb7a
--- /dev/null
+++ b/Tests/RunCMake/Make/TargetMessages-VAR-ON-build-check.cmake
@@ -0,0 +1,3 @@
+
+set (CHECK_TARGET_MESSAGES ON)
+include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
diff --git a/Tests/RunCMake/Make/TargetMessages-VAR-ON-build-stdout.txt b/Tests/RunCMake/Make/TargetMessages-VAR-ON-build-stdout.txt
index a827624bc..8d98f9deb 100644
--- a/Tests/RunCMake/Make/TargetMessages-VAR-ON-build-stdout.txt
+++ b/Tests/RunCMake/Make/TargetMessages-VAR-ON-build-stdout.txt
@@ -1,8 +1 @@
-^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*
-)*Scanning dependencies of target CustomTarget(
-([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*)*
-Built target CustomTarget(
-([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
-]*)*$
+.*
diff --git a/Tests/RunCMake/Make/TargetMessages-validation.cmake b/Tests/RunCMake/Make/TargetMessages-validation.cmake
new file mode 100644
index 000000000..f3d7af198
--- /dev/null
+++ b/Tests/RunCMake/Make/TargetMessages-validation.cmake
@@ -0,0 +1,10 @@
+
+if (CHECK_TARGET_MESSAGES)
+ if (NOT actual_stdout MATCHES "Built target CustomTarget")
+ set (RunCMake_TEST_FAILED "Not found expected 'Built target' message.")
+ endif()
+else()
+ if (actual_stdout MATCHES "Built target CustomTarget")
+ set (RunCMake_TEST_FAILED "Found unexpected 'Built target' message.")
+ endif()
+endif()
diff --git a/Tests/RunCMake/Ninja/AssumedSources.cmake b/Tests/RunCMake/Ninja/AssumedSources.cmake
index 5fb02199d..d5364f027 100644
--- a/Tests/RunCMake/Ninja/AssumedSources.cmake
+++ b/Tests/RunCMake/Ninja/AssumedSources.cmake
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.8)
+cmake_policy(SET CMP0118 NEW)
project(AssumedSources)
set_source_files_properties(
diff --git a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake b/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake
index d69a119ac..74566086c 100644
--- a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake
+++ b/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake
@@ -7,3 +7,7 @@ set(CMAKE_AUTOMOC ON)
add_library(simple_lib SHARED simple_lib.cpp)
add_executable(app_with_qt app.cpp app_qt.cpp)
target_link_libraries(app_with_qt PRIVATE simple_lib Qt5::Core)
+
+add_subdirectory(QtSubDir1)
+add_subdirectory(QtSubDir2)
+add_subdirectory(QtSubDir3)
diff --git a/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt
new file mode 100644
index 000000000..64016b683
--- /dev/null
+++ b/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0116 OLD)
+
+add_executable(sub_exe_1 ../app.cpp)
+target_link_libraries(sub_exe_1 PRIVATE Qt5::Core)
diff --git a/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt
new file mode 100644
index 000000000..3176426f4
--- /dev/null
+++ b/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0116 NEW)
+
+add_executable(sub_exe_2 ../app.cpp)
+target_link_libraries(sub_exe_2 PRIVATE Qt5::Core)
diff --git a/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt
new file mode 100644
index 000000000..d38cfe076
--- /dev/null
+++ b/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(sub_exe_3 ../app.cpp)
+target_link_libraries(sub_exe_3 PRIVATE Qt5::Core)
diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
index 35be2ecfc..1b252cd18 100644
--- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
@@ -340,8 +340,17 @@ function(run_Qt5AutoMocDeps)
# Build and assert that AUTOMOC was not run for app_with_qt.
run_ninja("${RunCMake_TEST_BINARY_DIR}")
if(ninja_stdout MATCHES "Automatic MOC for target app_with_qt")
- message(FATAL_ERROR
- "AUTOMOC should not have executed for 'app_with_qt' target:\nstdout:\n${ninja_stdout}")
+ message(FATAL_ERROR
+ "AUTOMOC should not have executed for 'app_with_qt' target:\nstdout:\n${ninja_stdout}")
+ endif()
+ # Assert that the subdir executables were not rebuilt.
+ if(ninja_stdout MATCHES "Automatic MOC for target sub_exe_1")
+ message(FATAL_ERROR
+ "AUTOMOC should not have executed for 'sub_exe_1' target:\nstdout:\n${ninja_stdout}")
+ endif()
+ if(ninja_stdout MATCHES "Automatic MOC for target sub_exe_2")
+ message(FATAL_ERROR
+ "AUTOMOC should not have executed for 'sub_exe_2' target:\nstdout:\n${ninja_stdout}")
endif()
endif()
endfunction()
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-again-ninja-check.cmake
index 1e4cbe10d..1e4cbe10d 100644
--- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-again-ninja-check.cmake
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..cc2e49a01
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_genex_Debug\.txt
+depend_echo_genex_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-ninja-stdout.txt
new file mode 100644
index 000000000..cc2e49a01
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_genex_Debug\.txt
+depend_echo_genex_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..214e747d4
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_genex_cmd_Debug\.txt
+depend_echo_genex_cmd_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-ninja-stdout.txt
new file mode 100644
index 000000000..842336dbd
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_cmd-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_genex_cmd_Debug\.txt
+depend_echo_genex_cmd_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..eafe30b06
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_genex_out_Debug\.txt
+depend_echo_genex_out_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-ninja-stdout.txt
new file mode 100644
index 000000000..eafe30b06
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_genex_out-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_genex_out_Debug\.txt
+depend_echo_genex_out_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..e7b74b952
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_raw_Debug\.txt
+depend_echo_raw_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-ninja-stdout.txt
new file mode 100644
index 000000000..2e01d6a93
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-depend_echo_raw-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating depend_echo_raw_Debug\.txt
+depend_echo_raw_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..7455c258f
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] Generating echo_depend_Debug\.txt
+echo_depend_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-ninja-stdout.txt
new file mode 100644
index 000000000..7455c258f
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] Generating echo_depend_Debug\.txt
+echo_depend_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..6d5620d56
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Release\.txt
+depend_Release\.txt
+\[2/2\] Generating echo_depend_cmd_Debug\.txt
+echo_depend_cmd_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-ninja-stdout.txt
new file mode 100644
index 000000000..2f0f1f11d
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_cmd-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] Generating echo_depend_cmd_Debug\.txt
+echo_depend_cmd_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..39f547152
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] Generating echo_depend_out_Debug\.txt
+echo_depend_out_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-ninja-stdout.txt
new file mode 100644
index 000000000..39f547152
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_out-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] Generating echo_depend_out_Debug\.txt
+echo_depend_out_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..cc43cda6b
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] Generating echo_genex_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release' 'echo_genex_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-ninja-stdout.txt
new file mode 100644
index 000000000..11985c693
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_genex_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_genex_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..68a8cd12c
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_genex_out_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_genex_out_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-ninja-stdout.txt
new file mode 100644
index 000000000..76b409df3
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_genex_out-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_genex_out_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_genex_out_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-result.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-result.txt
new file mode 100644
index 000000000..d197c913c
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-stderr.txt
new file mode 100644
index 000000000..86f7995e3
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-in-release-graph-ninja-stderr.txt
@@ -0,0 +1 @@
+ninja: error: 'echo_no_cross_byproduct_Debug\.txt', needed by 'CMakeFiles/echo_no_cross_byproduct-Debug', missing and no known rule to make it
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-ninja-stdout.txt
new file mode 100644
index 000000000..1c74b71ea
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_no_cross_byproduct_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_no_cross_byproduct_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-result.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-stderr.txt
new file mode 100644
index 000000000..e41cb178e
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-in-release-graph-ninja-stderr.txt
@@ -0,0 +1 @@
+ninja: error: 'echo_no_cross_byproduct_if_Debug\.txt', needed by 'CMakeFiles/echo_no_cross_byproduct_if-Debug', missing and no known rule to make it
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-ninja-stdout.txt
new file mode 100644
index 000000000..294d48b9f
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_byproduct_if-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_no_cross_byproduct_if_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_no_cross_byproduct_if_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-result.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-result.txt
new file mode 100644
index 000000000..d197c913c
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-stderr.txt
new file mode 100644
index 000000000..2ea22fad1
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-in-release-graph-ninja-stderr.txt
@@ -0,0 +1 @@
+ninja: error: 'echo_no_cross_output_Debug\.txt', needed by 'CMakeFiles/echo_no_cross_output-Debug', missing and no known rule to make it
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-ninja-stdout.txt
new file mode 100644
index 000000000..1f4cc414d
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_no_cross_output\.txt, echo_no_cross_output_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_no_cross_output_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-result.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-stderr.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-stderr.txt
new file mode 100644
index 000000000..fde66ead9
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-in-release-graph-ninja-stderr.txt
@@ -0,0 +1 @@
+ninja: error: 'echo_no_cross_output_if_Debug\.txt', needed by 'CMakeFiles/echo_no_cross_output_if-Debug', missing and no known rule to make it
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-ninja-stdout.txt
new file mode 100644
index 000000000..dc31f3beb
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_no_cross_output_if-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_no_cross_output_a\.txt, echo_no_cross_output_if_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_no_cross_output_if_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..01ebae33f
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] Generating echo_raw_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Debug' 'echo_raw_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-ninja-stdout.txt
new file mode 100644
index 000000000..242c9b0e5
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_raw-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] Generating echo_raw_Debug\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_raw_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..e77ef1aad
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] echo_target_depend
+echo_target_depend_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-ninja-stdout.txt
new file mode 100644
index 000000000..e77ef1aad
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] echo_target_depend
+echo_target_depend_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..8196fcb5a
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Release\.txt
+depend_Release\.txt
+\[2/2\] echo_target_depend_cmd
+echo_target_depend_cmd_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-ninja-stdout.txt
new file mode 100644
index 000000000..d45dcc2bd
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_cmd-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] echo_target_depend_cmd
+echo_target_depend_cmd_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..45f2e57b3
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,5 @@
+^(Recompacting log\.\.\.
+)?\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] echo_target_depend_out
+echo_target_depend_out_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-ninja-stdout.txt
new file mode 100644
index 000000000..d90a2f3cc
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_depend_out-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/2\] Generating depend_Debug\.txt
+depend_Debug\.txt
+\[2/2\] echo_target_depend_out
+echo_target_depend_out_Debug\.txt$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..73b403fa5
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] echo_target_genex
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release' 'echo_target_genex_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-ninja-stdout.txt
new file mode 100644
index 000000000..c374ce807
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] echo_target_genex
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_target_genex_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..ad6d6e052
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] echo_target_genex_out
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_target_genex_out_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-ninja-stdout.txt
new file mode 100644
index 000000000..e819fdf26
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_genex_out-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] echo_target_genex_out
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_target_genex_out_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..34df64595
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] echo_target_raw
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Debug' 'echo_target_raw_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-ninja-stdout.txt
new file mode 100644
index 000000000..3fa5488cb
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_target_raw-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] echo_target_raw
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'echo_target_raw_Debug\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..f504d98e9
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Release[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Release[\/]echo(\.exe)?
+\[3/3\] target_no_cross_byproduct
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release' 'target_no_cross_byproduct\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-ninja-stdout.txt
new file mode 100644
index 000000000..6e933b279
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-target_no_cross_byproduct-debug-ninja-stdout.txt
@@ -0,0 +1,4 @@
+^\[1/3\] Building C object CMakeFiles[\/]echo.dir[\/]Debug[\/]echo\.c\.(o|obj)
+\[2/3\] Linking C executable Debug[\/]echo(\.exe)?
+\[3/3\] target_no_cross_byproduct
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug' 'target_no_cross_byproduct\.txt'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake
new file mode 100644
index 000000000..5d6f42141
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake
@@ -0,0 +1,167 @@
+enable_language(C)
+
+add_executable(echo echo.c)
+
+add_custom_command(
+ OUTPUT echo_raw_$<CONFIG>.txt
+ COMMAND echo $<CONFIG> echo_raw_$<CONFIG>.txt
+ WORKING_DIRECTORY $<CONFIG>
+ )
+
+add_custom_command(
+ OUTPUT echo_genex_$<IF:$<CONFIG:Debug>,Debug,$<IF:$<CONFIG:Release>,Release,$<IF:$<CONFIG:MinSizeRel>,MinSizeRel,RelWithDebInfo>>>.txt
+ COMMAND $<TARGET_FILE:echo> $<COMMAND_CONFIG:$<CONFIG>> echo_genex_$<OUTPUT_CONFIG:$<CONFIG>>.txt
+ WORKING_DIRECTORY $<OUTPUT_CONFIG:$<CONFIG>>
+ )
+
+add_custom_command(
+ OUTPUT echo_genex_out_$<CONFIG>.txt
+ COMMAND $<OUTPUT_CONFIG:$<TARGET_FILE:echo>> $<CONFIG> echo_genex_out_$<CONFIG>.txt
+ WORKING_DIRECTORY $<COMMAND_CONFIG:$<CONFIG>>
+ )
+
+add_custom_command(
+ OUTPUT depend_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo depend_$<CONFIG>.txt
+ )
+
+add_custom_command(
+ OUTPUT echo_depend_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo echo_depend_$<CONFIG>.txt
+ DEPENDS depend_$<CONFIG>.txt
+ )
+
+add_custom_command(
+ OUTPUT echo_depend_out_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo echo_depend_out_$<CONFIG>.txt
+ DEPENDS $<OUTPUT_CONFIG:depend_$<CONFIG>.txt>
+ )
+
+add_custom_command(
+ OUTPUT echo_depend_cmd_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo echo_depend_cmd_$<CONFIG>.txt
+ DEPENDS $<COMMAND_CONFIG:depend_$<CONFIG>.txt>
+ )
+
+add_custom_command(
+ OUTPUT depend_echo_raw_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo depend_echo_raw_$<CONFIG>.txt
+ DEPENDS echo
+ )
+
+add_custom_command(
+ OUTPUT depend_echo_genex_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo depend_echo_genex_$<CONFIG>.txt
+ DEPENDS $<TARGET_FILE:echo>
+ )
+
+add_custom_command(
+ OUTPUT depend_echo_genex_out_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo depend_echo_genex_out_$<CONFIG>.txt
+ DEPENDS $<OUTPUT_CONFIG:$<TARGET_FILE:echo>>
+ )
+
+add_custom_command(
+ OUTPUT depend_echo_genex_cmd_$<CONFIG>.txt
+ COMMAND ${CMAKE_COMMAND} -E echo depend_echo_genex_cmd_$<CONFIG>.txt
+ DEPENDS $<COMMAND_CONFIG:$<TARGET_FILE:echo>>
+ )
+
+# An OUTPUT that is not per-config prevents cross-config generation.
+add_custom_command(
+ OUTPUT echo_no_cross_output.txt echo_no_cross_output_$<CONFIG>.txt
+ COMMAND echo $<CONFIG> echo_no_cross_output_$<CONFIG>.txt
+ WORKING_DIRECTORY $<CONFIG>
+ )
+add_custom_command(
+ OUTPUT echo_no_cross_output_$<IF:$<CONFIG:Debug>,a,b>.txt echo_no_cross_output_if_$<CONFIG>.txt
+ COMMAND echo $<CONFIG> echo_no_cross_output_if_$<CONFIG>.txt
+ WORKING_DIRECTORY $<CONFIG>
+ )
+
+# BYPRODUCTS that are not per-config prevent cross-config generation.
+add_custom_command(
+ OUTPUT echo_no_cross_byproduct_$<CONFIG>.txt
+ BYPRODUCTS echo_no_cross_byproduct.txt
+ COMMAND echo $<CONFIG> echo_no_cross_byproduct_$<CONFIG>.txt
+ WORKING_DIRECTORY $<CONFIG>
+ )
+add_custom_command(
+ OUTPUT echo_no_cross_byproduct_if_$<CONFIG>.txt
+ BYPRODUCTS echo_no_cross_byproduct_$<IF:$<CONFIG:Debug>,a,b>.txt
+ COMMAND echo $<CONFIG> echo_no_cross_byproduct_if_$<CONFIG>.txt
+ WORKING_DIRECTORY $<CONFIG>
+ )
+
+foreach(case
+ echo_raw
+ echo_genex
+ echo_genex_out
+ echo_depend
+ echo_depend_out
+ echo_depend_cmd
+ depend
+ depend_echo_raw
+ depend_echo_genex
+ depend_echo_genex_out
+ depend_echo_genex_cmd
+ echo_no_cross_output
+ echo_no_cross_output_if
+ echo_no_cross_byproduct
+ echo_no_cross_byproduct_if
+ )
+ set_property(SOURCE
+ ${CMAKE_CURRENT_BINARY_DIR}/${case}_Debug.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/${case}_Release.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/${case}_MinSizeRel.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/${case}_RelWithDebInfo.txt
+ PROPERTY SYMBOLIC 1)
+ add_custom_target(${case} DEPENDS ${case}_$<CONFIG>.txt)
+endforeach()
+
+add_custom_target(echo_target_raw
+ BYPRODUCTS echo_target_raw_$<CONFIG>.txt
+ COMMENT echo_target_raw
+ COMMAND echo $<CONFIG> echo_target_raw_$<CONFIG>.txt
+ WORKING_DIRECTORY $<CONFIG>
+ )
+
+add_custom_target(echo_target_genex
+ BYPRODUCTS echo_target_genex_$<CONFIG>.txt
+ COMMENT echo_target_genex
+ COMMAND $<TARGET_FILE:echo> $<COMMAND_CONFIG:$<CONFIG>> echo_target_genex_$<OUTPUT_CONFIG:$<CONFIG>>.txt
+ WORKING_DIRECTORY $<OUTPUT_CONFIG:$<CONFIG>>
+ )
+
+add_custom_target(echo_target_genex_out
+ BYPRODUCTS echo_target_genex_out_$<CONFIG>.txt
+ COMMENT echo_target_genex_out
+ COMMAND $<OUTPUT_CONFIG:$<TARGET_FILE:echo>> $<CONFIG> echo_target_genex_out_$<CONFIG>.txt
+ WORKING_DIRECTORY $<COMMAND_CONFIG:$<CONFIG>>
+ )
+
+add_custom_target(echo_target_depend
+ COMMAND ${CMAKE_COMMAND} -E echo echo_target_depend_$<CONFIG>.txt
+ DEPENDS depend_$<CONFIG>.txt
+ COMMENT echo_target_depend
+ )
+
+add_custom_target(echo_target_depend_out
+ COMMAND ${CMAKE_COMMAND} -E echo echo_target_depend_out_$<CONFIG>.txt
+ DEPENDS $<OUTPUT_CONFIG:depend_$<CONFIG>.txt>
+ COMMENT echo_target_depend_out
+ )
+
+add_custom_target(echo_target_depend_cmd
+ COMMAND ${CMAKE_COMMAND} -E echo echo_target_depend_cmd_$<CONFIG>.txt
+ DEPENDS $<COMMAND_CONFIG:depend_$<CONFIG>.txt>
+ COMMENT echo_target_depend_cmd
+ )
+
+# BYPRODUCTS that are not per-config block cross-configs.
+add_custom_target(target_no_cross_byproduct
+ BYPRODUCTS target_no_cross_byproduct.txt
+ COMMENT target_no_cross_byproduct
+ COMMAND echo $<CONFIG> target_no_cross_byproduct.txt
+ WORKING_DIRECTORY $<CONFIG>
+ )
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt
new file mode 100644
index 000000000..fad923ac0
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt
@@ -0,0 +1,2 @@
+Running post-build command with Debug
+Generating Debug\.txt
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt
new file mode 100644
index 000000000..485a52c23
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt
@@ -0,0 +1,3 @@
+Running post-build command with Release
+Generating out\.txt with Release
+Generating Release\.txt
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake b/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake
new file mode 100644
index 000000000..5fcff7463
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+add_executable(Exe main.c)
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Running post-build command with $<CONFIG>")
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Generating out.txt with $<CONFIG>" BYPRODUCTS out.txt)
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Generating $<CONFIG>.txt" BYPRODUCTS $<CONFIG>.txt)
diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake
index 3a1c7f5e4..578256a73 100644
--- a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake
@@ -16,12 +16,13 @@ if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0")
set(moc_writes_depfiles 1)
endif()
-set(autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation.cpp")
+set(autogen_files)
if(moc_writes_depfiles)
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/deps")
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/timestamp")
endif()
foreach(c IN LISTS CMAKE_CONFIGURATION_TYPES)
+ list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation_${c}.cpp")
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp")
if(moc_writes_depfiles)
list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp.d")
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index 6699a0990..21c2658c7 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -85,6 +85,9 @@ set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=RelWithDebInfo\\;Debug\\;
run_cmake_configure(Simple)
unset(RunCMake_TEST_OPTIONS)
include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
+run_ninja(Simple targets-default build.ninja -t targets)
+run_ninja(Simple targets-debug build-Debug.ninja -t targets)
+run_ninja(Simple targets-release build-Debug.ninja -t targets)
run_cmake_build(Simple debug-target Debug simpleexe)
run_ninja(Simple debug-target build-Debug.ninja simplestatic)
get_filename_component(simpleshared_Release "${TARGET_FILE_simpleshared_Release}" NAME)
@@ -187,6 +190,12 @@ run_ninja(SimpleCrossConfigs clean-all-in-release-graph build-Release.ninja clea
run_cmake_build(SimpleCrossConfigs all-all-in-release-graph Release all:all)
run_cmake_build(SimpleCrossConfigs all-relwithdebinfo-in-release-graph Release all:RelWithDebInfo)
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostBuild-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
+run_cmake_configure(PostBuild)
+run_cmake_build(PostBuild release Release Exe)
+run_cmake_build(PostBuild debug-in-release-graph Release Exe:Debug)
+
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Framework-build)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
run_cmake_configure(Framework)
@@ -215,7 +224,7 @@ run_ninja(CustomCommandGenerator debug-clean build-Debug.ninja clean)
run_cmake_build(CustomCommandGenerator release-clean Release clean)
run_cmake_build(CustomCommandGenerator debug-in-release-graph Release generated:Debug)
run_cmake_command(CustomCommandGenerator-debug-in-release-graph-generated "${TARGET_FILE_generated_Debug}")
-run_ninja(CustomCommandGenerator debug-in-release-graph-clean build-Debug.ninja clean:Debug)
+run_ninja(CustomCommandGenerator debug-clean-again build-Debug.ninja clean:Debug)
run_ninja(CustomCommandGenerator release-in-debug-graph build-Debug.ninja generated:Release)
run_cmake_command(CustomCommandGenerator-release-in-debug-graph-generated "${TARGET_FILE_generated_Release}")
unset(RunCMake_TEST_NO_CLEAN)
@@ -242,6 +251,102 @@ run_ninja(CustomCommandsAndTargets release-leaf-exe build-Release.ninja LeafExe)
run_cmake_build(CustomCommandsAndTargets release-clean Release clean:all)
run_ninja(CustomCommandsAndTargets release-leaf-byproduct build-Release.ninja main.c)
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandOutputGenex-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release\\;MinSizeRel\\;RelWithDebInfo;-DCMAKE_CROSS_CONFIGS=all")
+run_cmake_configure(CustomCommandOutputGenex)
+set(RunCMake_TEST_NO_CLEAN 1)
+unset(RunCMake_TEST_OPTIONS)
+# echo_raw
+run_ninja(CustomCommandOutputGenex echo_raw-debug build-Debug.ninja echo_raw:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_raw-debug-in-release-graph build-Release.ninja echo_raw:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_genex
+run_ninja(CustomCommandOutputGenex echo_genex-debug build-Debug.ninja echo_genex:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_genex-debug-in-release-graph build-Release.ninja echo_genex:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_genex_out
+run_ninja(CustomCommandOutputGenex echo_genex_out-debug build-Debug.ninja echo_genex_out:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_genex_out-debug-in-release-graph build-Release.ninja echo_genex_out:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_depend*
+run_ninja(CustomCommandOutputGenex echo_depend-debug build-Debug.ninja echo_depend:Debug)
+run_ninja(CustomCommandOutputGenex echo_depend_out-debug build-Debug.ninja echo_depend_out_Debug.txt)
+run_ninja(CustomCommandOutputGenex echo_depend_cmd-debug build-Debug.ninja echo_depend_cmd_Debug.txt)
+run_ninja(CustomCommandOutputGenex echo_depend-debug-in-release-graph build-Release.ninja echo_depend:Debug)
+run_ninja(CustomCommandOutputGenex echo_depend_out-debug-in-release-graph build-Release.ninja echo_depend_out_Debug.txt)
+run_ninja(CustomCommandOutputGenex echo_depend_cmd-debug-in-release-graph build-Release.ninja echo_depend_cmd_Debug.txt)
+# depend_echo_raw
+run_ninja(CustomCommandOutputGenex depend_echo_raw-debug build-Debug.ninja depend_echo_raw:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex depend_echo_raw-debug-in-release-graph build-Release.ninja depend_echo_raw:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# depend_echo_genex
+run_ninja(CustomCommandOutputGenex depend_echo_genex-debug build-Debug.ninja depend_echo_genex:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex depend_echo_genex-debug-in-release-graph build-Release.ninja depend_echo_genex:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# depend_echo_genex_out
+run_ninja(CustomCommandOutputGenex depend_echo_genex_out-debug build-Debug.ninja depend_echo_genex_out:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex depend_echo_genex_out-debug-in-release-graph build-Release.ninja depend_echo_genex_out:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# depend_echo_genex_cmd
+run_ninja(CustomCommandOutputGenex depend_echo_genex_cmd-debug build-Debug.ninja depend_echo_genex_cmd:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex depend_echo_genex_cmd-debug-in-release-graph build-Release.ninja depend_echo_genex_cmd:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# no_cross_output
+run_ninja(CustomCommandOutputGenex echo_no_cross_output-debug build-Debug.ninja echo_no_cross_output:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_no_cross_output-debug-in-release-graph build-Release.ninja echo_no_cross_output:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# no_cross_output_if
+run_ninja(CustomCommandOutputGenex echo_no_cross_output_if-debug build-Debug.ninja echo_no_cross_output_if:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_no_cross_output_if-debug-in-release-graph build-Release.ninja echo_no_cross_output_if:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# no_cross_byproduct
+run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct-debug build-Debug.ninja echo_no_cross_byproduct:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct-debug-in-release-graph build-Release.ninja echo_no_cross_byproduct:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# no_cross_byproduct_if
+run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct_if-debug build-Debug.ninja echo_no_cross_byproduct_if:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_no_cross_byproduct_if-debug-in-release-graph build-Release.ninja echo_no_cross_byproduct_if:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_target_raw
+run_ninja(CustomCommandOutputGenex echo_target_raw-debug build-Debug.ninja echo_target_raw:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_target_raw-debug-in-release-graph build-Release.ninja echo_target_raw:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_target_genex
+run_ninja(CustomCommandOutputGenex echo_target_genex-debug build-Debug.ninja echo_target_genex:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_target_genex-debug-in-release-graph build-Release.ninja echo_target_genex:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_target_genex_out
+run_ninja(CustomCommandOutputGenex echo_target_genex_out-debug build-Debug.ninja echo_target_genex_out:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_target_genex_out-debug-in-release-graph build-Release.ninja echo_target_genex_out:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_target_depend*
+run_ninja(CustomCommandOutputGenex echo_target_depend-debug build-Debug.ninja echo_target_depend:Debug)
+run_ninja(CustomCommandOutputGenex echo_target_depend_out-debug build-Debug.ninja echo_target_depend_out:Debug)
+run_ninja(CustomCommandOutputGenex echo_target_depend_cmd-debug build-Debug.ninja CMakeFiles/echo_target_depend_cmd-Debug) # undocumented
+run_ninja(CustomCommandOutputGenex echo_target_depend-debug-in-release-graph build-Release.ninja echo_target_depend:Debug)
+run_ninja(CustomCommandOutputGenex echo_target_depend_out-debug-in-release-graph build-Release.ninja echo_target_depend_out:Debug)
+run_ninja(CustomCommandOutputGenex echo_target_depend_cmd-debug-in-release-graph build-Release.ninja CMakeFiles/echo_target_depend_cmd-Debug) # undocumented
+# target_no_cross_*
+run_ninja(CustomCommandOutputGenex target_no_cross_byproduct-debug build-Debug.ninja target_no_cross_byproduct:Debug)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex target_no_cross_byproduct-debug-in-release-graph build-Release.ninja target_no_cross_byproduct:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+unset(RunCMake_TEST_NO_CLEAN)
+
unset(RunCMake_TEST_BINARY_DIR)
run_cmake(CustomCommandDepfile)
diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-targets-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/Simple-targets-debug-ninja-stdout.txt
new file mode 100644
index 000000000..f72516fc8
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/Simple-targets-debug-ninja-stdout.txt
@@ -0,0 +1,3 @@
+(rebuild_cache: phony.*
+edit_cache: phony|edit_cache: phony.*
+rebuild_cache: phony)
diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-targets-default-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/Simple-targets-default-ninja-stdout.txt
new file mode 100644
index 000000000..f72516fc8
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/Simple-targets-default-ninja-stdout.txt
@@ -0,0 +1,3 @@
+(rebuild_cache: phony.*
+edit_cache: phony|edit_cache: phony.*
+rebuild_cache: phony)
diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-targets-release-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/Simple-targets-release-ninja-stdout.txt
new file mode 100644
index 000000000..f72516fc8
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/Simple-targets-release-ninja-stdout.txt
@@ -0,0 +1,3 @@
+(rebuild_cache: phony.*
+edit_cache: phony|edit_cache: phony.*
+rebuild_cache: phony)
diff --git a/Tests/RunCMake/NinjaMultiConfig/echo.c b/Tests/RunCMake/NinjaMultiConfig/echo.c
new file mode 100644
index 000000000..48a187fcf
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/echo.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#if defined(_WIN32)
+# include <direct.h>
+# define getcwd _getcwd
+#else
+# include <unistd.h>
+#endif
+
+int main(int argc, char** argv)
+{
+ int i;
+ char cwd[1024];
+ if (getcwd(cwd, sizeof(cwd)) != NULL) {
+ printf("'%s'$", cwd);
+ }
+ for (i = 0; i < argc; ++i) {
+ printf(" '%s'", argv[i]);
+ }
+ printf("\n");
+ return 0;
+}
diff --git a/Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake b/Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake
new file mode 100644
index 000000000..af1df7897
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake
@@ -0,0 +1,15 @@
+set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/ImportMultiArch.xcodeproj/project.pbxproj")
+if(NOT EXISTS "${xcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.")
+ return()
+endif()
+
+file(READ ${xcProjectFile} pbxFileContents)
+foreach(config IN ITEMS Debug Release RelWithDebInfo MinSizeRel)
+ set(regex "--findconfig-${config}[^
+]*\\$\\(CURRENT_ARCH\\)")
+ if(NOT pbxFileContents MATCHES "${regex}")
+ set(RunCMake_TEST_FAILED "$(CURRENT_ARCH) not preserved for config ${config}")
+ return()
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake b/Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake
new file mode 100644
index 000000000..64029ee41
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake
@@ -0,0 +1,13 @@
+
+add_library(A OBJECT IMPORTED)
+
+# We don't actually build this example so just configure dummy
+# object files to test. They do not have to exist.
+set_target_properties(A PROPERTIES
+ IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/$(CURRENT_ARCH)/does_not_exist.o"
+)
+
+add_library(B SHARED $<TARGET_OBJECTS:A> b.c)
+
+# We use this to find the relevant lines of the project.pbx file
+target_link_options(B PRIVATE --findconfig-$<CONFIG>)
diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt
deleted file mode 100644
index 0fadac208..000000000
--- a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at ImportNotSupported.cmake:[0-9]+ \(add_library\):
- The OBJECT library type may not be used for IMPORTED libraries under Xcode
- with multiple architectures.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake b/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake
deleted file mode 100644
index 806b44a25..000000000
--- a/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake
+++ /dev/null
@@ -1 +0,0 @@
-add_library(A OBJECT IMPORTED)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
index 0a76932ec..3d60556bf 100644
--- a/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
@@ -12,4 +12,10 @@ add_executable(LinkObjLHSShared LinkObjLHSShared.c)
target_link_libraries(LinkObjLHSShared AnObjLib)
# Verify that our dependency on OtherLib generated its versioning symlinks.
+if(CMAKE_GENERATOR STREQUAL "Xcode" AND
+ "${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64")
+ # Xcode runs POST_BUILD before signing, so let the linker use ad-hoc signing.
+ # See CMake Issue 21845.
+ target_link_options(LinkObjLHSShared PRIVATE LINKER:-adhoc_codesign)
+endif()
add_custom_command(TARGET LinkObjLHSShared POST_BUILD COMMAND LinkObjLHSShared)
diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
index 5ec401873..8515ba540 100644
--- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -6,7 +6,7 @@ run_cmake(BadSourceExpression3)
run_cmake(BadObjSource1)
run_cmake(BadObjSource2)
if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
- run_cmake(ImportNotSupported)
+ run_cmake(ImportMultiArch)
run_cmake(InstallNotSupported)
else()
run_cmake(Import)
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
index bb6beb22b..c46d044bc 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake
@@ -50,6 +50,7 @@ else()
endif()
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
+include(${CMAKE_ROOT}/Modules/CMakeParseLibraryArchitecture.cmake)
#
# load_compiler_info: read infile, parsing out cmake compiler info
@@ -80,6 +81,7 @@ function(load_compiler_info infile lang_var outcmvars_var outstr_var)
message("load_compiler_info: ${infile} no LANG info; default to C")
set(lang C)
endif()
+
set(${lang_var} "${lang}" PARENT_SCOPE)
set(${outcmvars_var} "${outcmvars}" PARENT_SCOPE)
set(${outstr_var} "${outstr}" PARENT_SCOPE)
@@ -94,6 +96,21 @@ function(unload_compiler_info cmvars)
endforeach()
endfunction()
+
+#
+# load_platform_info: establish CMAKE_LIBRARY_ARCHITECTURE_REGEX
+# based on the target platform.
+#
+function(load_platform_info target)
+ if(target MATCHES "linux-")
+ set(CMAKE_LIBRARY_ARCHITECTURE_REGEX "[a-z0-9_]+(-[a-z0-9_]+)?-linux-gnu[a-z0-9_]*" PARENT_SCOPE)
+ set(CMAKE_LIBRARY_ARCHITECTURE_REGEX_VERSIONED "gcc/[a-z0-9_]+(-[a-z0-9_]+)?-linux(-gnu)?/[0-9]+(\\.[0-9]+\\.[0-9]+)*" PARENT_SCOPE)
+ else()
+ unset(CMAKE_LIBRARY_ARCHITECTURE_REGEX PARENT_SCOPE)
+ unset(CMAKE_LIBRARY_ARCHITECTURE_REGEX_VERSIONED PARENT_SCOPE)
+ endif()
+endfunction()
+
#
# main test loop
#
@@ -112,10 +129,12 @@ foreach(t ${targets})
endif()
load_compiler_info(${infile} lang cmvars input)
+ load_platform_info(${t})
# Need to handle files with empty entries for both libs or dirs
set(implicit_lib_output "")
set(idirs_output "")
+ set(library_arch_output "")
file(STRINGS ${outfile} outputs)
foreach(line IN LISTS outputs)
if(line MATCHES "libs=")
@@ -124,13 +143,19 @@ foreach(t ${targets})
if(line MATCHES "dirs=")
string(REPLACE "dirs=" "" idirs_output "${line}")
endif()
+ if(line MATCHES "library_arch=")
+ string(REPLACE "library_arch=" "" library_arch_output "${line}")
+ endif()
endforeach()
cmake_parse_implicit_link_info("${input}" implicit_libs idirs implicit_fwks log
"${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}")
+ set(library_arch)
+ cmake_parse_library_architecture("${idirs}" library_arch)
+
# File format
- # file(WRITE ${outfile} "libs=${implicit_libs}\ndirs=${idirs}\n")
+ # file(WRITE ${outfile} "libs=${implicit_libs}\ndirs=${idirs}\nlibrary_arch=${library_arch}")
if(t MATCHES "-empty$") # empty isn't supposed to parse
if("${state}" STREQUAL "done")
@@ -140,6 +165,8 @@ foreach(t ${targets})
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 AND NOT "${library_arch}" STREQUAL "${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/linux-C-GNU-7.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-7.3.0.output
index 63b51a1ec..0cf3a4969 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-7.3.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-GNU-7.3.0.output
@@ -1,2 +1,3 @@
libs=gcc;gcc_s;c;gcc;gcc_s
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-C-Intel-18.0.0.20170811.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-Intel-18.0.0.20170811.output
index b61e097d2..55852c0ef 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,2 +1,3 @@
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=x86_64-redhat-linux
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-PGI-18.10.1.output
index 7b2091502..793110272 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-PGI-18.10.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-PGI-18.10.1.output
@@ -1,2 +1,3 @@
libs=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-C-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-12.1.0.output
index de407f2f0..de8c8ebf7 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-12.1.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-12.1.0.output
@@ -1,2 +1,3 @@
libs=xlopt;xl;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=ppc64-redhat-linux
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-16.1.0.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-16.1.0.0.output
index de515e790..cd672d5d1 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-16.1.0.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-C-XL-16.1.0.0.output
@@ -1,2 +1,3 @@
libs=xlopt;xl;dl;gcc_s;pthread;gcc;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=ppc64le-redhat-linux
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 a657b8508..813457aef 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,2 +1,3 @@
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 58ae64d60..8824772c9 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,2 +1,3 @@
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=ppc64le-redhat-linux
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 7c99bf669..275fe40c9 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,2 +1,3 @@
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-7.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-CXX-GNU-7.3.0.output
index 4fc79373d..4957f5cd3 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,2 +1,3 @@
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 5d857892c..6a2a10544 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,2 +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
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=x86_64-redhat-linux
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 db0b29c90..cd15054cb 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,2 +1,3 @@
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 4466415b3..9fbc84403 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,2 +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
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=ppc64-redhat-linux
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 8124911fa..4e9ab0a37 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,2 +1,3 @@
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=ppc64le-redhat-linux
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-7.3.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-7.3.0.output
index f985a0330..09b720e5f 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-7.3.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-GNU-7.3.0.output
@@ -1,2 +1,3 @@
libs=gfortran;m;gcc_s;gcc;quadmath;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-Fortran-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-PGI-18.10.1.output
index d40f81eb9..f3cc5518e 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-PGI-18.10.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-PGI-18.10.1.output
@@ -1,2 +1,3 @@
libs=pgf90rtl;pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;pgmp;numa;pthread;pgmath;nspgc;pgc;rt;pthread;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-Fortran-XL-14.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-XL-14.1.0.output
index 3c5d23bfc..68be4c56d 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-XL-14.1.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux-Fortran-XL-14.1.0.output
@@ -1,2 +1,3 @@
libs=xlf90;xlopt;xlomp_ser;xl;xlfmath;gcc_s;dl;rt;pthread;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/xlf/bg/14.1/lib64;/usr/lib/gcc/ppc64-redhat-linux/4.4.7;/usr/lib64;/lib64;/usr/lib
+library_arch=ppc64-redhat-linux
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-PGI-18.10.1.output
index 7b2091502..e44c84db5 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-PGI-18.10.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-PGI-18.10.1.output
@@ -1,2 +1,3 @@
libs=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-gnu2
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-XL-12.1.0.output
index de407f2f0..de8c8ebf7 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-XL-12.1.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-C-XL-12.1.0.output
@@ -1,2 +1,3 @@
libs=xlopt;xl;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=ppc64-redhat-linux
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 db0b29c90..cd15054cb 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,2 +1,3 @@
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_nostdinc-CXX-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-CXX-XL-12.1.0.output
index 4466415b3..9fbc84403 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,2 +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
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=ppc64-redhat-linux
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-Fortran-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-Fortran-PGI-18.10.1.output
index d40f81eb9..f3cc5518e 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-Fortran-PGI-18.10.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc-Fortran-PGI-18.10.1.output
@@ -1,2 +1,3 @@
libs=pgf90rtl;pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;pgmp;numa;pthread;pgmath;nspgc;pgc;rt;pthread;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_nostdinc_i-C-XL-12.1.0.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc_i-C-XL-12.1.0.output
index de407f2f0..de8c8ebf7 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc_i-C-XL-12.1.0.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_nostdinc_i-C-XL-12.1.0.output
@@ -1,2 +1,3 @@
libs=xlopt;xl;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=ppc64-redhat-linux
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_pgf77-Fortran-PGI-18.10.1.output b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_pgf77-Fortran-PGI-18.10.1.output
index 7b523ea9d..8f68358f8 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_pgf77-Fortran-PGI-18.10.1.output
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/results/linux_pgf77-Fortran-PGI-18.10.1.output
@@ -1,2 +1,3 @@
libs=pgftnrtl;pgmp;numa;pthread;pgmath;nspgc;pgc;rt;pthread;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/Policy/CMakeLists.txt b/Tests/RunCMake/Policy/CMakeLists.txt
new file mode 100644
index 000000000..667561ea7
--- /dev/null
+++ b/Tests/RunCMake/Policy/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
diff --git a/Tests/RunCMake/Policy/InvalidMaxVersion-result.txt b/Tests/RunCMake/Policy/InvalidMaxVersion-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidMaxVersion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Policy/InvalidMaxVersion-stderr.txt b/Tests/RunCMake/Policy/InvalidMaxVersion-stderr.txt
new file mode 100644
index 000000000..25d22f560
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidMaxVersion-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at InvalidMaxVersion.cmake:[0-9]+ \(cmake_policy\):
+ Invalid policy max version value "[A-Za-z0-9]+.[A-Za-z0-9]*.[A-Za-z0-9]*.[A-Za-z0-9]*"\. A numeric
+ major.minor\[\.patch\[\.tweak\]\] must be given\.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/InvalidMaxVersion.cmake b/Tests/RunCMake/Policy/InvalidMaxVersion.cmake
new file mode 100644
index 000000000..be3270f45
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidMaxVersion.cmake
@@ -0,0 +1,5 @@
+if(NOT version)
+ message(SEND_ERROR "Vesrion string is empty: ${version}")
+endif()
+
+cmake_policy(VERSION 3.1...${version})
diff --git a/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-result.txt b/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-result.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-result.txt
diff --git a/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-stderr.txt b/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-stderr.txt
new file mode 100644
index 000000000..a48feb31a
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at InvalidRangeMaxVersionNotGiven.cmake:[0-9]+ \(cmake_policy\):
+ cmake_policy VERSION "3.15..." does not have a version on both sides of
+ "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven.cmake b/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven.cmake
new file mode 100644
index 000000000..e55803c61
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidRangeMaxVersionNotGiven.cmake
@@ -0,0 +1 @@
+cmake_policy(VERSION 3.15...)
diff --git a/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-result.txt b/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-stderr.txt b/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-stderr.txt
new file mode 100644
index 000000000..84e9b88ef
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at InvalidRangeMinVersionNotGiven.cmake:[0-9]+ \(cmake_policy\):
+ cmake_policy VERSION "...3.15" does not have a version on both sides of
+ "...".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven.cmake b/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven.cmake
new file mode 100644
index 000000000..60e7e256b
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidRangeMinVersionNotGiven.cmake
@@ -0,0 +1 @@
+cmake_policy(VERSION ...3.15)
diff --git a/Tests/RunCMake/Policy/InvalidVersion-result.txt b/Tests/RunCMake/Policy/InvalidVersion-result.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidVersion-result.txt
diff --git a/Tests/RunCMake/Policy/InvalidVersion-stderr.txt b/Tests/RunCMake/Policy/InvalidVersion-stderr.txt
new file mode 100644
index 000000000..783f4edb8
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidVersion-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at InvalidVersion.cmake:[0-9]+ \(cmake_policy\):
+ Invalid policy version value "[A-Za-z0-9]+.[A-Za-z0-9]*.[A-Za-z0-9]*.[A-Za-z0-9]*"\. A numeric
+ major\.minor\[\.patch\[\.tweak\]\] must be given\.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/InvalidVersion.cmake b/Tests/RunCMake/Policy/InvalidVersion.cmake
new file mode 100644
index 000000000..b135ba649
--- /dev/null
+++ b/Tests/RunCMake/Policy/InvalidVersion.cmake
@@ -0,0 +1,5 @@
+if(NOT version)
+ message(SEND_ERROR "Vesrion string is empty: ${version}")
+endif()
+
+cmake_policy(VERSION ${version})
diff --git a/Tests/RunCMake/Policy/MinVersionLargerThanMax-result.txt b/Tests/RunCMake/Policy/MinVersionLargerThanMax-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Policy/MinVersionLargerThanMax-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt b/Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt
new file mode 100644
index 000000000..0b0308f9d
--- /dev/null
+++ b/Tests/RunCMake/Policy/MinVersionLargerThanMax-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at MinVersionLargerThanMax.cmake:[0-9]+ \(cmake_policy\):
+ Policy VERSION range "3.12...3.8" specifies a larger minimum than maximum.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/MinVersionLargerThanMax.cmake b/Tests/RunCMake/Policy/MinVersionLargerThanMax.cmake
new file mode 100644
index 000000000..67d5f85a5
--- /dev/null
+++ b/Tests/RunCMake/Policy/MinVersionLargerThanMax.cmake
@@ -0,0 +1 @@
+cmake_policy(VERSION 3.12...3.8)
diff --git a/Tests/RunCMake/Policy/RunCMakeTest.cmake b/Tests/RunCMake/Policy/RunCMakeTest.cmake
new file mode 100644
index 000000000..74c7d6349
--- /dev/null
+++ b/Tests/RunCMake/Policy/RunCMakeTest.cmake
@@ -0,0 +1,19 @@
+include(RunCMake)
+
+run_cmake(VersionNotGiven)
+run_cmake(TooManyVersionsGiven)
+run_cmake(InvalidRangeMinVersionNotGiven)
+run_cmake(InvalidRangeMaxVersionNotGiven)
+
+set(RunCMake_TEST_OPTIONS "-Dversion=three")
+run_cmake(InvalidVersion)
+run_cmake(InvalidMaxVersion)
+unset(RunCMake_TEST_OPTIONS)
+set(RunCMake_TEST_OPTIONS "-Dversion=3.one")
+run_cmake(InvalidVersion)
+run_cmake(InvalidMaxVersion)
+unset(RunCMake_TEST_OPTIONS)
+
+run_cmake(VersionLowerThan2_4)
+run_cmake(MinVersionLargerThanMax)
+run_cmake(VeryHighVersion)
diff --git a/Tests/RunCMake/Policy/TooManyVersionsGiven-result.txt b/Tests/RunCMake/Policy/TooManyVersionsGiven-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Policy/TooManyVersionsGiven-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Policy/TooManyVersionsGiven-stderr.txt b/Tests/RunCMake/Policy/TooManyVersionsGiven-stderr.txt
new file mode 100644
index 000000000..7a4f8c796
--- /dev/null
+++ b/Tests/RunCMake/Policy/TooManyVersionsGiven-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at TooManyVersionsGiven.cmake:[0-9]+ \(cmake_policy\):
+ cmake_policy VERSION given too many arguments
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/TooManyVersionsGiven.cmake b/Tests/RunCMake/Policy/TooManyVersionsGiven.cmake
new file mode 100644
index 000000000..6c99af253
--- /dev/null
+++ b/Tests/RunCMake/Policy/TooManyVersionsGiven.cmake
@@ -0,0 +1 @@
+cmake_policy(VERSION 1 2 3)
diff --git a/Tests/RunCMake/Policy/VersionLowerThan2_4-result.txt b/Tests/RunCMake/Policy/VersionLowerThan2_4-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Policy/VersionLowerThan2_4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Policy/VersionLowerThan2_4-stderr.txt b/Tests/RunCMake/Policy/VersionLowerThan2_4-stderr.txt
new file mode 100644
index 000000000..3f19192d0
--- /dev/null
+++ b/Tests/RunCMake/Policy/VersionLowerThan2_4-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at VersionLowerThan2_4.cmake:[0-9]+ \(cmake_policy\):
+ Compatibility with CMake < 2.4 is not supported by CMake >= 3.0. For
+ compatibility with older versions please use any CMake 2.8.x release or
+ lower.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/VersionLowerThan2_4.cmake b/Tests/RunCMake/Policy/VersionLowerThan2_4.cmake
new file mode 100644
index 000000000..f1a4fd91d
--- /dev/null
+++ b/Tests/RunCMake/Policy/VersionLowerThan2_4.cmake
@@ -0,0 +1 @@
+cmake_policy(VERSION 2.2)
diff --git a/Tests/RunCMake/Policy/VersionNotGiven-result.txt b/Tests/RunCMake/Policy/VersionNotGiven-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Policy/VersionNotGiven-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Policy/VersionNotGiven-stderr.txt b/Tests/RunCMake/Policy/VersionNotGiven-stderr.txt
new file mode 100644
index 000000000..8eeb1778c
--- /dev/null
+++ b/Tests/RunCMake/Policy/VersionNotGiven-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VersionNotGiven.cmake:[0-9]+ \(cmake_policy\):
+ cmake_policy VERSION not given an argument
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/VersionNotGiven.cmake b/Tests/RunCMake/Policy/VersionNotGiven.cmake
new file mode 100644
index 000000000..53b3d7f5c
--- /dev/null
+++ b/Tests/RunCMake/Policy/VersionNotGiven.cmake
@@ -0,0 +1 @@
+cmake_policy(VERSION)
diff --git a/Tests/RunCMake/Policy/VeryHighVersion-result.txt b/Tests/RunCMake/Policy/VeryHighVersion-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Policy/VeryHighVersion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Policy/VeryHighVersion-stderr.txt b/Tests/RunCMake/Policy/VeryHighVersion-stderr.txt
new file mode 100644
index 000000000..7cca91b7a
--- /dev/null
+++ b/Tests/RunCMake/Policy/VeryHighVersion-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at VeryHighVersion.cmake:[0-9]+ \(cmake_policy\):
+ An attempt was made to set the policy version of CMake to "99.1" which is
+ greater than this version of CMake. This is not allowed because the
+ greater version may have new policies not known to this CMake. You may
+ need a newer CMake version to build this project.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/Policy/VeryHighVersion.cmake b/Tests/RunCMake/Policy/VeryHighVersion.cmake
new file mode 100644
index 000000000..3d4af8c53
--- /dev/null
+++ b/Tests/RunCMake/Policy/VeryHighVersion.cmake
@@ -0,0 +1 @@
+cmake_policy(VERSION 99.1)
diff --git a/Tests/RunCMake/PrecompileHeaders/CXXnotC.cmake b/Tests/RunCMake/PrecompileHeaders/CXXnotC.cmake
new file mode 100644
index 000000000..9ec1b36c0
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/CXXnotC.cmake
@@ -0,0 +1,15 @@
+enable_language(C)
+enable_language(CXX)
+
+add_executable(main
+ no_pch.c
+ use_pch.cxx
+)
+
+target_include_directories(main PUBLIC include)
+target_precompile_headers(main PRIVATE
+ "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/include/cxx_pch.h>"
+ )
+
+enable_testing()
+add_test(NAME main COMMAND main)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake
new file mode 100644
index 000000000..ba504a3ef
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromObjLib.cmake
@@ -0,0 +1,131 @@
+cmake_minimum_required(VERSION 3.18)
+
+project(PchReuseFromObjLib)
+
+set(CMAKE_PCH_WARN_INVALID OFF)
+
+if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
+ add_definitions(-DHAVE_PCH_SUPPORT)
+endif()
+
+######################################################################
+
+file(WRITE ${CMAKE_BINARY_DIR}/CONFIG/config.hxx "/*empty*/\n")
+
+file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[
+void nothing()
+{
+}
+]=])
+
+file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[
+#include <string.h>
+
+namespace std {
+ struct string
+ {
+ char storage[20];
+
+ string(const char* s) {
+ strcpy(storage, s);
+ }
+
+ const char* c_str() const {
+ return storage;
+ }
+ };
+}
+]=])
+
+add_library(pch-generator OBJECT ${CMAKE_BINARY_DIR}/pch.cxx)
+set_property(TARGET pch-generator PROPERTY POSITION_INDEPENDENT_CODE ON)
+target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx)
+
+target_include_directories(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/CONFIG)
+
+######################################################################
+
+file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[
+#include "message.hxx"
+
+#ifndef HAVE_PCH_SUPPORT
+ #include "string.hxx"
+#endif
+
+const char* message()
+{
+ static std::string greeting("hi there");
+ return greeting.c_str();
+}
+]=])
+
+file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[
+#include "config.hxx"
+#ifdef WIN32_BUILD_SHARED
+ #ifdef BUILD_LIBRARY
+ #define MESSAGE_EXPORT __declspec(dllexport)
+ #else
+ #define MESSAGE_EXPORT __declspec(dllimport)
+ #endif
+#else
+ #define MESSAGE_EXPORT
+#endif
+
+MESSAGE_EXPORT const char* message();
+]=])
+
+######################################################################
+
+file(WRITE ${CMAKE_BINARY_DIR}/main.cxx [=[
+#include "message.hxx"
+#include <string.h>
+
+int main()
+{
+ return strcmp(message(), "hi there");
+}
+]=])
+
+######################################################################
+
+enable_testing()
+
+function(add_library_and_executable type)
+ add_library(message_${type} ${type} ${CMAKE_BINARY_DIR}/message.cxx)
+ target_precompile_headers(message_${type} REUSE_FROM pch-generator)
+
+ set_property(TARGET message_${type} PROPERTY POSITION_INDEPENDENT_CODE ON)
+ set_property(TARGET message_${type} PROPERTY DEFINE_SYMBOL "")
+
+ if (WIN32 AND type STREQUAL "SHARED")
+ file(WRITE ${CMAKE_BINARY_DIR}/SHARED/config.hxx [=[
+ #define BUILD_LIBRARY
+ #define WIN32_BUILD_SHARED
+ ]=])
+ target_include_directories(message_${type} PRIVATE ${CMAKE_BINARY_DIR}/SHARED)
+
+ # Workaround for VS2008, the compiler fails with
+ # c1xx : fatal error C1083: Cannot open source file: '_WINDLL': No such file or directory
+ file(WRITE ${CMAKE_BINARY_DIR}/_WINDLL "/*empty*/\n")
+ else()
+ target_include_directories(message_${type} PRIVATE ${CMAKE_BINARY_DIR}/CONFIG)
+ endif()
+
+ add_executable(main_${type} ${CMAKE_BINARY_DIR}/main.cxx)
+ target_include_directories(main_${type} PRIVATE ${CMAKE_BINARY_DIR})
+
+ if (WIN32 AND type STREQUAL "SHARED")
+ file(WRITE ${CMAKE_BINARY_DIR}/main_SHARED/config.hxx "#define WIN32_BUILD_SHARED\n")
+ target_include_directories(main_${type} PRIVATE ${CMAKE_BINARY_DIR}/main_SHARED)
+ else()
+ target_include_directories(main_${type} PRIVATE ${CMAKE_BINARY_DIR}/CONFIG)
+ endif()
+
+ target_link_libraries(main_${type} PRIVATE message_${type})
+
+ add_test(NAME main_${type} COMMAND main_${type})
+endfunction()
+
+foreach(type OBJECT STATIC SHARED)
+ add_library_and_executable(${type})
+endforeach()
diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
index 74670bafc..8cc59d224 100644
--- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
@@ -14,6 +14,7 @@ run_cmake(PchDebugGenex)
run_test(PchInterface)
run_cmake(PchPrologueEpilogue)
run_test(SkipPrecompileHeaders)
+run_test(CXXnotC)
run_test(PchReuseFrom)
run_test(PchReuseFromPrefixed)
run_test(PchReuseFromSubdir)
@@ -26,3 +27,4 @@ if(RunCMake_GENERATOR MATCHES "Make|Ninja")
run_cmake(PchInstantiateTemplates)
endif()
endif()
+run_test(PchReuseFromObjLib)
diff --git a/Tests/RunCMake/PrecompileHeaders/include/cxx_pch.h b/Tests/RunCMake/PrecompileHeaders/include/cxx_pch.h
new file mode 100644
index 000000000..3282cec60
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/include/cxx_pch.h
@@ -0,0 +1 @@
+#define CXX_PCH
diff --git a/Tests/RunCMake/PrecompileHeaders/no_pch.c b/Tests/RunCMake/PrecompileHeaders/no_pch.c
new file mode 100644
index 000000000..8d225800c
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/no_pch.c
@@ -0,0 +1,7 @@
+#ifdef CXX_PCH
+# error "CXX PCH included in C source."
+#endif
+int no_pch(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/PrecompileHeaders/use_pch.cxx b/Tests/RunCMake/PrecompileHeaders/use_pch.cxx
new file mode 100644
index 000000000..caf115bee
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/use_pch.cxx
@@ -0,0 +1,9 @@
+#include "cxx_pch.h"
+#ifndef CXX_PCH
+# error "CXX PCH not included in CXX source."
+#endif
+extern "C" int no_pch(void);
+int main()
+{
+ return no_pch();
+}
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index 1a690594d..a26f632e0 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -214,11 +214,6 @@ function(run_cmake_command test)
run_cmake(${test})
endfunction()
-function(run_cmake_script test)
- set(RunCMake_TEST_COMMAND ${CMAKE_COMMAND} ${ARGN} -P ${RunCMake_SOURCE_DIR}/${test}.cmake)
- run_cmake(${test})
-endfunction()
-
function(run_cmake_with_options test)
set(RunCMake_TEST_OPTIONS "${ARGN}")
run_cmake(${test})
diff --git a/Tests/RunCMake/Syntax/FunctionUnmatched-stderr.txt b/Tests/RunCMake/Syntax/FunctionUnmatched-stderr.txt
index 306c2555a..87fa7464d 100644
--- a/Tests/RunCMake/Syntax/FunctionUnmatched-stderr.txt
+++ b/Tests/RunCMake/Syntax/FunctionUnmatched-stderr.txt
@@ -1,8 +1,4 @@
-^CMake Error in FunctionUnmatched.cmake:
- A logical block opening on the line
-
- .*/Tests/RunCMake/Syntax/FunctionUnmatched.cmake:[0-9]+ \(function\)
-
- is not closed.
+^CMake Error at FunctionUnmatched\.cmake:[0-9]+ \(function\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/Syntax/FunctionUnmatchedForeach-stderr.txt b/Tests/RunCMake/Syntax/FunctionUnmatchedForeach-stderr.txt
index f4ff70945..7904b87b1 100644
--- a/Tests/RunCMake/Syntax/FunctionUnmatchedForeach-stderr.txt
+++ b/Tests/RunCMake/Syntax/FunctionUnmatchedForeach-stderr.txt
@@ -1,8 +1,4 @@
-^CMake Error at FunctionUnmatchedForeach.cmake:[0-9]+ \(f\):
- A logical block opening on the line
-
- .*/Tests/RunCMake/Syntax/FunctionUnmatchedForeach.cmake:[0-9]+ \(foreach\)
-
- is not closed.
+^CMake Error at FunctionUnmatchedForeach\.cmake:[0-9]+ \(endfunction\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/Syntax/ImproperNesting-result.txt b/Tests/RunCMake/Syntax/ImproperNesting-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/ImproperNesting-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/ImproperNesting-stderr.txt b/Tests/RunCMake/Syntax/ImproperNesting-stderr.txt
new file mode 100644
index 000000000..a209ef6ce
--- /dev/null
+++ b/Tests/RunCMake/Syntax/ImproperNesting-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at ImproperNesting\.cmake:[0-9]+ \(endforeach\):
+ Flow control statements are not properly nested\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/Syntax/ImproperNesting.cmake b/Tests/RunCMake/Syntax/ImproperNesting.cmake
new file mode 100644
index 000000000..47ff9f90b
--- /dev/null
+++ b/Tests/RunCMake/Syntax/ImproperNesting.cmake
@@ -0,0 +1,7 @@
+message(FATAL_ERROR "This should not happen")
+
+foreach(i 1 2)
+ if(1)
+endforeach()
+endif()
+endif()
diff --git a/Tests/RunCMake/Syntax/MacroUnmatched-stderr.txt b/Tests/RunCMake/Syntax/MacroUnmatched-stderr.txt
index 440d86394..a7af590ff 100644
--- a/Tests/RunCMake/Syntax/MacroUnmatched-stderr.txt
+++ b/Tests/RunCMake/Syntax/MacroUnmatched-stderr.txt
@@ -1,8 +1,4 @@
-^CMake Error in MacroUnmatched.cmake:
- A logical block opening on the line
-
- .*/Tests/RunCMake/Syntax/MacroUnmatched.cmake:[0-9]+ \(macro\)
-
- is not closed.
+^CMake Error at MacroUnmatched\.cmake:[0-9]+ \(macro\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/Syntax/MacroUnmatchedForeach-stderr.txt b/Tests/RunCMake/Syntax/MacroUnmatchedForeach-stderr.txt
index 820cd2e5a..30c4a4c02 100644
--- a/Tests/RunCMake/Syntax/MacroUnmatchedForeach-stderr.txt
+++ b/Tests/RunCMake/Syntax/MacroUnmatchedForeach-stderr.txt
@@ -1,8 +1,4 @@
-^CMake Error at MacroUnmatchedForeach.cmake:[0-9]+ \(m\):
- A logical block opening on the line
-
- .*/Tests/RunCMake/Syntax/MacroUnmatchedForeach.cmake:[0-9]+ \(foreach\)
-
- is not closed.
+^CMake Error at MacroUnmatchedForeach\.cmake:[0-9]+ \(endmacro\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/Syntax/NameWithSpaces-stderr.txt b/Tests/RunCMake/Syntax/NameWithSpaces-stderr.txt
index cf6dad5d3..71e8db307 100644
--- a/Tests/RunCMake/Syntax/NameWithSpaces-stderr.txt
+++ b/Tests/RunCMake/Syntax/NameWithSpaces-stderr.txt
@@ -7,6 +7,6 @@
\${var
- syntax error, unexpected \$end, expecting } \(6\)
+ syntax error, unexpected end of file, expecting } \(6\)
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/Syntax/NameWithTabs-stderr.txt b/Tests/RunCMake/Syntax/NameWithTabs-stderr.txt
index 70e7c125b..84ccdbee3 100644
--- a/Tests/RunCMake/Syntax/NameWithTabs-stderr.txt
+++ b/Tests/RunCMake/Syntax/NameWithTabs-stderr.txt
@@ -7,6 +7,6 @@
\${var
- syntax error, unexpected \$end, expecting } \(6\)
+ syntax error, unexpected end of file, expecting } \(6\)
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/Syntax/Override.cmake b/Tests/RunCMake/Syntax/Override.cmake
new file mode 100644
index 000000000..af62db140
--- /dev/null
+++ b/Tests/RunCMake/Syntax/Override.cmake
@@ -0,0 +1,6 @@
+function(override)
+ function(${FUNCTION_NAME})
+ endfunction()
+endfunction()
+override()
+message(FATAL_ERROR "This shouldn't happen")
diff --git a/Tests/RunCMake/Syntax/OverrideBreak-result.txt b/Tests/RunCMake/Syntax/OverrideBreak-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideBreak-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideContinue-result.txt b/Tests/RunCMake/Syntax/OverrideContinue-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideContinue-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideElse-result.txt b/Tests/RunCMake/Syntax/OverrideElse-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideElse-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideElseIf-result.txt b/Tests/RunCMake/Syntax/OverrideElseIf-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideElseIf-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideEndForeach-result.txt b/Tests/RunCMake/Syntax/OverrideEndForeach-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideEndForeach-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideEndFunction-result.txt b/Tests/RunCMake/Syntax/OverrideEndFunction-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideEndFunction-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideEndIf-result.txt b/Tests/RunCMake/Syntax/OverrideEndIf-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideEndIf-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideEndMacro-result.txt b/Tests/RunCMake/Syntax/OverrideEndMacro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideEndMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideEndWhile-result.txt b/Tests/RunCMake/Syntax/OverrideEndWhile-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideEndWhile-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideForeach-result.txt b/Tests/RunCMake/Syntax/OverrideForeach-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideForeach-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideFunction-result.txt b/Tests/RunCMake/Syntax/OverrideFunction-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideFunction-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideIf-result.txt b/Tests/RunCMake/Syntax/OverrideIf-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideIf-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideMacro-result.txt b/Tests/RunCMake/Syntax/OverrideMacro-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideReturn-result.txt b/Tests/RunCMake/Syntax/OverrideReturn-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideReturn-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/OverrideWhile-result.txt b/Tests/RunCMake/Syntax/OverrideWhile-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/OverrideWhile-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/ParenInENV-stderr.txt b/Tests/RunCMake/Syntax/ParenInENV-stderr.txt
index 144b57c1e..24c810bef 100644
--- a/Tests/RunCMake/Syntax/ParenInENV-stderr.txt
+++ b/Tests/RunCMake/Syntax/ParenInENV-stderr.txt
@@ -9,12 +9,12 @@ This warning is for project developers. Use -Wno-dev to suppress it.
CMake Error at ParenInENV.cmake:2 \(message\):
Syntax error in cmake code at
- .*Tests/RunCMake/Syntax/ParenInENV.cmake:2
+ .*/Tests/RunCMake/Syntax/ParenInENV.cmake:2
when parsing string
-->\$ENV{e
- syntax error, unexpected \$end, expecting } \(10\)
+ syntax error, unexpected end of file, expecting } \(10\)
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/Syntax/RunCMakeTest.cmake b/Tests/RunCMake/Syntax/RunCMakeTest.cmake
index 8d74dc163..4d246577b 100644
--- a/Tests/RunCMake/Syntax/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Syntax/RunCMakeTest.cmake
@@ -72,6 +72,7 @@ run_cmake(UnterminatedBrace2)
run_cmake(UnterminatedBracket0)
run_cmake(UnterminatedBracket1)
run_cmake(UnterminatedBracketComment)
+run_cmake(ImproperNesting)
# Variable expansion tests
run_cmake(ExpandInAt)
@@ -122,3 +123,30 @@ run_cmake(FunctionUnmatched)
run_cmake(FunctionUnmatchedForeach)
run_cmake(MacroUnmatched)
run_cmake(MacroUnmatchedForeach)
+
+function(run_override name)
+ string(TOLOWER "${name}" lname)
+ set(RunCMake_DEFAULT_stderr "^CMake Error at [^
+]*/Tests/RunCMake/Syntax/Override\\.cmake:[0-9]+ \\(function\\):
+ Built-in flow control command \"${lname}\" cannot be overridden\\.
+Call Stack \\(most recent call first\\):
+ [^
+]*/Tests/RunCMake/Syntax/Override\\.cmake:[0-9]+ \\(override\\)$")
+ run_cmake_command(Override${name} "${CMAKE_COMMAND}" -DFUNCTION_NAME=${name} -P "${RunCMake_SOURCE_DIR}/Override.cmake")
+endfunction()
+
+run_override(Break)
+run_override(Continue)
+run_override(Else)
+run_override(ElseIf)
+run_override(EndForeach)
+run_override(EndFunction)
+run_override(EndIf)
+run_override(EndMacro)
+run_override(EndWhile)
+run_override(Foreach)
+run_override(Function)
+run_override(If)
+run_override(Macro)
+run_override(Return)
+run_override(While)
diff --git a/Tests/RunCMake/Syntax/UnterminatedBrace0-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedBrace0-stderr.txt
index cf63dbe77..b309c3baf 100644
--- a/Tests/RunCMake/Syntax/UnterminatedBrace0-stderr.txt
+++ b/Tests/RunCMake/Syntax/UnterminatedBrace0-stderr.txt
@@ -7,6 +7,6 @@ CMake Error at UnterminatedBrace0.cmake:2 \(set\):
\${
- syntax error, unexpected \$end, expecting } \(3\)
+ syntax error, unexpected end of file, expecting } \(3\)
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/Syntax/UnterminatedBrace1-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedBrace1-stderr.txt
index 0e6f7864e..ffe0e2a9e 100644
--- a/Tests/RunCMake/Syntax/UnterminatedBrace1-stderr.txt
+++ b/Tests/RunCMake/Syntax/UnterminatedBrace1-stderr.txt
@@ -7,7 +7,7 @@ CMake Warning \(dev\) at UnterminatedBrace1.cmake:3 \(set\):
\${
- syntax error, unexpected \$end, expecting } \(3\)
+ syntax error, unexpected end of file, expecting } \(3\)
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/TargetObjects/CMakeLists.txt b/Tests/RunCMake/TargetObjects/CMakeLists.txt
index 44b5d30c0..e9a0a3f04 100644
--- a/Tests/RunCMake/TargetObjects/CMakeLists.txt
+++ b/Tests/RunCMake/TargetObjects/CMakeLists.txt
@@ -1,3 +1,3 @@
cmake_minimum_required(VERSION 3.3)
-project(${RunCMake_TEST})
+project(${RunCMake_TEST} LANGUAGES NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
index 30b9fee53..d2b3032bb 100644
--- a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
@@ -2,3 +2,7 @@ include(RunCMake)
run_cmake(NoTarget)
run_cmake(NotObjlibTarget)
+
+if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
+ run_cmake(XcodeVariableNoGenexExpansion)
+endif()
diff --git a/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-result.txt b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt
new file mode 100644
index 000000000..1360015ac
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at XcodeVariableNoGenexExpansion\.cmake:9 \(file\):
+ Error evaluating generator expression:
+
+ \$\<TARGET_OBJECTS:A\>
+
+ The evaluation of the TARGET_OBJECTS generator expression is only suitable
+ for consumption by CMake \(limited under Xcode with multiple architectures\)\.
+ It is not suitable for writing out elsewhere\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake
new file mode 100644
index 000000000..83d721000
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake
@@ -0,0 +1,12 @@
+add_library(A OBJECT IMPORTED)
+
+# We don't actually build this example so just configure a dummy
+# object file to test. It does not have to exist.
+set_target_properties(A PROPERTIES
+ IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/$(CURRENT_ARCH)/does_not_exist.o"
+)
+
+file(GENERATE
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objects.txt
+ CONTENT "$<TARGET_OBJECTS:A>"
+)
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index b3f3a5ea7..3846d7c9b 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -34,6 +34,7 @@
\* CMP0108
\* CMP0112
\* CMP0113
+ \* CMP0119
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetCheckProperty.cmake b/Tests/RunCMake/TargetSources/AddCustomTargetCheckProperty.cmake
new file mode 100644
index 000000000..1787e877b
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetCheckProperty.cmake
@@ -0,0 +1,16 @@
+add_custom_target(target1 ALL)
+target_sources(target1 PRIVATE main.cpp)
+get_property(actualProp1 TARGET target1 PROPERTY SOURCES)
+set(desiredProp1 main.cpp)
+if(NOT desiredProp1 STREQUAL actualProp1)
+ message("source property not set. desired: \"${desiredProp1}\" actual: \"${actualProp1}\"")
+endif()
+
+add_custom_target(target2 ALL SOURCES main.cpp)
+target_sources(target2 PRIVATE empty_1.cpp empty_2.cpp)
+target_sources(target2 PRIVATE empty_3.cpp)
+get_property(actualProp2 TARGET target2 PROPERTY SOURCES)
+set(desiredProp2 main.cpp empty_1.cpp empty_2.cpp empty_3.cpp)
+if (NOT desiredProp2 STREQUAL actualProp2)
+ message("source property not set. desired: \"${desiredProp2}\" actual: \"${actualProp2}\"")
+endif()
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetGenx.cmake b/Tests/RunCMake/TargetSources/AddCustomTargetGenx.cmake
new file mode 100644
index 000000000..0078eab0f
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetGenx.cmake
@@ -0,0 +1,2 @@
+add_custom_target(target ALL)
+target_sources(target PRIVATE $<IF:1,${CMAKE_CURRENT_LIST_DIR}/main.cpp,${CMAKE_CURRENT_LIST_DIR}/empty_1.cpp>)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-result.txt b/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-stderr.txt b/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-stderr.txt
new file mode 100644
index 000000000..9334bf6ff
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at AddCustomTargetInterfaceSources.cmake:2 \(target_sources\):
+ target_sources may only set PRIVATE properties on custom targets
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources.cmake b/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources.cmake
new file mode 100644
index 000000000..42a8ca2f1
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetInterfaceSources.cmake
@@ -0,0 +1,2 @@
+add_custom_target(target ALL)
+target_sources(target INTERFACE main.cpp)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetPrivateSources.cmake b/Tests/RunCMake/TargetSources/AddCustomTargetPrivateSources.cmake
new file mode 100644
index 000000000..11f0258c8
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetPrivateSources.cmake
@@ -0,0 +1,2 @@
+add_custom_target(target ALL)
+target_sources(target PRIVATE main.cpp)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-result.txt b/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-stderr.txt b/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-stderr.txt
new file mode 100644
index 000000000..afba4beed
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at AddCustomTargetPublicSources.cmake:2 \(target_sources\):
+ target_sources may only set PRIVATE properties on custom targets
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources.cmake b/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources.cmake
new file mode 100644
index 000000000..d9e82c02f
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetPublicSources.cmake
@@ -0,0 +1,2 @@
+add_custom_target(target ALL)
+target_sources(target PUBLIC main.cpp)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetSources-result.txt b/Tests/RunCMake/TargetSources/AddCustomTargetSources-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetSources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetSources-stderr.txt b/Tests/RunCMake/TargetSources/AddCustomTargetSources-stderr.txt
new file mode 100644
index 000000000..4a153e967
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetSources-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at AddCustomTargetSources.cmake:2 \(target_sources\):
+ target_sources called with invalid arguments
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetSources/AddCustomTargetSources.cmake b/Tests/RunCMake/TargetSources/AddCustomTargetSources.cmake
new file mode 100644
index 000000000..dd688d30d
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/AddCustomTargetSources.cmake
@@ -0,0 +1,2 @@
+add_custom_target(target ALL)
+target_sources(target main.cpp)
diff --git a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
index 0d462ba66..b56ee44e8 100644
--- a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
@@ -14,3 +14,9 @@ run_cmake(RelativePathInSubdirInterface)
run_cmake(RelativePathInSubdirPrivate)
run_cmake(RelativePathInSubdirInclude)
run_cmake(ExportBuild)
+run_cmake(AddCustomTargetPublicSources)
+run_cmake(AddCustomTargetPrivateSources)
+run_cmake(AddCustomTargetInterfaceSources)
+run_cmake(AddCustomTargetSources)
+run_cmake(AddCustomTargetCheckProperty)
+run_cmake(AddCustomTargetGenx)
diff --git a/Tests/RunCMake/ToolchainFile/CheckLanguage-stdout.txt b/Tests/RunCMake/ToolchainFile/CheckLanguage-stdout.txt
new file mode 100644
index 000000000..b96eee625
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/CheckLanguage-stdout.txt
@@ -0,0 +1 @@
+-- Looking for a C compiler - NOTFOUND
diff --git a/Tests/RunCMake/ToolchainFile/CheckLanguage-toolchain.cmake b/Tests/RunCMake/ToolchainFile/CheckLanguage-toolchain.cmake
new file mode 100644
index 000000000..081f905b1
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/CheckLanguage-toolchain.cmake
@@ -0,0 +1,4 @@
+get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE)
+if(in_try_compile)
+ message(FATAL_ERROR "Toolchain file included")
+endif()
diff --git a/Tests/RunCMake/ToolchainFile/CheckLanguage.cmake b/Tests/RunCMake/ToolchainFile/CheckLanguage.cmake
new file mode 100644
index 000000000..854b3d450
--- /dev/null
+++ b/Tests/RunCMake/ToolchainFile/CheckLanguage.cmake
@@ -0,0 +1,2 @@
+include(CheckLanguage)
+check_language(C)
diff --git a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
index 7eb4485d0..659523c42 100644
--- a/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ToolchainFile/RunCMakeTest.cmake
@@ -7,6 +7,7 @@ endfunction()
run_cmake_toolchain(CallEnableLanguage)
run_cmake_toolchain(CallProject)
+run_cmake_toolchain(CheckLanguage)
run_cmake_toolchain(FlagsInit)
run_cmake_toolchain(LinkFlagsInit)
diff --git a/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake
new file mode 100644
index 000000000..9a38b957f
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake
@@ -0,0 +1,21 @@
+include(RunCMake)
+
+function(run_transform_depfile name)
+ set(RunCMake-check-file gccdepfile.cmake)
+ 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)
+ run_transform_depfile(deps-windows)
+else()
+ run_transform_depfile(deps-unix)
+endif()
+run_transform_depfile(noexist)
+run_transform_depfile(empty)
+run_transform_depfile(invalid)
diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.d b/Tests/RunCMake/TransformDepfile/deps-unix.d
new file mode 100644
index 000000000..5da5be8f7
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-unix.d
@@ -0,0 +1,6 @@
+out1 /home/build/out2: in1 /home/build/in2
+
+out3 \
+ /home/build/out4: \
+ in3 \
+ /home/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.d.txt b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt
new file mode 100644
index 000000000..fbdecc072
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt
@@ -0,0 +1,8 @@
+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-unix.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt
new file mode 100644
index 000000000..70bac5da2
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt
@@ -0,0 +1,6 @@
+^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.d b/Tests/RunCMake/TransformDepfile/deps-windows.d
new file mode 100644
index 000000000..c92667090
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-windows.d
@@ -0,0 +1,6 @@
+out1 C:/build/out2: in1 C:/build/in2
+
+out3 \
+ C:/build/out4: \
+ in3 \
+ C:/build/in4
diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.d.txt b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt
new file mode 100644
index 000000000..e09ae375a
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt
@@ -0,0 +1,8 @@
+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/deps-windows.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt
new file mode 100644
index 000000000..09f9e9711
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt
@@ -0,0 +1,6 @@
+^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/empty.d b/Tests/RunCMake/TransformDepfile/empty.d
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/empty.d
diff --git a/Tests/RunCMake/TransformDepfile/empty.d.txt b/Tests/RunCMake/TransformDepfile/empty.d.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/empty.d.txt
diff --git a/Tests/RunCMake/TransformDepfile/empty.tlog.txt b/Tests/RunCMake/TransformDepfile/empty.tlog.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/empty.tlog.txt
diff --git a/Tests/RunCMake/TransformDepfile/gccdepfile.cmake b/Tests/RunCMake/TransformDepfile/gccdepfile.cmake
new file mode 100644
index 000000000..be1e21016
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/gccdepfile.cmake
@@ -0,0 +1,16 @@
+if(EXISTS "${RunCMake_SOURCE_DIR}/${name}.d.txt")
+ file(READ "${RunCMake_SOURCE_DIR}/${name}.d.txt" expected_contents)
+
+ if(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.d")
+ file(READ "${RunCMake_TEST_BINARY_DIR}/out.d" 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.d:\n ${p_expected_contents}\nActual contents:\n ${p_actual_contents}")
+ endif()
+ else()
+ string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.d should exist\n")
+ endif()
+elseif(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.d")
+ string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.d should not exist\n")
+endif()
diff --git a/Tests/RunCMake/CommandLine/E_server-pipe-result.txt b/Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt
index 0cfbf0888..0cfbf0888 100644
--- a/Tests/RunCMake/CommandLine/E_server-pipe-result.txt
+++ b/Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt
diff --git a/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt b/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt
@@ -0,0 +1 @@
+2
diff --git a/Tests/RunCMake/TransformDepfile/invalid.d b/Tests/RunCMake/TransformDepfile/invalid.d
new file mode 100644
index 000000000..9977a2836
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/invalid.d
@@ -0,0 +1 @@
+invalid
diff --git a/Tests/RunCMake/TransformDepfile/noexist.d.txt b/Tests/RunCMake/TransformDepfile/noexist.d.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/noexist.d.txt
diff --git a/Tests/RunCMake/TransformDepfile/noexist.tlog.txt b/Tests/RunCMake/TransformDepfile/noexist.tlog.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/noexist.tlog.txt
diff --git a/Tests/RunCMake/TransformDepfile/vstlog.cmake b/Tests/RunCMake/TransformDepfile/vstlog.cmake
new file mode 100644
index 000000000..afa78d05c
--- /dev/null
+++ b/Tests/RunCMake/TransformDepfile/vstlog.cmake
@@ -0,0 +1,16 @@
+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/UnityBuild/RunCMakeTest.cmake b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
index 9ba3c856d..c00f78b3d 100644
--- a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
+++ b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
@@ -1,5 +1,14 @@
include(RunCMake)
+function(run_build name)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake(${name})
+ run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug)
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endfunction()
+
run_cmake(unitybuild_c)
run_cmake(unitybuild_c_batch)
run_cmake(unitybuild_c_group)
@@ -15,6 +24,9 @@ run_cmake(unitybuild_c_no_unity_build)
run_cmake(unitybuild_c_no_unity_build_group)
run_cmake(unitybuild_order)
run_cmake(unitybuild_invalid_mode)
+run_build(unitybuild_anon_ns)
+run_build(unitybuild_anon_ns_no_unity_build)
+run_build(unitybuild_anon_ns_group_mode)
function(run_test name)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
diff --git a/Tests/RunCMake/UnityBuild/f.cxx b/Tests/RunCMake/UnityBuild/f.cxx
new file mode 100644
index 000000000..d5813c67c
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/f.cxx
@@ -0,0 +1,5 @@
+int f(int x)
+{
+ (void)x;
+ return 0;
+}
diff --git a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake
new file mode 100644
index 000000000..746be3248
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake
@@ -0,0 +1,10 @@
+set(unitybuild_0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_cxx.cxx")
+
+file(STRINGS ${unitybuild_0} src)
+
+foreach(expectedRegex IN ITEMS "SRC_f\\.cxx" "BLD_s1\\.cpp")
+ if(NOT "${src}" MATCHES "${expectedRegex}")
+ set(RunCMake_TEST_FAILED "Generated unity file doesn't have a match for expected unity ID regex ${expectedRegex}")
+ return()
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake
new file mode 100644
index 000000000..e05863dff
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake
@@ -0,0 +1,11 @@
+project(unitybuild_anon_ns CXX)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/unitybuild_anon_ns_test_files.cmake)
+
+write_unity_build_anon_ns_test_files(srcs)
+
+add_library(tgt SHARED f.cxx ${srcs})
+
+set_target_properties(tgt PROPERTIES UNITY_BUILD ON)
+
+set_target_properties(tgt PROPERTIES UNITY_BUILD_UNIQUE_ID MY_ANON_ID)
diff --git a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_group_mode.cmake b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_group_mode.cmake
new file mode 100644
index 000000000..a91fc745d
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_group_mode.cmake
@@ -0,0 +1,19 @@
+project(unitybuild_anon_ns_group_mode CXX)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/unitybuild_anon_ns_test_files.cmake)
+
+write_unity_build_anon_ns_test_files(srcs)
+
+add_library(tgt SHARED ${srcs})
+
+set_target_properties(tgt PROPERTIES UNITY_BUILD ON
+ UNITY_BUILD_MODE GROUP)
+
+set_target_properties(tgt PROPERTIES UNITY_BUILD_UNIQUE_ID MY_ANON_ID)
+
+set_source_files_properties(s1.cpp s2.cpp s5.cpp s7.cpp s8.cpp
+ PROPERTIES UNITY_GROUP "a"
+ )
+set_source_files_properties(s3.cpp s4.cpp s6.cpp
+ PROPERTIES UNITY_GROUP "b"
+ )
diff --git a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_no_unity_build.cmake b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_no_unity_build.cmake
new file mode 100644
index 000000000..9f0a9e1d6
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_no_unity_build.cmake
@@ -0,0 +1,11 @@
+project(unitybuild_anon_ns_no_unity_build CXX)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/unitybuild_anon_ns_test_files.cmake)
+
+write_unity_build_anon_ns_test_files(srcs)
+
+add_library(tgt SHARED ${srcs})
+
+set_target_properties(tgt PROPERTIES UNITY_BUILD OFF)
+
+set_target_properties(tgt PROPERTIES UNITY_BUILD_UNIQUE_ID MY_ANON_ID)
diff --git a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_test_files.cmake b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_test_files.cmake
new file mode 100644
index 000000000..06a600e2e
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns_test_files.cmake
@@ -0,0 +1,31 @@
+
+function(write_unity_build_anon_ns_test_files OUTVAR)
+ set(srcs)
+ foreach(s RANGE 1 8)
+ set(src "${CMAKE_CURRENT_BINARY_DIR}/s${s}.cpp")
+ file(WRITE "${src}" "
+#ifndef CONFIG_H
+#define CONFIG_H
+#define MY_ANON_NAMESPACE MY_ANON_ID
+#define MY_ANON(Name) MY_ANON_NAMESPACE::Name
+#define MY_ANON_USING_NAMESPACE using namespace MY_ANON_NAMESPACE
+#endif
+
+namespace { namespace MY_ANON_NAMESPACE {
+ int i = ${s};
+}}
+int use_plain_${s}() {
+ return MY_ANON_NAMESPACE::i;
+}
+int func_like_macro_${s}() {
+ return MY_ANON(i);
+}
+int using_macro_${s}() {
+ MY_ANON_USING_NAMESPACE;
+ return i;
+}
+")
+ list(APPEND srcs "${src}")
+ endforeach()
+ set(${OUTVAR} ${srcs} PARENT_SCOPE)
+endfunction()
diff --git a/Tests/RunCMake/VS10Project/CustomCommandGenex-check.cmake b/Tests/RunCMake/VS10Project/CustomCommandGenex-check.cmake
new file mode 100644
index 000000000..a7047bcf8
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/CustomCommandGenex-check.cmake
@@ -0,0 +1,37 @@
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+set(found_CustomBuild_out 0)
+set(found_CustomBuild_out_CONFIG 0)
+set(found_CustomBuild_out_CONFIG_CONFIG 0)
+set(found_CustomBuild_out_HASH 0)
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES [[<CustomBuild Include=".*\\out\.txt\.rule">]])
+ set(found_CustomBuild_out 1)
+ endif()
+ if(line MATCHES [[<CustomBuild Include=".*\\out-\(CONFIG\)\.txt\.rule">]])
+ set(found_CustomBuild_out_CONFIG 1)
+ endif()
+ if(line MATCHES [[<CustomBuild Include=".*\\out-\(CONFIG\)-\(CONFIG\)\.txt\.rule">]])
+ set(found_CustomBuild_out_CONFIG_CONFIG 1)
+ endif()
+ if(line MATCHES [[<CustomBuild Include=".*\\[0-9A-Fa-f]+\.rule">]])
+ set(found_CustomBuild_out_HASH 1)
+ endif()
+endforeach()
+if(NOT found_CustomBuild_out)
+ string(APPEND RunCMake_TEST_FAILED "CustomBuild for out.txt.rule not found in\n ${vcProjectFile}\n")
+endif()
+if(NOT found_CustomBuild_out_CONFIG)
+ string(APPEND RunCMake_TEST_FAILED "CustomBuild for out-(CONFIG).txt.rule not found in\n ${vcProjectFile}\n")
+endif()
+if(NOT found_CustomBuild_out_CONFIG_CONFIG)
+ string(APPEND RunCMake_TEST_FAILED "CustomBuild for out-(CONFIG)-(CONFIG).txt.rule not found in\n ${vcProjectFile}\n")
+endif()
+if(NOT found_CustomBuild_out_HASH)
+ string(APPEND RunCMake_TEST_FAILED "CustomBuild for <hash>.rule not found in\n ${vcProjectFile}\n")
+endif()
diff --git a/Tests/RunCMake/VS10Project/CustomCommandGenex.cmake b/Tests/RunCMake/VS10Project/CustomCommandGenex.cmake
new file mode 100644
index 000000000..5b69dc218
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/CustomCommandGenex.cmake
@@ -0,0 +1,21 @@
+add_custom_command(
+ OUTPUT "$<1:out.txt>"
+ COMMAND ${CMAKE_COMMAND} -E touch "out.txt"
+ VERBATIM
+ )
+add_custom_command(
+ OUTPUT "out-$<CONFIG>.txt"
+ COMMAND ${CMAKE_COMMAND} -E touch "out-$<CONFIG>.txt"
+ VERBATIM
+ )
+add_custom_command(
+ OUTPUT "out-$<CONFIG>-$<CONFIG>.txt"
+ COMMAND ${CMAKE_COMMAND} -E touch "out-$<CONFIG>-$<CONFIG>.txt"
+ VERBATIM
+ )
+add_custom_command(
+ OUTPUT "out-$<CONFIG>-$<CONFIG:Debug>.txt"
+ COMMAND ${CMAKE_COMMAND} -E touch "out-$<CONFIG>-$<CONFIG:Debug>.txt"
+ VERBATIM
+ )
+add_custom_target(foo DEPENDS "out.txt" "out-$<CONFIG>.txt" "out-$<CONFIG>-$<CONFIG>.txt" "out-$<CONFIG>-$<CONFIG:Debug>.txt")
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index 133dacc17..d5ed136ac 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -7,6 +7,7 @@ if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREA
run_cmake(LanguageStandard)
endif()
+run_cmake(CustomCommandGenex)
run_cmake(VsCsharpSourceGroup)
run_cmake(VsCSharpCompilerOpts)
run_cmake(ExplicitCMakeLists)
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-result.txt b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-stderr.txt b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-stderr.txt
new file mode 100644
index 000000000..4e0d75622
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/Modules/WriteCompilerDetectionHeader.cmake:[0-9]+ \(message\):
+ The WriteCompilerDetectionHeader module has been removed by policy CMP0120.
+Call Stack \(most recent call first\):
+ CMP0120-NEW-Direct.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct.cmake b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct.cmake
new file mode 100644
index 000000000..4cd2c5625
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-Direct.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0120 NEW)
+include(${CMAKE_ROOT}/Modules/WriteCompilerDetectionHeader.cmake)
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-result.txt b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-stderr.txt b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-stderr.txt
new file mode 100644
index 000000000..2f7ad705b
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at CMP0120-NEW.cmake:[0-9]+ \(include\):
+ include could not find requested file:
+
+ WriteCompilerDetectionHeader
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW.cmake b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW.cmake
new file mode 100644
index 000000000..3d39a979c
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0120 NEW)
+include(WriteCompilerDetectionHeader)
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD-Direct.cmake b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD-Direct.cmake
new file mode 100644
index 000000000..48517e640
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD-Direct.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0120 OLD)
+include(${CMAKE_ROOT}/Modules/WriteCompilerDetectionHeader.cmake)
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD.cmake b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD.cmake
new file mode 100644
index 000000000..c51318613
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0120 OLD)
+include(WriteCompilerDetectionHeader)
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct-stderr.txt b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct-stderr.txt
new file mode 100644
index 000000000..88cd8f74d
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Warning \(dev\) at [^
+]*/Modules/WriteCompilerDetectionHeader.cmake:[0-9]+ \(message\):
+ The WriteCompilerDetectionHeader module will be removed by policy CMP0120.
+ Projects should be ported away from the module, perhaps by bundling a copy
+ of the generated header or using a third-party alternative.
+Call Stack \(most recent call first\):
+ CMP0120-WARN-Direct.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct.cmake b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct.cmake
new file mode 100644
index 000000000..d3c7f776d
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-Direct.cmake
@@ -0,0 +1,2 @@
+
+include(${CMAKE_ROOT}/Modules/WriteCompilerDetectionHeader.cmake)
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-stderr.txt b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-stderr.txt
new file mode 100644
index 000000000..315b4b141
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN-stderr.txt
@@ -0,0 +1,18 @@
+^CMake Warning \(dev\) at CMP0120-WARN.cmake:[0-9]+ \(include\):
+ Policy CMP0120 is not set: The WriteCompilerDetectionHeader module is
+ removed. Run "cmake --help-policy CMP0120" for policy details. Use the
+ cmake_policy command to set the policy and suppress this warning.
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\) at [^
+]*/Modules/WriteCompilerDetectionHeader.cmake:[0-9]+ \(message\):
+ The WriteCompilerDetectionHeader module will be removed by policy CMP0120.
+ Projects should be ported away from the module, perhaps by bundling a copy
+ of the generated header or using a third-party alternative.
+Call Stack \(most recent call first\):
+ CMP0120-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN.cmake b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN.cmake
new file mode 100644
index 000000000..1f95e3ed6
--- /dev/null
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/CMP0120-WARN.cmake
@@ -0,0 +1,2 @@
+
+include(WriteCompilerDetectionHeader)
diff --git a/Tests/RunCMake/WriteCompilerDetectionHeader/RunCMakeTest.cmake b/Tests/RunCMake/WriteCompilerDetectionHeader/RunCMakeTest.cmake
index a834e6d45..7589f745e 100644
--- a/Tests/RunCMake/WriteCompilerDetectionHeader/RunCMakeTest.cmake
+++ b/Tests/RunCMake/WriteCompilerDetectionHeader/RunCMakeTest.cmake
@@ -1,5 +1,12 @@
include(RunCMake)
+run_cmake(CMP0120-WARN)
+run_cmake(CMP0120-OLD)
+run_cmake(CMP0120-NEW)
+run_cmake(CMP0120-WARN-Direct)
+run_cmake(CMP0120-OLD-Direct)
+run_cmake(CMP0120-NEW-Direct)
+
run_cmake(InvalidArgs)
run_cmake(NoCompiler)
run_cmake(NoFeature)
diff --git a/Tests/RunCMake/XcodeProject-Embed/CMakeLists.txt b/Tests/RunCMake/XcodeProject-Embed/CMakeLists.txt
new file mode 100644
index 000000000..0400d1a03
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19)
+project(${RunCMake_TEST} LANGUAGES C)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake
new file mode 100644
index 000000000..9cc03b9f4
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff-check.cmake
@@ -0,0 +1,14 @@
+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
+ )
+
+ if(NOT result_var)
+ set(RunCMake_TEST_FAILED "${attr} attribute is set" PARENT_SCOPE)
+ endif()
+endfunction()
+
+findAttribute(${test} "RemoveHeadersOnCopy")
+findAttribute(${test} "CodeSignOnCopy")
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake
new file mode 100644
index 000000000..f4fe07fde
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake
@@ -0,0 +1,7 @@
+add_executable(app MACOSX_BUNDLE main.m)
+
+set_target_properties(app PROPERTIES
+ XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
+ XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY OFF
+ XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY OFF
+)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake
new file mode 100644
index 000000000..e4ea55df2
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake
@@ -0,0 +1,3 @@
+if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/sharedFrameworkExt.framework)
+ set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location")
+endif()
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake
new file mode 100644
index 000000000..3f62640c9
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-check.cmake
@@ -0,0 +1,14 @@
+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
+ )
+
+ if(result_var)
+ set(RunCMake_TEST_FAILED "${attr} attribute not set" PARENT_SCOPE)
+ endif()
+endfunction()
+
+findAttribute(${test} "RemoveHeadersOnCopy")
+findAttribute(${test} "CodeSignOnCopy")
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake
new file mode 100644
index 000000000..79d8d7779
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake
@@ -0,0 +1,7 @@
+add_executable(app MACOSX_BUNDLE main.m)
+
+set_target_properties(app PROPERTIES
+ XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
+ XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON
+ XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
+)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake
new file mode 100644
index 000000000..57c79eae4
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake
@@ -0,0 +1,3 @@
+if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/subdir/sharedFrameworkExt.framework)
+ set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location")
+endif()
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake
new file mode 100644
index 000000000..3f62640c9
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-check.cmake
@@ -0,0 +1,14 @@
+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
+ )
+
+ if(result_var)
+ set(RunCMake_TEST_FAILED "${attr} attribute not set" PARENT_SCOPE)
+ endif()
+endfunction()
+
+findAttribute(${test} "RemoveHeadersOnCopy")
+findAttribute(${test} "CodeSignOnCopy")
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake
new file mode 100644
index 000000000..4c78199e5
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake
@@ -0,0 +1,8 @@
+add_executable(app MACOSX_BUNDLE main.m)
+
+set_target_properties(app PROPERTIES
+ XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
+ XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON
+ XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
+ XCODE_EMBED_FRAMEWORKS_PATH "subdir"
+)
diff --git a/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake b/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake
new file mode 100644
index 000000000..64e2f9587
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake
@@ -0,0 +1,2 @@
+add_library(sharedFrameworkExt SHARED func.m)
+set_target_properties(sharedFrameworkExt PROPERTIES FRAMEWORK TRUE)
diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
new file mode 100644
index 000000000..0dc1cf31c
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
@@ -0,0 +1,43 @@
+include(RunCMake)
+
+# Build a framework that the other tests will use and treat as external.
+# Always build in the Debug configuration so that the path to the framework
+# is predictable.
+function(ExternalFramework)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExternalFramework-build)
+ set(externalFramework ${RunCMake_TEST_BINARY_DIR}/Debug/sharedFrameworkExt.framework PARENT_SCOPE)
+
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ run_cmake(ExternalFramework)
+ run_cmake_command(ExternalFramework-build
+ ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}
+ --config Debug
+ --target sharedFrameworkExt
+ )
+endfunction()
+ExternalFramework()
+
+set(RunCMake_TEST_OPTIONS -DEXTERNAL_FWK=${externalFramework})
+
+run_cmake(EmbedFrameworksFlagsOff)
+
+function(TestFlagsOn testName)
+ 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()
+
+TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir)
+TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir)
diff --git a/Tests/RunCMake/XcodeProject-Embed/func.m b/Tests/RunCMake/XcodeProject-Embed/func.m
new file mode 100644
index 000000000..29c66895a
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/func.m
@@ -0,0 +1,6 @@
+#import <CoreFoundation/CoreFoundation.h>
+
+int func()
+{
+ return 1;
+}
diff --git a/Tests/RunCMake/XcodeProject-Embed/main.m b/Tests/RunCMake/XcodeProject-Embed/main.m
new file mode 100644
index 000000000..72e425d77
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject-Embed/main.m
@@ -0,0 +1,6 @@
+#import <CoreFoundation/CoreFoundation.h>
+
+int main(int argc, char** argv)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
index 794274c3a..8b0321657 100644
--- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
@@ -3,6 +3,7 @@ include(RunCMake)
run_cmake(ExplicitCMakeLists)
run_cmake(ImplicitCMakeLists)
run_cmake(InterfaceLibSources)
+run_cmake_with_options(SearchPaths -DCMAKE_CONFIGURATION_TYPES=Debug)
run_cmake(XcodeFileType)
run_cmake(XcodeAttributeLocation)
@@ -51,6 +52,35 @@ run_cmake(PerConfigPerSourceOptions)
run_cmake(PerConfigPerSourceDefinitions)
run_cmake(PerConfigPerSourceIncludeDirs)
+if(XCODE_VERSION VERSION_GREATER_EQUAL 12)
+
+ function(XcodeObjectLibsInTwoProjectsiOS)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeObjectLibsInTwoProjects-build-ios)
+ set(RunCMake_TEST_OPTIONS "-DCMAKE_SYSTEM_NAME=iOS")
+
+ run_cmake(XcodeObjectLibsInTwoProjects)
+
+ set(RunCMake_TEST_NO_CLEAN 1)
+
+ run_cmake_command(XcodeObjectLibsInTwoProjects-build-ios ${CMAKE_COMMAND} --build . --target shared_lib -- -sdk iphonesimulator)
+ endfunction()
+
+ XcodeObjectLibsInTwoProjectsiOS()
+
+ function(XcodeObjectLibsInTwoProjectsMacOS)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeObjectLibsInTwoProjects-build-macos)
+
+ run_cmake(XcodeObjectLibsInTwoProjects)
+
+ set(RunCMake_TEST_NO_CLEAN 1)
+
+ run_cmake_command(XcodeObjectLibsInTwoProjects-build-macos ${CMAKE_COMMAND} --build . --target shared_lib)
+ endfunction()
+
+ XcodeObjectLibsInTwoProjectsMacOS()
+
+endif()
+
function(XcodeSchemaGeneration)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeSchemaGeneration-build)
set(RunCMake_TEST_NO_CLEAN 1)
diff --git a/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake
new file mode 100644
index 000000000..71b7d8fae
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake
@@ -0,0 +1,76 @@
+set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/SearchPaths.xcodeproj/project.pbxproj")
+if(NOT EXISTS "${xcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.")
+ return()
+endif()
+
+set(relevant_lines "")
+set(found_project_FRAMEWORK_SEARCH_PATHS 0)
+set(found_target_both_FRAMEWORK_SEARCH_PATHS 0)
+set(found_target_include_FRAMEWORK_SEARCH_PATHS 0)
+set(found_target_library_FRAMEWORK_SEARCH_PATHS 0)
+set(found_inherited_FRAMEWORK_SEARCH_PATHS 0)
+set(found_project_LIBRARY_SEARCH_PATHS 0)
+set(found_target_library_LIBRARY_SEARCH_PATHS 0)
+set(found_inherited_LIBRARY_SEARCH_PATHS 0)
+file(STRINGS "${xcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES [[FRAMEWORK_SEARCH_PATHS]])
+ string(APPEND relevant_lines " ${line}\n")
+ if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = "[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/ProjectSearchPath";]])
+ set(found_project_FRAMEWORK_SEARCH_PATHS 1)
+ endif()
+ if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathInc(\\")?","(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib(\\")?","\$\(inherited\)"\);]])
+ set(found_target_both_FRAMEWORK_SEARCH_PATHS 1)
+ endif()
+ if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathInc(\\")?","\$\(inherited\)"\);]])
+ set(found_target_include_FRAMEWORK_SEARCH_PATHS 1)
+ endif()
+ if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib(\\")?","\$\(inherited\)"\);]])
+ set(found_target_library_FRAMEWORK_SEARCH_PATHS 1)
+ endif()
+ if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("\$\(inherited\)"\);]])
+ set(found_inherited_FRAMEWORK_SEARCH_PATHS 1)
+ endif()
+ endif()
+
+ if(line MATCHES [[LIBRARY_SEARCH_PATHS]])
+ string(APPEND relevant_lines " ${line}\n")
+ if(line MATCHES [[LIBRARY_SEARCH_PATHS = "[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/ProjectSearchPath";]])
+ set(found_project_LIBRARY_SEARCH_PATHS 1)
+ endif()
+ if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib/\$\(CONFIGURATION\)\$\(EFFECTIVE_PLATFORM_NAME\)(\\")?","(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib(\\")?","\$\(inherited\)"\);]])
+ set(found_target_library_LIBRARY_SEARCH_PATHS 1)
+ endif()
+ if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("\$\(inherited\)"\);]])
+ set(found_inherited_LIBRARY_SEARCH_PATHS 1)
+ endif()
+ endif()
+endforeach()
+if(NOT found_project_FRAMEWORK_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected FRAMEWORK_SEARCH_PATHS for project in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_target_both_FRAMEWORK_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected FRAMEWORK_SEARCH_PATHS for target 'both' in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_target_include_FRAMEWORK_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'include' in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_target_library_FRAMEWORK_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'library' in\n ${xcProjectFile}\n")
+endif()
+if(found_inherited_FRAMEWORK_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Found unexpected LIBRARY_SEARCH_PATHS inherited-only value in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_project_LIBRARY_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for project in\n ${xcProjectFile}\n")
+endif()
+if(NOT found_target_library_LIBRARY_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'library' in\n ${xcProjectFile}\n")
+endif()
+if(found_inherited_LIBRARY_SEARCH_PATHS)
+ string(APPEND RunCMake_TEST_FAILED "Found unexpected LIBRARY_SEARCH_PATHS inherited-only value 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/SearchPaths.cmake b/Tests/RunCMake/XcodeProject/SearchPaths.cmake
new file mode 100644
index 000000000..ef977092b
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/SearchPaths.cmake
@@ -0,0 +1,21 @@
+enable_language(C)
+
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathInc/TargetInc.framework")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework")
+
+set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath")
+set(CMAKE_XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath")
+
+add_executable(neither main.c)
+
+add_executable(both main.c)
+target_include_directories(both PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathInc/TargetInc.framework")
+target_link_libraries(both PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework")
+
+add_executable(include main.c)
+target_include_directories(include PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathInc/TargetInc.framework")
+
+add_executable(library main.c)
+target_link_libraries(library PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework")
+target_link_directories(library PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib")
diff --git a/Tests/RunCMake/XcodeProject/XcodeObjectLibsInTwoProjects.cmake b/Tests/RunCMake/XcodeProject/XcodeObjectLibsInTwoProjects.cmake
new file mode 100644
index 000000000..3ca24af8d
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/XcodeObjectLibsInTwoProjects.cmake
@@ -0,0 +1,5 @@
+cmake_minimum_required (VERSION 3.19)
+
+project (test_xcode_fail NONE)
+
+add_subdirectory(subproject_two_object_libs)
diff --git a/Tests/RunCMake/XcodeProject/subproject_two_object_libs/CMakeLists.txt b/Tests/RunCMake/XcodeProject/subproject_two_object_libs/CMakeLists.txt
new file mode 100644
index 000000000..e55836d98
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/subproject_two_object_libs/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required (VERSION 3.16)
+
+enable_language(CXX)
+
+project (subproject_two_object_libs)
+
+set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED NO)
+set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "")
+
+if(IOS)
+ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+ set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
+endif()
+
+# Hierarchy of libraries looks like:
+#
+# OBJECT-1 ---> STATIC--\
+# |---> SHARED
+# OBJECT-2 -------------/
+
+add_library(object_lib_dependency1 OBJECT dummy.cpp)
+
+add_library(static_lib_dependency STATIC dummy.cpp $<TARGET_OBJECTS:object_lib_dependency1>)
+
+add_library(object_lib_dependency2 OBJECT dummy.cpp)
+target_link_libraries(object_lib_dependency2 PRIVATE static_lib_dependency)
+
+add_library(shared_lib SHARED dummy.cpp)
+target_link_libraries(shared_lib PRIVATE static_lib_dependency)
+target_sources(shared_lib PRIVATE $<TARGET_OBJECTS:object_lib_dependency2>)
diff --git a/Tests/RunCMake/XcodeProject/subproject_two_object_libs/dummy.cpp b/Tests/RunCMake/XcodeProject/subproject_two_object_libs/dummy.cpp
new file mode 100644
index 000000000..8082abc61
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/subproject_two_object_libs/dummy.cpp
@@ -0,0 +1,5 @@
+namespace {
+void foo()
+{
+}
+}
diff --git a/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt b/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
index b7ee23a55..93243026f 100644
--- a/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
+++ b/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
@@ -1,5 +1,5 @@
CMake Error at AppendNotOutput.cmake:1 \(add_custom_command\):
- add_custom_command given APPEND option with output
+ Attempt to APPEND to custom command with output
.*RunCMake/add_custom_command/AppendNotOutput-build/out
diff --git a/Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt b/Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt
index 086e39752..547fb1c33 100644
--- a/Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt
+++ b/Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt
@@ -1,36 +1,67 @@
CMake Error at BadByproduct.cmake:2 \(add_custom_command\):
- add_custom_command called with BYPRODUCTS containing a "#". This character
- is not allowed.
+ BYPRODUCTS containing a "#" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error at BadByproduct.cmake:3 \(add_custom_command\):
- add_custom_command called with BYPRODUCTS containing a "<". This character
- is not allowed.
+ BYPRODUCTS containing a "<" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error at BadByproduct.cmake:4 \(add_custom_command\):
- add_custom_command called with BYPRODUCTS containing a ">". This character
- is not allowed.
+ BYPRODUCTS containing a ">" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
-
+(
CMake Error at BadByproduct.cmake:5 \(add_custom_command\):
- add_custom_command called with BYPRODUCTS containing a "<". This character
- is not allowed.
+ BYPRODUCTS containing a "#" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
-
+)+
CMake Error at BadByproduct.cmake:6 \(add_custom_command\):
- add_custom_command attempted to have a file
+ BYPRODUCTS path
.*RunCMake/add_custom_command/f
in a source directory as an output of custom command.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
+
+(
+CMake Error at BadByproduct.cmake:7 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:prop>
+
+ \$<TARGET_PROPERTY:prop> may only be used with binary targets. It may not
+ be used with add_custom_command or add_custom_target. Specify the target
+ to read a property from using the \$<TARGET_PROPERTY:tgt,prop> signature
+ instead.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+(
+CMake Error at BadByproduct.cmake:8 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<OUTPUT_CONFIG:h>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+(
+CMake Error at BadByproduct.cmake:9 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<COMMAND_CONFIG:i>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+
diff --git a/Tests/RunCMake/add_custom_command/BadByproduct.cmake b/Tests/RunCMake/add_custom_command/BadByproduct.cmake
index 91bca5220..cf00f5b85 100644
--- a/Tests/RunCMake/add_custom_command/BadByproduct.cmake
+++ b/Tests/RunCMake/add_custom_command/BadByproduct.cmake
@@ -4,3 +4,6 @@ add_custom_command(OUTPUT b BYPRODUCTS "a<")
add_custom_command(OUTPUT c BYPRODUCTS "a>")
add_custom_command(OUTPUT d BYPRODUCTS "$<CONFIG>/#")
add_custom_command(OUTPUT e BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/f)
+add_custom_command(OUTPUT f BYPRODUCTS "$<TARGET_PROPERTY:prop>")
+add_custom_command(OUTPUT h BYPRODUCTS "$<OUTPUT_CONFIG:h>")
+add_custom_command(OUTPUT i BYPRODUCTS "$<COMMAND_CONFIG:i>")
diff --git a/Tests/RunCMake/add_custom_command/BadCommand-result.txt b/Tests/RunCMake/add_custom_command/BadCommand-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadCommand-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/BadCommand-stderr.txt b/Tests/RunCMake/add_custom_command/BadCommand-stderr.txt
new file mode 100644
index 000000000..470afd6a3
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadCommand-stderr.txt
@@ -0,0 +1,21 @@
+(CMake Error at BadCommand.cmake:1 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<OUTPUT_CONFIG:a>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+)+(CMake Error at BadCommand.cmake:2 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<COMMAND_CONFIG:b>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+)+
diff --git a/Tests/RunCMake/add_custom_command/BadCommand.cmake b/Tests/RunCMake/add_custom_command/BadCommand.cmake
new file mode 100644
index 000000000..8c9c3f90e
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadCommand.cmake
@@ -0,0 +1,3 @@
+add_custom_command(OUTPUT "a" COMMAND "$<1:$<OUTPUT_CONFIG:a>>")
+add_custom_command(OUTPUT "b" COMMAND "$<1:$<COMMAND_CONFIG:b>>")
+add_custom_target(drive DEPENDS "a" "b")
diff --git a/Tests/RunCMake/add_custom_command/BadOutput-stderr.txt b/Tests/RunCMake/add_custom_command/BadOutput-stderr.txt
index 731e58d03..2e43568d4 100644
--- a/Tests/RunCMake/add_custom_command/BadOutput-stderr.txt
+++ b/Tests/RunCMake/add_custom_command/BadOutput-stderr.txt
@@ -1,36 +1,67 @@
CMake Error at BadOutput.cmake:2 \(add_custom_command\):
- add_custom_command called with OUTPUT containing a "#". This character is
- not allowed.
+ OUTPUT containing a "#" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error at BadOutput.cmake:3 \(add_custom_command\):
- add_custom_command called with OUTPUT containing a "<". This character is
- not allowed.
+ OUTPUT containing a "<" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error at BadOutput.cmake:4 \(add_custom_command\):
- add_custom_command called with OUTPUT containing a ">". This character is
- not allowed.
+ OUTPUT containing a ">" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
-
+(
CMake Error at BadOutput.cmake:5 \(add_custom_command\):
- add_custom_command called with OUTPUT containing a "<". This character is
- not allowed.
+ OUTPUT containing a "#" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
-
+)+
CMake Error at BadOutput.cmake:6 \(add_custom_command\):
- add_custom_command attempted to have a file
+ OUTPUT path
.*RunCMake/add_custom_command/e
in a source directory as an output of custom command.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
+
+(
+CMake Error at BadOutput.cmake:7 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:prop>
+
+ \$<TARGET_PROPERTY:prop> may only be used with binary targets. It may not
+ be used with add_custom_command or add_custom_target. Specify the target
+ to read a property from using the \$<TARGET_PROPERTY:tgt,prop> signature
+ instead.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+(
+CMake Error at BadOutput.cmake:8 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<OUTPUT_CONFIG:h>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+(
+CMake Error at BadOutput.cmake:9 \(add_custom_command\):
+ Error evaluating generator expression:
+
+ \$<COMMAND_CONFIG:i>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+
diff --git a/Tests/RunCMake/add_custom_command/BadOutput.cmake b/Tests/RunCMake/add_custom_command/BadOutput.cmake
index 6875fe966..f04bdd16a 100644
--- a/Tests/RunCMake/add_custom_command/BadOutput.cmake
+++ b/Tests/RunCMake/add_custom_command/BadOutput.cmake
@@ -4,3 +4,6 @@ add_custom_command(OUTPUT "a<" COMMAND b)
add_custom_command(OUTPUT "a>" COMMAND c)
add_custom_command(OUTPUT "$<CONFIG>/#" COMMAND d)
add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/e COMMAND f)
+add_custom_command(OUTPUT "$<TARGET_PROPERTY:prop>" COMMAND g)
+add_custom_command(OUTPUT "$<OUTPUT_CONFIG:h>" COMMAND h)
+add_custom_command(OUTPUT "$<COMMAND_CONFIG:i>" COMMAND i)
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index aac085dc1..9c59b4b75 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -6,6 +6,7 @@ run_cmake(AppendNotOutput)
run_cmake(BadArgument)
run_cmake(BadByproduct)
run_cmake(BadOutput)
+run_cmake(BadCommand)
run_cmake(GeneratedProperty)
run_cmake(LiteralQuotes)
run_cmake(NoArguments)
diff --git a/Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt b/Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt
index 0f58550a3..da9af49a0 100644
--- a/Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt
+++ b/Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt
@@ -1,36 +1,67 @@
CMake Error at BadByproduct.cmake:2 \(add_custom_target\):
- add_custom_target called with BYPRODUCTS containing a "#". This character
- is not allowed.
+ BYPRODUCTS containing a "#" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error at BadByproduct.cmake:3 \(add_custom_target\):
- add_custom_target called with BYPRODUCTS containing a "<". This character
- is not allowed.
+ BYPRODUCTS containing a "<" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error at BadByproduct.cmake:4 \(add_custom_target\):
- add_custom_target called with BYPRODUCTS containing a ">". This character
- is not allowed.
+ BYPRODUCTS containing a ">" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
-
+(
CMake Error at BadByproduct.cmake:5 \(add_custom_target\):
- add_custom_target called with BYPRODUCTS containing a "<". This character
- is not allowed.
+ BYPRODUCTS containing a "#" is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
-
+)+
CMake Error at BadByproduct.cmake:6 \(add_custom_target\):
- add_custom_target attempted to have a file
+ BYPRODUCTS path
.*RunCMake/add_custom_target/j
in a source directory as an output of custom command.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
+
+(
+CMake Error at BadByproduct.cmake:7 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:prop>
+
+ \$<TARGET_PROPERTY:prop> may only be used with binary targets. It may not
+ be used with add_custom_command or add_custom_target. Specify the target
+ to read a property from using the \$<TARGET_PROPERTY:tgt,prop> signature
+ instead.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+(
+CMake Error at BadByproduct.cmake:8 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<OUTPUT_CONFIG:n>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+(
+CMake Error at BadByproduct.cmake:9 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<COMMAND_CONFIG:p>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+)+
diff --git a/Tests/RunCMake/add_custom_target/BadByproduct.cmake b/Tests/RunCMake/add_custom_target/BadByproduct.cmake
index 963d6416b..c317b8354 100644
--- a/Tests/RunCMake/add_custom_target/BadByproduct.cmake
+++ b/Tests/RunCMake/add_custom_target/BadByproduct.cmake
@@ -4,3 +4,6 @@ add_custom_target(c BYPRODUCTS "a<" COMMAND d)
add_custom_target(e BYPRODUCTS "a>" COMMAND f)
add_custom_target(g BYPRODUCTS "$<CONFIG>/#" COMMAND h)
add_custom_target(i BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/j COMMAND k)
+add_custom_target(l BYPRODUCTS "$<TARGET_PROPERTY:prop>" COMMAND m)
+add_custom_target(n BYPRODUCTS "$<OUTPUT_CONFIG:n>" COMMAND o)
+add_custom_target(p BYPRODUCTS "$<COMMAND_CONFIG:p>" COMMAND q)
diff --git a/Tests/RunCMake/add_custom_target/BadCommand-result.txt b/Tests/RunCMake/add_custom_target/BadCommand-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/BadCommand-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_target/BadCommand-stderr.txt b/Tests/RunCMake/add_custom_target/BadCommand-stderr.txt
new file mode 100644
index 000000000..dfdf8f81a
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/BadCommand-stderr.txt
@@ -0,0 +1,21 @@
+(CMake Error at BadCommand.cmake:1 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<OUTPUT_CONFIG:a>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+)+(CMake Error at BadCommand.cmake:1 \(add_custom_target\):
+ Error evaluating generator expression:
+
+ \$<COMMAND_CONFIG:b>
+
+ Expression did not evaluate to a known generator expression
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+)+
diff --git a/Tests/RunCMake/add_custom_target/BadCommand.cmake b/Tests/RunCMake/add_custom_target/BadCommand.cmake
new file mode 100644
index 000000000..dadf0381c
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/BadCommand.cmake
@@ -0,0 +1,4 @@
+add_custom_target(drive
+ COMMAND "$<1:$<OUTPUT_CONFIG:a>>"
+ COMMAND "$<1:$<COMMAND_CONFIG:b>>"
+ )
diff --git a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
index f5d5dd2b5..22a9ed49e 100644
--- a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
@@ -1,6 +1,7 @@
include(RunCMake)
run_cmake(BadByproduct)
+run_cmake(BadCommand)
run_cmake(BadTargetName)
run_cmake(ByproductsNoCommand)
run_cmake(CommandExpandsEmpty)
diff --git a/Tests/RunCMake/add_library/CMP0073-stderr.txt b/Tests/RunCMake/add_library/CMP0073-stderr.txt
new file mode 100644
index 000000000..7f43fd740
--- /dev/null
+++ b/Tests/RunCMake/add_library/CMP0073-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0073.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0073 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/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-invalid-arg-result.txt b/Tests/RunCMake/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-invalid-arg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-invalid-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-no-arg-result.txt b/Tests/RunCMake/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-no-arg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/APPEND_STRING-OUTPUT_VARIABLE-no-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/APPEND_STRING-wrong-path-result.txt b/Tests/RunCMake/cmake_path/APPEND_STRING-wrong-path-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/APPEND_STRING-wrong-path-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/CONCAT.cmake b/Tests/RunCMake/cmake_path/APPEND_STRING.cmake
index 62b5eb001..ea5f2dd8c 100644
--- a/Tests/RunCMake/cmake_path/CONCAT.cmake
+++ b/Tests/RunCMake/cmake_path/APPEND_STRING.cmake
@@ -3,13 +3,13 @@ include ("${RunCMake_SOURCE_DIR}/check_errors.cmake")
unset (errors)
set (path "/a/b")
-cmake_path (CONCAT path "cd")
+cmake_path (APPEND_STRING path "cd")
if (NOT path STREQUAL "/a/bcd")
list (APPEND errors "'${path}' instead of 'a/bcd'")
endif()
set (path "/a/b")
-cmake_path (CONCAT path "cd" "ef" OUTPUT_VARIABLE output)
+cmake_path (APPEND_STRING path "cd" "ef" OUTPUT_VARIABLE output)
if (NOT path STREQUAL "/a/b")
list (APPEND errors "input changed unexpectedly")
endif()
@@ -17,4 +17,4 @@ if (NOT output STREQUAL "/a/bcdef")
list (APPEND errors "'${output}' instead of 'a/bcdef'")
endif()
-check_errors (CONCAT ${errors})
+check_errors (APPEND_STRING ${errors})
diff --git a/Tests/RunCMake/cmake_path/COMPARE.cmake b/Tests/RunCMake/cmake_path/COMPARE.cmake
index bc6b9b46c..ecf7c8270 100644
--- a/Tests/RunCMake/cmake_path/COMPARE.cmake
+++ b/Tests/RunCMake/cmake_path/COMPARE.cmake
@@ -2,19 +2,19 @@
include ("${RunCMake_SOURCE_DIR}/check_errors.cmake")
unset (errors)
-set (path "a///b/c")
-cmake_path(COMPARE path EQUAL "a/b/c" output)
+set(path "a///b/c")
+cmake_path(COMPARE "${path}" EQUAL "a/b/c" output)
if (NOT output)
list (APPEND errors "'${path}' not equal to 'a/b/c'")
endif()
set (path "a/b/d/../c")
-cmake_path(COMPARE path NOT_EQUAL "a/b/c" output)
+cmake_path(COMPARE "${path}" NOT_EQUAL "a/b/c" output)
if (NOT output)
list (APPEND errors "'${path}' equal to 'a/b/c'")
endif()
cmake_path(NORMAL_PATH path)
-cmake_path(COMPARE path EQUAL "a/b/c" output)
+cmake_path(COMPARE "${path}" EQUAL "a/b/c" output)
if (NOT output)
list (APPEND errors "'${path}' not equal to 'a/b/c'")
endif()
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-invalid-output-result.txt b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-invalid-output-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-invalid-output-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-missing-output-result.txt b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-missing-output-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-missing-output-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-unexpected-arg-result.txt b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-unexpected-arg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-unexpected-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-wrong-path-result.txt b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-wrong-path-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/GET-RELATIVE_PART-wrong-path-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/GET.cmake b/Tests/RunCMake/cmake_path/GET.cmake
index e68e65403..463bc471b 100644
--- a/Tests/RunCMake/cmake_path/GET.cmake
+++ b/Tests/RunCMake/cmake_path/GET.cmake
@@ -61,9 +61,9 @@ if (NOT output STREQUAL "cc.ext1")
list (APPEND errors "STEM LAST_ONLY returns bad data: ${output}")
endif()
-cmake_path(GET path RELATIVE_PATH output)
+cmake_path(GET path RELATIVE_PART output)
if (NOT output STREQUAL "aa/bb/cc.ext1.ext2")
- list (APPEND errors "RELATIVE_PATH returns bad data: ${output}")
+ list (APPEND errors "RELATIVE_PART returns bad data: ${output}")
endif()
cmake_path(GET path PARENT_PATH output)
@@ -112,9 +112,9 @@ if (NOT output STREQUAL "")
list (APPEND errors "STEM returns bad data: ${output}")
endif()
-cmake_path(GET path RELATIVE_PATH output)
+cmake_path(GET path RELATIVE_PART output)
if (NOT output STREQUAL path)
- list (APPEND errors "RELATIVE_PATH returns bad data: ${output}")
+ list (APPEND errors "RELATIVE_PART returns bad data: ${output}")
endif()
cmake_path(GET path PARENT_PATH output)
@@ -173,9 +173,9 @@ if (NOT output STREQUAL "")
list (APPEND errors "STEM returns bad data: ${output}")
endif()
-cmake_path(GET path RELATIVE_PATH output)
+cmake_path(GET path RELATIVE_PART output)
if (NOT output STREQUAL "")
- list (APPEND errors "RELATIVE_PATH returns bad data: ${output}")
+ list (APPEND errors "RELATIVE_PART returns bad data: ${output}")
endif()
cmake_path(GET path PARENT_PATH output)
diff --git a/Tests/RunCMake/cmake_path/HASH.cmake b/Tests/RunCMake/cmake_path/HASH.cmake
index dfcf2b2a1..eb04f7f7e 100644
--- a/Tests/RunCMake/cmake_path/HASH.cmake
+++ b/Tests/RunCMake/cmake_path/HASH.cmake
@@ -14,11 +14,6 @@ set (path1 "a///b/c/../d")
cmake_path(HASH path1 hash1)
set (path2 "a/b////d")
cmake_path(HASH path2 hash2)
-if (hash1 STREQUAL hash2)
- list (APPEND errors "'hash values equal for '${path1}' and '${path2}'")
-endif()
-cmake_path(HASH path1 hash1 NORMALIZE)
-cmake_path(HASH path2 NORMALIZE hash2)
if (NOT hash1 STREQUAL hash2)
list (APPEND errors "'hash values not equal for '${path1}' and '${path2}'")
endif()
diff --git a/Tests/RunCMake/cmake_path/HAS_ITEM.cmake b/Tests/RunCMake/cmake_path/HAS_ITEM.cmake
index eb73bd5df..e76776ccc 100644
--- a/Tests/RunCMake/cmake_path/HAS_ITEM.cmake
+++ b/Tests/RunCMake/cmake_path/HAS_ITEM.cmake
@@ -96,14 +96,14 @@ if (output)
endif()
set (path "/a/b")
-cmake_path(HAS_RELATIVE_PATH path output)
+cmake_path(HAS_RELATIVE_PART path output)
if (NOT output)
- list (APPEND errors "RELATIVE_PATH: ${path} does not have relative path")
+ list (APPEND errors "RELATIVE_PART: ${path} does not have relative part")
endif()
set (path "/")
-cmake_path(HAS_RELATIVE_PATH path output)
+cmake_path(HAS_RELATIVE_PART path output)
if (output)
- list (APPEND errors "RELATIVE_PATH: ${path} has relative path")
+ list (APPEND errors "RELATIVE_PART: ${path} has relative part")
endif()
set (path "/a/b")
@@ -180,21 +180,21 @@ if (WIN32)
endif()
set (path "c:/a/b")
- cmake_path(HAS_RELATIVE_PATH path output)
+ cmake_path(HAS_RELATIVE_PART path output)
if (NOT output)
- list (APPEND errors "RELATIVE_PATH: ${path} does not have relative path")
+ list (APPEND errors "RELATIVE_PART: ${path} does not have relative part")
endif()
set (path "c:a/b")
- cmake_path(HAS_RELATIVE_PATH path output)
+ cmake_path(HAS_RELATIVE_PART path output)
if (NOT output)
- list (APPEND errors "RELATIVE_PATH: ${path} does not have relative path")
+ list (APPEND errors "RELATIVE_PART: ${path} does not have relative part")
endif()
set (path "//host/b")
- cmake_path(HAS_RELATIVE_PATH path output)
+ cmake_path(HAS_RELATIVE_PART path output)
if (NOT output)
- list (APPEND errors "RELATIVE_PATH: ${path} does not have relative path")
+ list (APPEND errors "RELATIVE_PART: ${path} does not have relative part")
endif()
set (path "c:/a/b")
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-invalid-output-result.txt b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-invalid-output-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-invalid-output-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-missing-output-result.txt b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-missing-output-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-missing-output-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-unexpected-arg-result.txt b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-unexpected-arg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-unexpected-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-wrong-path-result.txt b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-wrong-path-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/HAS_RELATIVE_PART-wrong-path-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/IS_PREFIX.cmake b/Tests/RunCMake/cmake_path/IS_PREFIX.cmake
index 53da93bc9..9160dab11 100644
--- a/Tests/RunCMake/cmake_path/IS_PREFIX.cmake
+++ b/Tests/RunCMake/cmake_path/IS_PREFIX.cmake
@@ -18,5 +18,10 @@ if (NOT output)
list (APPEND errors "'${path} is not prefix of 'a/b/d/e'")
endif()
+set(path "/a/b/..")
+cmake_path(IS_PREFIX path "/a/c/../b" NORMALIZE output)
+if (NOT output)
+ list (APPEND errors "'${path} is not prefix of '/a/c/../b'")
+endif()
check_errors (IS_PREFIX ${errors})
diff --git a/Tests/RunCMake/cmake_path/PROXIMATE_PATH.cmake b/Tests/RunCMake/cmake_path/PROXIMATE_PATH.cmake
deleted file mode 100644
index ad2337764..000000000
--- a/Tests/RunCMake/cmake_path/PROXIMATE_PATH.cmake
+++ /dev/null
@@ -1,41 +0,0 @@
-
-include ("${RunCMake_SOURCE_DIR}/check_errors.cmake")
-unset (errors)
-
-if (WIN32)
- set (path "c:/a/d")
- cmake_path(PROXIMATE_PATH path BASE_DIRECTORY "e/d/c")
- if (NOT path STREQUAL "c:/a/d")
- list (APPEND errors "'${path}' instead of 'c:/a/d'")
- endif()
-else()
- set (path "/a/d")
- cmake_path(PROXIMATE_PATH path BASE_DIRECTORY "e/d/c")
- if (NOT path STREQUAL "/a/d")
- list (APPEND errors "'${path}' instead of '/a/d'")
- endif()
-endif()
-
-set (path "/a/d")
-cmake_path(PROXIMATE_PATH path BASE_DIRECTORY "/a/b/c" OUTPUT_VARIABLE output)
-if (NOT path STREQUAL "/a/d")
- list (APPEND errors "input changed unexpectedly")
-endif()
-if (NOT output STREQUAL "../../d")
- list (APPEND errors "'${output}' instead of '../../d'")
-endif()
-
-set (path "${CMAKE_CURRENT_SOURCE_DIR}/a/d")
-cmake_path(PROXIMATE_PATH path)
-if (NOT path STREQUAL "a/d")
- list (APPEND errors "'${path}' instead of 'a/d'")
-endif()
-
-set (path "a/b/c")
-cmake_path(PROXIMATE_PATH path)
-if (NOT path STREQUAL "a/b/c")
- list (APPEND errors "'${path}' instead of 'a/b/c'")
-endif()
-
-
-check_errors (PROXIMATE_PATH ${errors})
diff --git a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
index ca9cba66a..991f46b09 100644
--- a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
@@ -7,25 +7,20 @@ set (RunCMake-stderr-file "wrong-path-stderr.txt")
### GET sub-command
foreach (subcommand IN ITEMS ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME EXTENSION
- STEM RELATIVE_PATH PARENT_PATH)
+ STEM RELATIVE_PART PARENT_PATH)
run_cmake_command (GET-${subcommand}-wrong-path "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=GET wrong_path ${subcommand} output" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
-### COMPARE sub-command
-foreach (subcommand IN ITEMS EQUAL NOT_EQUAL)
- run_cmake_command (COMPARE-${subcommand}-wrong-path "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=COMPARE wrong_path ${subcommand} path2 output" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
-endforeach()
-
-foreach (command IN ITEMS CONCAT REMOVE_FILENAME REPLACE_FILENAME
+foreach (command IN ITEMS APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME
REMOVE_EXTENSION REPLACE_EXTENSION NORMAL_PATH
- RELATIVE_PATH PROXIMATE_PATH ABSOLUTE_PATH)
+ RELATIVE_PATH ABSOLUTE_PATH)
run_cmake_command (${command}-wrong-path "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} wrong_path" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
foreach (command IN ITEMS NATIVE_PATH
HAS_ROOT_NAME HAS_ROOT_DIRECTORY HAS_ROOT_PATH
HAS_FILENAME HAS_EXTENSION HAS_STEM
- HAS_RELATIVE_PATH HAS_PARENT_PATH
+ HAS_RELATIVE_PART HAS_PARENT_PATH
IS_ABSOLUTE IS_RELATIVE IS_PREFIX HASH)
if (command STREQUAL "IS_PREFIX")
set (extra_args path2)
@@ -41,7 +36,7 @@ set (RunCMake-stderr-file "missing-output-stderr.txt")
### GET sub-command
foreach (subcommand IN ITEMS ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME EXTENSION
- STEM RELATIVE_PATH PARENT_PATH)
+ STEM RELATIVE_PART PARENT_PATH)
run_cmake_command (GET-${subcommand}-missing-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=GET path ${subcommand}" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
@@ -55,10 +50,10 @@ foreach (subcommand IN ITEMS EQUAL NOT_EQUAL)
run_cmake_command (COMPARE-${subcommand}-missing-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=COMPARE path ${subcommand} path2" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
-foreach (command IN ITEMS CMAKE_PATH NATIVE_PATH
+foreach (command IN ITEMS SET NATIVE_PATH
HAS_ROOT_NAME HAS_ROOT_DIRECTORY HAS_ROOT_PATH
HAS_FILENAME HAS_EXTENSION HAS_STEM
- HAS_RELATIVE_PATH HAS_PARENT_PATH
+ HAS_RELATIVE_PART HAS_PARENT_PATH
IS_ABSOLUTE IS_RELATIVE IS_PREFIX HASH)
if (command STREQUAL "IS_PREFIX")
set (extra_args path2)
@@ -72,9 +67,9 @@ endforeach()
## OUTPUT_VARIABLE without argument
set (RunCMake-stderr-file "OUTPUT_VARIABLE-no-arg-stderr.txt")
-foreach (command IN ITEMS APPEND CONCAT REMOVE_FILENAME REPLACE_FILENAME
+foreach (command IN ITEMS APPEND APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME
REMOVE_EXTENSION REPLACE_EXTENSION NORMAL_PATH
- RELATIVE_PATH PROXIMATE_PATH ABSOLUTE_PATH)
+ RELATIVE_PATH ABSOLUTE_PATH)
run_cmake_command (${command}-OUTPUT_VARIABLE-no-arg "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path OUTPUT_VARIABLE" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
@@ -84,7 +79,7 @@ set (RunCMake-stderr-file "invalid-output-var-stderr.txt")
### GET sub-command
foreach (subcommand IN ITEMS ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME EXTENSION
- STEM RELATIVE_PATH PARENT_PATH)
+ STEM RELATIVE_PART PARENT_PATH)
run_cmake_command (GET-${subcommand}-invalid-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=GET path ${subcommand}" -DCHECK_INVALID_OUTPUT=ON -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
@@ -98,10 +93,10 @@ foreach (subcommand IN ITEMS EQUAL NOT_EQUAL)
run_cmake_command (COMPARE-${subcommand}-invalid-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=COMPARE path ${subcommand} path2" -DCHECK_INVALID_OUTPUT=ON -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
-foreach (command IN ITEMS CMAKE_PATH NATIVE_PATH
+foreach (command IN ITEMS NATIVE_PATH
HAS_ROOT_NAME HAS_ROOT_DIRECTORY HAS_ROOT_PATH
HAS_FILENAME HAS_EXTENSION HAS_STEM
- HAS_RELATIVE_PATH HAS_PARENT_PATH
+ HAS_RELATIVE_PART HAS_PARENT_PATH
IS_ABSOLUTE IS_RELATIVE IS_PREFIX HASH)
if (command STREQUAL "IS_PREFIX")
set (extra_args path2)
@@ -111,9 +106,9 @@ foreach (command IN ITEMS CMAKE_PATH NATIVE_PATH
run_cmake_command (${command}-invalid-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path ${extra_args}" -DCHECK_INVALID_OUTPUT=ON -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
-foreach (command IN ITEMS APPEND CONCAT REMOVE_FILENAME REPLACE_FILENAME
+foreach (command IN ITEMS APPEND APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME
REMOVE_EXTENSION REPLACE_EXTENSION NORMAL_PATH
- RELATIVE_PATH PROXIMATE_PATH ABSOLUTE_PATH)
+ RELATIVE_PATH ABSOLUTE_PATH)
run_cmake_command (${command}-OUTPUT_VARIABLE-invalid-arg "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path OUTPUT_VARIABLE" -DCHECK_INVALID_OUTPUT=ON -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
@@ -123,7 +118,7 @@ set (RunCMake-stderr-file "unexpected-arg-stderr.txt")
### GET sub-command
foreach (subcommand IN ITEMS ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME EXTENSION
- STEM RELATIVE_PATH PARENT_PATH)
+ STEM RELATIVE_PART PARENT_PATH)
if (subcommand STREQUAL "EXTENSION" OR subcommand STREQUAL "STEM")
set (extra_args LAST_ONLY)
else()
@@ -139,7 +134,7 @@ endforeach()
foreach (command IN ITEMS REMOVE_FILENAME REPLACE_FILENAME
REMOVE_EXTENSION REPLACE_EXTENSION NORMAL_PATH
- RELATIVE_PATH PROXIMATE_PATH ABSOLUTE_PATH)
+ RELATIVE_PATH ABSOLUTE_PATH)
if (command STREQUAL "REPLACE_FILENAME" OR command STREQUAL "REPLACE_EXTENSION")
set (extra_args input)
else()
@@ -148,10 +143,10 @@ foreach (command IN ITEMS REMOVE_FILENAME REPLACE_FILENAME
run_cmake_command (${command}-unexpected-arg "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path ${extra_args} unexpected" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
endforeach()
-foreach (command IN ITEMS CMAKE_PATH NATIVE_PATH
+foreach (command IN ITEMS SET NATIVE_PATH
HAS_ROOT_NAME HAS_ROOT_DIRECTORY HAS_ROOT_PATH
HAS_FILENAME HAS_EXTENSION HAS_STEM
- HAS_RELATIVE_PATH HAS_PARENT_PATH
+ HAS_RELATIVE_PART HAS_PARENT_PATH
IS_ABSOLUTE IS_RELATIVE IS_PREFIX
HASH)
if (command STREQUAL "IS_PREFIX")
@@ -170,17 +165,16 @@ run_cmake(COMPARE-wrong-operator)
set (RunCMake_TEST_OPTIONS "-DRunCMake_SOURCE_DIR=${RunCMake_SOURCE_DIR}")
run_cmake(GET)
+run_cmake(SET)
run_cmake(APPEND)
-run_cmake(CONCAT)
+run_cmake(APPEND_STRING)
run_cmake(REMOVE_FILENAME)
run_cmake(REPLACE_FILENAME)
run_cmake(REMOVE_EXTENSION)
run_cmake(REPLACE_EXTENSION)
run_cmake(NORMAL_PATH)
run_cmake(RELATIVE_PATH)
-run_cmake(PROXIMATE_PATH)
run_cmake(ABSOLUTE_PATH)
-run_cmake(CMAKE_PATH)
run_cmake(NATIVE_PATH)
run_cmake(CONVERT)
run_cmake(COMPARE)
diff --git a/Tests/RunCMake/cmake_path/SET-missing-output-result.txt b/Tests/RunCMake/cmake_path/SET-missing-output-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/SET-missing-output-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/SET-unexpected-arg-result.txt b/Tests/RunCMake/cmake_path/SET-unexpected-arg-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/SET-unexpected-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_path/CMAKE_PATH.cmake b/Tests/RunCMake/cmake_path/SET.cmake
index b9320f365..445783ed8 100644
--- a/Tests/RunCMake/cmake_path/CMAKE_PATH.cmake
+++ b/Tests/RunCMake/cmake_path/SET.cmake
@@ -2,42 +2,42 @@
include ("${RunCMake_SOURCE_DIR}/check_errors.cmake")
unset (errors)
-cmake_path(CMAKE_PATH path "/x/y/z/../../a/d")
+cmake_path(SET path "/x/y/z/../../a/d")
if (NOT path STREQUAL "/x/y/z/../../a/d")
list (APPEND errors "'${path}' instead of '/x/y/z/../../a/d'")
endif()
-cmake_path(CMAKE_PATH path NORMALIZE "/x/y/z/../../a/d")
+cmake_path(SET path NORMALIZE "/x/y/z/../../a/d")
if (NOT path STREQUAL "/x/a/d")
list (APPEND errors "'${path}' instead of '/x/a/d'")
endif()
if (WIN32)
- cmake_path(CMAKE_PATH path "/x\\y/z\\..\\../a/d")
+ cmake_path(SET path "/x\\y/z\\..\\../a/d")
if (NOT path STREQUAL "/x/y/z/../../a/d")
list (APPEND errors "'${path}' instead of '/x/y/z/../../a/d'")
endif()
- cmake_path(CMAKE_PATH path NORMALIZE "/x\\y/z\\..\\../a/d")
+ cmake_path(SET path NORMALIZE "/x\\y/z\\..\\../a/d")
if (NOT path STREQUAL "/x/a/d")
list (APPEND errors "'${path}' instead of '/x/a/d'")
endif()
- cmake_path(CMAKE_PATH path "//?/c:/x\\y/z\\..\\../a/d")
+ cmake_path(SET path "//?/c:/x\\y/z\\..\\../a/d")
if (NOT path STREQUAL "c:/x/y/z/../../a/d")
list (APPEND errors "'${path}' instead of 'c:/x/y/z/../../a/d'")
endif()
- cmake_path(CMAKE_PATH path NORMALIZE "//?/c:/x\\y/z\\..\\../a/d")
+ cmake_path(SET path NORMALIZE "//?/c:/x\\y/z\\..\\../a/d")
if (NOT path STREQUAL "c:/x/a/d")
list (APPEND errors "'${path}' instead of 'c:/x/a/d'")
endif()
- cmake_path(CMAKE_PATH path "\\\\?\\UNC/host/x\\y/z\\..\\../a/d")
+ cmake_path(SET path "\\\\?\\UNC/host/x\\y/z\\..\\../a/d")
if (NOT path STREQUAL "//host/x/y/z/../../a/d")
list (APPEND errors "'${path}' instead of '//host/x/y/z/../../a/d'")
endif()
- cmake_path(CMAKE_PATH path NORMALIZE "\\\\?\\UNC\\host/x\\y/z\\..\\../a/d")
+ cmake_path(SET path NORMALIZE "\\\\?\\UNC\\host/x\\y/z\\..\\../a/d")
if (NOT path STREQUAL "//host/x/a/d")
list (APPEND errors "'${path}' instead of '//host/x/a/d'")
endif()
endif()
-check_errors (CMAKE_PATH ${errors})
+check_errors (SET ${errors})
diff --git a/Tests/RunCMake/configure_file/RunCMakeTest.cmake b/Tests/RunCMake/configure_file/RunCMakeTest.cmake
index 71694fb0b..0a2e3f9fb 100644
--- a/Tests/RunCMake/configure_file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/configure_file/RunCMakeTest.cmake
@@ -16,6 +16,13 @@ run_cmake(NewLineStyle-WrongArg)
run_cmake(NewLineStyle-ValidArg)
run_cmake(NewLineStyle-COPYONLY)
run_cmake(NoSourcePermissions)
+run_cmake(SourcePermissionsInvalidArg-1)
+run_cmake(SourcePermissionsInvalidArg-2)
+run_cmake(SourcePermissionsInvalidArg-3)
+run_cmake(SourcePermissionsInvalidArg-4)
+run_cmake(SourcePermissionsInvalidArg-5)
+run_cmake(UseSourcePermissions)
+run_cmake(SourcePermissions)
if(RunCMake_GENERATOR MATCHES "Make")
# Use a single build tree for a few tests without cleaning.
diff --git a/Tests/RunCMake/configure_file/SourcePermissions-result.txt b/Tests/RunCMake/configure_file/SourcePermissions-result.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissions-result.txt
diff --git a/Tests/RunCMake/configure_file/SourcePermissions-stderr.txt b/Tests/RunCMake/configure_file/SourcePermissions-stderr.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissions-stderr.txt
diff --git a/Tests/RunCMake/configure_file/SourcePermissions.cmake b/Tests/RunCMake/configure_file/SourcePermissions.cmake
new file mode 100644
index 000000000..50330fc42
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissions.cmake
@@ -0,0 +1,34 @@
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt
+ FILE_PERMISSIONS
+ OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ
+)
+
+if (UNIX)
+ find_program(STAT_EXECUTABLE NAMES stat)
+ if(NOT STAT_EXECUTABLE)
+ return()
+ endif()
+
+ if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt"
+ OUTPUT_VARIABLE output
+ )
+ elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt"
+ OUTPUT_VARIABLE output
+ )
+ else()
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt"
+ OUTPUT_VARIABLE output
+ )
+ endif()
+
+ if (NOT output EQUAL "554")
+ message(FATAL_ERROR "configure file has different permissions than "
+ "desired, generated permissions: ${output}")
+ endif()
+
+endif()
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-result.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-stderr.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-stderr.txt
new file mode 100644
index 000000000..d483d342b
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at SourcePermissionsInvalidArg-1.cmake:1 \(configure_file\):
+ configure_file given both USE_SOURCE_PERMISSIONS and NO_SOURCE_PERMISSIONS.
+ Only one option allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1.cmake b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1.cmake
new file mode 100644
index 000000000..49698808d
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-1.cmake
@@ -0,0 +1,5 @@
+configure_file(sourcefile.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+ NO_SOURCE_PERMISSIONS
+ USE_SOURCE_PERMISSIONS
+)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-result.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-stderr.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-stderr.txt
new file mode 100644
index 000000000..2fcfe58f6
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at SourcePermissionsInvalidArg-2.cmake:1 \(configure_file\):
+ configure_file given both FILE_PERMISSIONS and NO_SOURCE_PERMISSIONS. Only
+ one option allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2.cmake b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2.cmake
new file mode 100644
index 000000000..8a3fb8763
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-2.cmake
@@ -0,0 +1,5 @@
+configure_file(sourcefile.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+ NO_SOURCE_PERMISSIONS
+ FILE_PERMISSIONS OWNER_READ
+)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-result.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-stderr.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-stderr.txt
new file mode 100644
index 000000000..29fae1ba1
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at SourcePermissionsInvalidArg-3.cmake:1 \(configure_file\):
+ configure_file given both FILE_PERMISSIONS and USE_SOURCE_PERMISSIONS.
+ Only one option allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3.cmake b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3.cmake
new file mode 100644
index 000000000..78ecb0f10
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-3.cmake
@@ -0,0 +1,5 @@
+configure_file(sourcefile.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+ USE_SOURCE_PERMISSIONS
+ FILE_PERMISSIONS OWNER_READ
+)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-result.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-stderr.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-stderr.txt
new file mode 100644
index 000000000..7d477cb8b
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourcePermissionsInvalidArg-4.cmake:1 \(configure_file\):
+ configure_file given FILE_PERMISSIONS without any options.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4.cmake b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4.cmake
new file mode 100644
index 000000000..308b455aa
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-4.cmake
@@ -0,0 +1,4 @@
+configure_file(sourcefile.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/sourcefile.txt
+ FILE_PERMISSIONS
+)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-result.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-stderr.txt b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-stderr.txt
new file mode 100644
index 000000000..7cab120ae
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourcePermissionsInvalidArg-5.cmake:1 \(configure_file\):
+ configure_file given invalid permission "OWNER_RX","GROUP_RWX".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5.cmake b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5.cmake
new file mode 100644
index 000000000..15c6f9a5e
--- /dev/null
+++ b/Tests/RunCMake/configure_file/SourcePermissionsInvalidArg-5.cmake
@@ -0,0 +1,6 @@
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/sourcefile-source-permissions.txt
+ FILE_PERMISSIONS
+ OWNER_READ OWNER_RX
+ GROUP_RWX
+)
diff --git a/Tests/RunCMake/configure_file/UseSourcePermissions.cmake b/Tests/RunCMake/configure_file/UseSourcePermissions.cmake
new file mode 100644
index 000000000..f7aedd156
--- /dev/null
+++ b/Tests/RunCMake/configure_file/UseSourcePermissions.cmake
@@ -0,0 +1,40 @@
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt
+ USE_SOURCE_PERMISSIONS
+)
+
+if (UNIX)
+ find_program(STAT_EXECUTABLE NAMES stat)
+ if(NOT STAT_EXECUTABLE)
+ return()
+ endif()
+
+ if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt"
+ OUTPUT_VARIABLE output1
+ )
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %Lp "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt"
+ OUTPUT_VARIABLE output2
+ )
+ elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt"
+ OUTPUT_VARIABLE output1
+ )
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -f %A "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt"
+ OUTPUT_VARIABLE output2
+ )
+ else()
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${CMAKE_CURRENT_SOURCE_DIR}/sourcefile.txt"
+ OUTPUT_VARIABLE output1
+ )
+ execute_process(COMMAND "${STAT_EXECUTABLE}" -c %a "${CMAKE_CURRENT_BINARY_DIR}/sourcefile-use-source-permissions.txt"
+ OUTPUT_VARIABLE output2
+ )
+ endif()
+
+ if (NOT output1 EQUAL output2)
+ message(FATAL_ERROR "configure file has different permissions source "
+ "permissions: ${output1} generated permissions: ${output2}")
+ endif()
+
+endif()
diff --git a/Tests/RunCMake/configure_file/sourcefile.txt b/Tests/RunCMake/configure_file/sourcefile.txt
new file mode 100644
index 000000000..22968080d
--- /dev/null
+++ b/Tests/RunCMake/configure_file/sourcefile.txt
@@ -0,0 +1 @@
+an empty file
diff --git a/Tests/RunCMake/ctest_submit/CTestConfig.cmake.in b/Tests/RunCMake/ctest_submit/CTestConfig.cmake.in
index 140e4be35..c35397cb8 100644
--- a/Tests/RunCMake/ctest_submit/CTestConfig.cmake.in
+++ b/Tests/RunCMake/ctest_submit/CTestConfig.cmake.in
@@ -3,3 +3,7 @@
# so that any ctest_submit calls fail with an error message.
set(CTEST_DROP_METHOD "@CASE_DROP_METHOD@")
set(CTEST_DROP_SITE "@CASE_DROP_SITE@")
+
+# do not use proxy for lookup of invalid site (DNS failure by proxy looks
+# different than DNS failure without proxy)
+set(ENV{no_proxy} "$ENV{no_proxy},@CASE_DROP_SITE@")
diff --git a/Tests/CMakeTests/ELFTest.cmake.in b/Tests/RunCMake/file-RPATH/Common.cmake
index 85c2360d3..cc1efb533 100644
--- a/Tests/CMakeTests/ELFTest.cmake.in
+++ b/Tests/RunCMake/file-RPATH/Common.cmake
@@ -1,15 +1,6 @@
-set(names
- elf32lsb.bin
- elf32msb.bin
- elf64lsb.bin
- elf64msb.bin
- )
-
# Prepare binaries on which to operate.
-set(in "@CMAKE_CURRENT_SOURCE_DIR@/ELF")
-set(out "@CMAKE_CURRENT_BINARY_DIR@/ELF-Out")
-file(REMOVE_RECURSE "${out}")
-file(MAKE_DIRECTORY "${out}")
+set(in "${CMAKE_CURRENT_LIST_DIR}/${format}")
+set(out "${CMAKE_CURRENT_BINARY_DIR}")
foreach(f ${names})
file(COPY ${in}/${f} DESTINATION ${out} NO_SOURCE_PERMISSIONS)
list(APPEND files "${out}/${f}")
diff --git a/Tests/RunCMake/file-RPATH/ELF.cmake b/Tests/RunCMake/file-RPATH/ELF.cmake
new file mode 100644
index 000000000..558b2e264
--- /dev/null
+++ b/Tests/RunCMake/file-RPATH/ELF.cmake
@@ -0,0 +1,9 @@
+set(names
+ elf32lsb.bin
+ elf32msb.bin
+ elf64lsb.bin
+ elf64msb.bin
+ )
+set(format ELF)
+
+include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
diff --git a/Tests/CMakeTests/ELF/elf32lsb.bin b/Tests/RunCMake/file-RPATH/ELF/elf32lsb.bin
index 803ac43f3..803ac43f3 100644..100755
--- a/Tests/CMakeTests/ELF/elf32lsb.bin
+++ b/Tests/RunCMake/file-RPATH/ELF/elf32lsb.bin
Binary files differ
diff --git a/Tests/CMakeTests/ELF/elf32msb.bin b/Tests/RunCMake/file-RPATH/ELF/elf32msb.bin
index d04aaf76c..d04aaf76c 100644..100755
--- a/Tests/CMakeTests/ELF/elf32msb.bin
+++ b/Tests/RunCMake/file-RPATH/ELF/elf32msb.bin
Binary files differ
diff --git a/Tests/CMakeTests/ELF/elf64lsb.bin b/Tests/RunCMake/file-RPATH/ELF/elf64lsb.bin
index a21e3eaa6..a21e3eaa6 100644..100755
--- a/Tests/CMakeTests/ELF/elf64lsb.bin
+++ b/Tests/RunCMake/file-RPATH/ELF/elf64lsb.bin
Binary files differ
diff --git a/Tests/CMakeTests/ELF/elf64msb.bin b/Tests/RunCMake/file-RPATH/ELF/elf64msb.bin
index bbe255189..bbe255189 100644..100755
--- a/Tests/CMakeTests/ELF/elf64msb.bin
+++ b/Tests/RunCMake/file-RPATH/ELF/elf64msb.bin
Binary files differ
diff --git a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake
new file mode 100644
index 000000000..eb7b49730
--- /dev/null
+++ b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake
@@ -0,0 +1,9 @@
+include(RunCMake)
+
+if(HAVE_ELF_H)
+ run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+ run_cmake_command(XCOFF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/XCOFF.cmake)
+endif()
diff --git a/Tests/RunCMake/file-RPATH/XCOFF.cmake b/Tests/RunCMake/file-RPATH/XCOFF.cmake
new file mode 100644
index 000000000..b5709208a
--- /dev/null
+++ b/Tests/RunCMake/file-RPATH/XCOFF.cmake
@@ -0,0 +1,7 @@
+set(names
+ xcoff32.bin
+ xcoff64.bin
+ )
+set(format XCOFF)
+
+include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
diff --git a/Tests/RunCMake/file-RPATH/XCOFF/xcoff32.bin b/Tests/RunCMake/file-RPATH/XCOFF/xcoff32.bin
new file mode 100644
index 000000000..2d8d96173
--- /dev/null
+++ b/Tests/RunCMake/file-RPATH/XCOFF/xcoff32.bin
Binary files differ
diff --git a/Tests/RunCMake/file-RPATH/XCOFF/xcoff64.bin b/Tests/RunCMake/file-RPATH/XCOFF/xcoff64.bin
new file mode 100644
index 000000000..bb5f5a70c
--- /dev/null
+++ b/Tests/RunCMake/file-RPATH/XCOFF/xcoff64.bin
Binary files differ
diff --git a/Tests/RunCMake/get_property/RunCMakeTest.cmake b/Tests/RunCMake/get_property/RunCMakeTest.cmake
index c4ee53d1e..2143fa2d8 100644
--- a/Tests/RunCMake/get_property/RunCMakeTest.cmake
+++ b/Tests/RunCMake/get_property/RunCMakeTest.cmake
@@ -2,6 +2,9 @@ include(RunCMake)
run_cmake(cache_properties)
run_cmake(directory_properties)
+run_cmake(get_directory_property_empty)
+run_cmake(get_directory_property_missing)
+run_cmake(get_directory_property_missingWithDir)
run_cmake(global_properties)
run_cmake(install_properties)
run_cmake(source_properties)
diff --git a/Tests/RunCMake/get_property/get_directory_property_empty-result.txt b/Tests/RunCMake/get_property/get_directory_property_empty-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_empty-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/get_property/get_directory_property_empty-stderr.txt b/Tests/RunCMake/get_property/get_directory_property_empty-stderr.txt
new file mode 100644
index 000000000..baa73f310
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_empty-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at get_directory_property_empty.cmake:1 \(get_directory_property\):
+ get_directory_property given empty string for the property name to get
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/get_property/get_directory_property_empty.cmake b/Tests/RunCMake/get_property/get_directory_property_empty.cmake
new file mode 100644
index 000000000..b49be1c4a
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_empty.cmake
@@ -0,0 +1 @@
+get_directory_property(outVar "")
diff --git a/Tests/RunCMake/get_property/get_directory_property_missing-result.txt b/Tests/RunCMake/get_property/get_directory_property_missing-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_missing-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/get_property/get_directory_property_missing-stderr.txt b/Tests/RunCMake/get_property/get_directory_property_missing-stderr.txt
new file mode 100644
index 000000000..e101c768d
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_missing-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at get_directory_property_missing.cmake:1 \(get_directory_property\):
+ get_directory_property called with incorrect number of arguments
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/get_property/get_directory_property_missing.cmake b/Tests/RunCMake/get_property/get_directory_property_missing.cmake
new file mode 100644
index 000000000..c28157eb9
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_missing.cmake
@@ -0,0 +1 @@
+get_directory_property(outVar)
diff --git a/Tests/RunCMake/get_property/get_directory_property_missingWithDir-result.txt b/Tests/RunCMake/get_property/get_directory_property_missingWithDir-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_missingWithDir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/get_property/get_directory_property_missingWithDir-stderr.txt b/Tests/RunCMake/get_property/get_directory_property_missingWithDir-stderr.txt
new file mode 100644
index 000000000..66deabbf6
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_missingWithDir-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at get_directory_property_missingWithDir.cmake:1 \(get_directory_property\):
+ get_directory_property called with incorrect number of arguments
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/get_property/get_directory_property_missingWithDir.cmake b/Tests/RunCMake/get_property/get_directory_property_missingWithDir.cmake
new file mode 100644
index 000000000..573e14abe
--- /dev/null
+++ b/Tests/RunCMake/get_property/get_directory_property_missingWithDir.cmake
@@ -0,0 +1 @@
+get_directory_property(outVar DIRECTORY .)
diff --git a/Tests/RunCMake/if/duplicate-deep-else-stderr.txt b/Tests/RunCMake/if/duplicate-deep-else-stderr.txt
index ac2335c05..ee886e07c 100644
--- a/Tests/RunCMake/if/duplicate-deep-else-stderr.txt
+++ b/Tests/RunCMake/if/duplicate-deep-else-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at duplicate-deep-else.cmake:[0-9]+ \(else\):
- A duplicate ELSE command was found inside an IF block.
+CMake Error at duplicate-deep-else\.cmake:[0-9]+ \(else\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt b/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt
index ba6765c82..60c8484c3 100644
--- a/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt
+++ b/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at duplicate-else-after-elseif.cmake:[0-9]+ \(else\):
- A duplicate ELSE command was found inside an IF block.
+CMake Error at duplicate-else-after-elseif\.cmake:[0-9]+ \(else\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/if/duplicate-else-stderr.txt b/Tests/RunCMake/if/duplicate-else-stderr.txt
index e0dd01f33..518c43f11 100644
--- a/Tests/RunCMake/if/duplicate-else-stderr.txt
+++ b/Tests/RunCMake/if/duplicate-else-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at duplicate-else.cmake:[0-9]+ \(else\):
- A duplicate ELSE command was found inside an IF block.
+CMake Error at duplicate-else\.cmake:[0-9]+ \(else\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/if/misplaced-elseif-stderr.txt b/Tests/RunCMake/if/misplaced-elseif-stderr.txt
index c4b0266c7..5138f11b4 100644
--- a/Tests/RunCMake/if/misplaced-elseif-stderr.txt
+++ b/Tests/RunCMake/if/misplaced-elseif-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at misplaced-elseif.cmake:[0-9]+ \(elseif\):
- An ELSEIF command was found after an ELSE command.
+CMake Error at misplaced-elseif\.cmake:[0-9]+ \(elseif\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/include/ExportExportInclude-stderr.txt b/Tests/RunCMake/include/ExportExportInclude-stderr.txt
index 70d013cfd..6d5c02f19 100644
--- a/Tests/RunCMake/include/ExportExportInclude-stderr.txt
+++ b/Tests/RunCMake/include/ExportExportInclude-stderr.txt
@@ -1,5 +1,5 @@
CMake Error at ExportExportInclude.cmake:6 \(include\):
- include could not find load file:
+ include could not find requested file:
.*/Tests/RunCMake/include/ExportExportInclude-build/theTargets.cmake
Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/include/IncludeIsDirectory-result.txt b/Tests/RunCMake/include/IncludeIsDirectory-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeIsDirectory-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include/IncludeIsDirectory-stderr.txt b/Tests/RunCMake/include/IncludeIsDirectory-stderr.txt
new file mode 100644
index 000000000..5735c2913
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeIsDirectory-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at IncludeIsDirectory.cmake:1 \(include\):
+ include requested file is a directory:
+
+ .*/Tests/RunCMake/include/IncludeIsDirectory-build
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/include/IncludeIsDirectory.cmake b/Tests/RunCMake/include/IncludeIsDirectory.cmake
new file mode 100644
index 000000000..74189e33d
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeIsDirectory.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_BINARY_DIR}")
diff --git a/Tests/RunCMake/include/IncludeMalformed-result.txt b/Tests/RunCMake/include/IncludeMalformed-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeMalformed-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include/IncludeMalformed-stderr.txt b/Tests/RunCMake/include/IncludeMalformed-stderr.txt
new file mode 100644
index 000000000..fc755495c
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeMalformed-stderr.txt
@@ -0,0 +1,13 @@
+CMake Error at malformedInclude.cmake:1:
+ Parse error. Function missing ending "\)". End of file reached.
+Call Stack \(most recent call first\):
+ IncludeMalformed.cmake:1 \(include\)
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at IncludeMalformed.cmake:1 \(include\):
+ include could not load requested file:
+
+ malformedInclude.cmake
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/include/IncludeMalformed.cmake b/Tests/RunCMake/include/IncludeMalformed.cmake
new file mode 100644
index 000000000..956014281
--- /dev/null
+++ b/Tests/RunCMake/include/IncludeMalformed.cmake
@@ -0,0 +1 @@
+include("malformedInclude.cmake")
diff --git a/Tests/RunCMake/include/RunCMakeTest.cmake b/Tests/RunCMake/include/RunCMakeTest.cmake
index bea7d5cc4..8fb720138 100644
--- a/Tests/RunCMake/include/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include/RunCMakeTest.cmake
@@ -5,3 +5,5 @@ run_cmake(EmptyStringOptional)
run_cmake(CMP0024-WARN)
run_cmake(CMP0024-NEW)
run_cmake(ExportExportInclude)
+run_cmake(IncludeIsDirectory)
+run_cmake(IncludeMalformed)
diff --git a/Tests/RunCMake/include/malformedInclude.cmake b/Tests/RunCMake/include/malformedInclude.cmake
new file mode 100644
index 000000000..3cec3ad96
--- /dev/null
+++ b/Tests/RunCMake/include/malformedInclude.cmake
@@ -0,0 +1 @@
+if(
diff --git a/Tests/RunCMake/install/FILES-RENAME-all-check.cmake b/Tests/RunCMake/install/FILES-RENAME-all-check.cmake
new file mode 100644
index 000000000..7e9b10354
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-RENAME-all-check.cmake
@@ -0,0 +1 @@
+check_installed([[^src;src/script_Debug\.ps]])
diff --git a/Tests/RunCMake/install/FILES-RENAME-bad-result.txt b/Tests/RunCMake/install/FILES-RENAME-bad-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-RENAME-bad-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/install/FILES-RENAME-bad-stderr.txt b/Tests/RunCMake/install/FILES-RENAME-bad-stderr.txt
new file mode 100644
index 000000000..984415868
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-RENAME-bad-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<NOTAGENEX>
+
+ Expression did not evaluate to a known generator expression
diff --git a/Tests/RunCMake/install/FILES-RENAME-bad.cmake b/Tests/RunCMake/install/FILES-RENAME-bad.cmake
new file mode 100644
index 000000000..5be0bb202
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-RENAME-bad.cmake
@@ -0,0 +1,4 @@
+install(FILES empty.c
+ DESTINATION mybin
+ RENAME $<NOTAGENEX>
+ )
diff --git a/Tests/RunCMake/install/FILES-RENAME.cmake b/Tests/RunCMake/install/FILES-RENAME.cmake
new file mode 100644
index 000000000..5896e64e4
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-RENAME.cmake
@@ -0,0 +1,4 @@
+install(FILES script.bat
+ DESTINATION src
+ RENAME script_$<CONFIG>.ps
+ )
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index d64d88b77..efd03df6f 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -48,14 +48,16 @@ in directory:
endif()
endfunction()
-# Wrapper for run_cmake() that skips platforms that are non-ELF or have no RPATH support
-function(run_cmake_ELFRPATH_only case)
- if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+# Wrapper for run_cmake() that skips platforms on which we do not support editing the RPATH.
+function(run_cmake_EDIT_RPATH_only case)
+ if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT MATCHES "^(ELF|XCOFF)$")
run_cmake(${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.")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+ message(FATAL_ERROR "Expected platform AIX to advertize itself as XCOFF-based, but it did not.")
else()
message(STATUS "${case} - SKIPPED (No ELF-based platform found)")
endif()
@@ -63,7 +65,7 @@ function(run_cmake_ELFRPATH_only case)
endfunction()
run_cmake(TARGETS-FILE_RPATH_CHANGE-old_rpath)
-run_cmake_ELFRPATH_only(TARGETS-FILE_RPATH_CHANGE-new_rpath)
+run_cmake_EDIT_RPATH_only(TARGETS-FILE_RPATH_CHANGE-new_rpath)
run_cmake(DIRECTORY-MESSAGE_NEVER)
run_cmake(DIRECTORY-PATTERN-MESSAGE_NEVER)
run_cmake(DIRECTORY-message)
@@ -74,6 +76,7 @@ run_cmake(SkipInstallRulesNoWarning2)
run_cmake(DIRECTORY-DIRECTORY-bad)
run_cmake(DIRECTORY-DESTINATION-bad)
run_cmake(FILES-DESTINATION-bad)
+run_cmake(FILES-RENAME-bad)
run_cmake(TARGETS-DESTINATION-bad)
run_cmake(EXPORT-OldIFace)
run_cmake(EXPORT-UnknownExport)
@@ -91,6 +94,10 @@ run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc)
run_cmake(FILES-DESTINATION-TYPE)
run_cmake(DIRECTORY-DESTINATION-TYPE)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=Debug")
+run_install_test(FILES-RENAME)
+unset(RunCMake_TEST_OPTIONS)
+
if(APPLE)
run_cmake(TARGETS-Apple-Defaults)
endif()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake
index 673fdde19..6b2faa379 100644
--- a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake
@@ -22,6 +22,8 @@ macro(skip_without_rpath_change_rule)
# Sanity check against a platform known to generate a file(RPATH_CHANGE) rule
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(FATAL_ERROR "Expected generated file(RPATH_CHANGE) rule on platform Linux.")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+ message(FATAL_ERROR "Expected generated file(RPATH_CHANGE) rule on platform AIX.")
else()
message(STATUS "${test} - All checks skipped. No file(RPATH_CHANGE) rule found on this platform.")
return()
diff --git a/Tests/RunCMake/list/REMOVE_ITEM-NoItemArg.cmake b/Tests/RunCMake/list/REMOVE_ITEM-NoItemArg.cmake
new file mode 100644
index 000000000..f69c024a4
--- /dev/null
+++ b/Tests/RunCMake/list/REMOVE_ITEM-NoItemArg.cmake
@@ -0,0 +1,5 @@
+set(ls "a" "b" "c")
+list(REMOVE_ITEM ls alpha)
+if (NOT ls STREQUAL "a;b;c")
+ message(FATAL_ERROR "list(REMOVE_ITEM) modified for empty item")
+endif ()
diff --git a/Tests/RunCMake/list/RunCMakeTest.cmake b/Tests/RunCMake/list/RunCMakeTest.cmake
index b4a91bc62..c11891c51 100644
--- a/Tests/RunCMake/list/RunCMakeTest.cmake
+++ b/Tests/RunCMake/list/RunCMakeTest.cmake
@@ -30,6 +30,7 @@ run_cmake(FILTER-NotList)
run_cmake(REMOVE_AT-NotList)
run_cmake(REMOVE_DUPLICATES-NotList)
run_cmake(REMOVE_ITEM-NotList)
+run_cmake(REMOVE_ITEM-NoItemArg)
run_cmake(REVERSE-NotList)
run_cmake(SORT-NotList)
diff --git a/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt b/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt
index 22226f2ae..da44726fd 100644
--- a/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt
+++ b/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error at MATH-InvalidExpression.cmake:1 \(math\):
- math cannot parse the expression: "INVALID": syntax error, unexpected \$end
- \(7\).
+ math cannot parse the expression: "INVALID": syntax error, unexpected end
+ of file \(7\).
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/pseudo_llvm-rc.c b/Tests/RunCMake/pseudo_llvm-rc.c
new file mode 100644
index 000000000..7acb2a3cf
--- /dev/null
+++ b/Tests/RunCMake/pseudo_llvm-rc.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char* argv[])
+{
+ FILE* source;
+ FILE* target;
+ int i;
+ for (i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "-bad") == 0) {
+ fprintf(stdout, "stdout from bad command line arg '-bad'\n");
+ fprintf(stderr, "stderr from bad command line arg '-bad'\n");
+ return 1;
+ }
+ }
+ source = fopen(argv[argc - 1], "rb");
+ if (source == NULL) {
+ return 1;
+ }
+ target = fopen(argv[argc - 2], "wb");
+ if (target != NULL) {
+ char buffer[500];
+ size_t n = fread(buffer, 1, sizeof(buffer), source);
+ fwrite(buffer, 1, n, target);
+ fclose(source);
+ fclose(target);
+ return 0;
+ }
+ return 1;
+}
diff --git a/Tests/RunCMake/separate_arguments/ProgramCommand.cmake b/Tests/RunCMake/separate_arguments/ProgramCommand.cmake
index 8325def1b..bdf5810b4 100644
--- a/Tests/RunCMake/separate_arguments/ProgramCommand.cmake
+++ b/Tests/RunCMake/separate_arguments/ProgramCommand.cmake
@@ -7,7 +7,7 @@ endif()
set (TEST_EXE_DIR "${CMAKE_CURRENT_BINARY_DIR}/TestExe")
file(MAKE_DIRECTORY "${TEST_EXE_DIR}")
file(COPY "${CMAKE_COMMAND}" DESTINATION "${TEST_EXE_DIR}")
-get_filename_component (cmake_exe "${CMAKE_COMMAND}" NAME)
+cmake_path (GET CMAKE_COMMAND FILENAME cmake_exe)
set (ENV{PATH} "${TEST_EXE_DIR}")
diff --git a/Tests/RunCMake/separate_arguments/ProgramCommandWithSeparateArgs.cmake b/Tests/RunCMake/separate_arguments/ProgramCommandWithSeparateArgs.cmake
index 07572ba60..2826cc946 100644
--- a/Tests/RunCMake/separate_arguments/ProgramCommandWithSeparateArgs.cmake
+++ b/Tests/RunCMake/separate_arguments/ProgramCommandWithSeparateArgs.cmake
@@ -7,7 +7,7 @@ endif()
set (TEST_EXE_DIR "${CMAKE_CURRENT_BINARY_DIR}/TestExe")
file(MAKE_DIRECTORY "${TEST_EXE_DIR}")
file(COPY "${CMAKE_COMMAND}" DESTINATION "${TEST_EXE_DIR}")
-get_filename_component (cmake_exe "${CMAKE_COMMAND}" NAME)
+cmake_path (GET CMAKE_COMMAND FILENAME cmake_exe)
set (ENV{PATH} "${TEST_EXE_DIR}")
diff --git a/Tests/RunCMake/target_include_directories/RunCMakeTest.cmake b/Tests/RunCMake/target_include_directories/RunCMakeTest.cmake
index b67c5983e..48a750d83 100644
--- a/Tests/RunCMake/target_include_directories/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_include_directories/RunCMakeTest.cmake
@@ -1,3 +1,6 @@
include(RunCMake)
run_cmake(empty_keyword_args)
+run_cmake(include_before)
+run_cmake(include_after)
+run_cmake(include_default)
diff --git a/Tests/RunCMake/target_include_directories/include_after.cmake b/Tests/RunCMake/target_include_directories/include_after.cmake
new file mode 100644
index 000000000..68a08a75a
--- /dev/null
+++ b/Tests/RunCMake/target_include_directories/include_after.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.c" "int main() { return 0;}")
+
+set(include_dir "${CMAKE_CURRENT_BINARY_DIR}/dir")
+set(after_include_dir "${CMAKE_CURRENT_BINARY_DIR}/dirAfter")
+file(MAKE_DIRECTORY "${include_dir}")
+file(MAKE_DIRECTORY "${after_include_dir}")
+
+add_executable(main "${CMAKE_CURRENT_BINARY_DIR}/main.c")
+include_directories("${include_dir}")
+target_include_directories(main AFTER PRIVATE "${after_include_dir}")
+
+get_target_property(actual_include_dirs main INCLUDE_DIRECTORIES)
+set(desired_include_dirs "${include_dir}" "${after_include_dir}")
+
+if (NOT "${actual_include_dirs}" MATCHES "${desired_include_dirs}")
+ message(SEND_ERROR "include after does not work")
+endif()
diff --git a/Tests/RunCMake/target_include_directories/include_before.cmake b/Tests/RunCMake/target_include_directories/include_before.cmake
new file mode 100644
index 000000000..9bebecd54
--- /dev/null
+++ b/Tests/RunCMake/target_include_directories/include_before.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.c" "int main() { return 0;}")
+
+set(include_dir "${CMAKE_CURRENT_BINARY_DIR}/dir")
+set(before_include_dir "${CMAKE_CURRENT_BINARY_DIR}/dirBefore")
+file(MAKE_DIRECTORY "${include_dir}")
+file(MAKE_DIRECTORY "${before_include_dir}")
+
+add_executable(main "${CMAKE_CURRENT_BINARY_DIR}/main.c")
+include_directories("${include_dir}")
+target_include_directories(main BEFORE PRIVATE "${before_include_dir}")
+
+get_target_property(actual_include_dirs main INCLUDE_DIRECTORIES)
+set(desired_include_dirs "${before_include_dir}" "${include_dir}")
+
+if (NOT "${actual_include_dirs}" MATCHES "${desired_include_dirs}")
+ message(SEND_ERROR "include before does not work")
+endif()
diff --git a/Tests/RunCMake/target_include_directories/include_default.cmake b/Tests/RunCMake/target_include_directories/include_default.cmake
new file mode 100644
index 000000000..88b2502c3
--- /dev/null
+++ b/Tests/RunCMake/target_include_directories/include_default.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.c" "int main() { return 0;}")
+
+set(include_dir "${CMAKE_CURRENT_BINARY_DIR}/dir")
+set(default_include_dir "${CMAKE_CURRENT_BINARY_DIR}/dirDefault")
+file(MAKE_DIRECTORY "${include_dir}")
+file(MAKE_DIRECTORY "${default_include_dir}")
+
+add_executable(main "${CMAKE_CURRENT_BINARY_DIR}/main.c")
+include_directories("${include_dir}")
+target_include_directories(main AFTER PRIVATE "${default_include_dir}")
+
+get_target_property(actual_include_dirs main INCLUDE_DIRECTORIES)
+set(desired_include_dirs "${include_dir}" "${default_include_dir}")
+
+if (NOT "${actual_include_dirs}" MATCHES "${desired_include_dirs}")
+ message(SEND_ERROR "include default does not work")
+endif()
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake
index 0f0e5d87a..f43a7c6c7 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/RunCMakeTest.cmake
@@ -34,6 +34,7 @@ if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Visual Studio|Xcode|Watcom WMake
run_cmake_target(genex CXX_interface2 LinkLibraries_CXX_interface2 --config Release)
run_cmake_target(genex C_static LinkLibraries_C_static --config Release)
run_cmake_target(genex CXX_static LinkLibraries_CXX_static --config Release)
+ run_cmake_target(genex C_static_CXX LinkLibraries_C_static_CXX --config Release)
unset(RunCMake_TEST_OPTIONS)
unset(RunCMake_TEST_OUTPUT_MERGE)
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx
index a12cacadb..ee6811c1d 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/func.cxx
@@ -1,7 +1,18 @@
-#if defined(_WIN32)
-__declspec(dllexport)
+#if !defined(BUILD_STATIC) && defined(_WIN32)
+# define EXPORT_SYMBOL __declspec(dllexport)
+#else
+# define EXPORT_SYMBOL
#endif
- void func_cxx()
+
+EXPORT_SYMBOL
+void func_cxx()
{
}
+
+extern "C" {
+EXPORT_SYMBOL
+void func_c_cxx()
+{
+}
+}
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake
index f3fe9554d..22d3df738 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/genex.cmake
@@ -7,6 +7,8 @@ enable_language(CXX)
add_library(shared_C SHARED func.c)
add_library(shared_CXX SHARED func.cxx)
+add_library(static_cxx STATIC func.cxx)
+target_compile_definitions(static_cxx PRIVATE BUILD_STATIC)
add_library(static1_C STATIC empty.c)
target_link_libraries (static1_C INTERFACE $<$<LINK_LANGUAGE:C>:shared_C>)
@@ -70,3 +72,10 @@ add_executable(LinkLibraries_C_static main.c)
target_link_libraries (LinkLibraries_C_static PRIVATE static3)
add_executable(LinkLibraries_CXX_static main.cxx)
target_link_libraries (LinkLibraries_CXX_static PRIVATE static3)
+
+# $<LINK_LANGUAGE:> change, by default, link language from C to CXX
+# but because LINKER_LANGUAGE property is set, keep C as link language
+add_executable(LinkLibraries_C_static_CXX main.c)
+target_compile_definitions (LinkLibraries_C_static_CXX PRIVATE C_USE_CXX)
+target_link_libraries (LinkLibraries_C_static_CXX PRIVATE $<$<LINK_LANGUAGE:C>:static_cxx>)
+set_property(TARGET LinkLibraries_C_static_CXX PROPERTY LINKER_LANGUAGE C)
diff --git a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c
index a908dea23..689dbd756 100644
--- a/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c
+++ b/Tests/RunCMake/target_link_libraries-LINK_LANGUAGE/main.c
@@ -1,12 +1,20 @@
-#if defined(_WIN32)
+#if defined(C_USE_CXX)
+void func_c_cxx();
+#else
+# if defined(_WIN32)
__declspec(dllimport)
-#endif
+# endif
void func_c();
+#endif
int main()
{
+#if defined(C_USE_CXX)
+ func_c_cxx();
+#else
func_c();
+#endif
return 0;
}
diff --git a/Tests/RunCMake/try_run/RunCMakeTest.cmake b/Tests/RunCMake/try_run/RunCMakeTest.cmake
index 368956295..fa30eb492 100644
--- a/Tests/RunCMake/try_run/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_run/RunCMakeTest.cmake
@@ -8,3 +8,5 @@ if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
run_cmake(LinkOptions)
unset (RunCMake_TEST_OPTIONS)
endif()
+
+run_cmake(WorkingDirArg)
diff --git a/Tests/RunCMake/try_run/WorkingDirArg.cmake b/Tests/RunCMake/try_run/WorkingDirArg.cmake
new file mode 100644
index 000000000..b58382333
--- /dev/null
+++ b/Tests/RunCMake/try_run/WorkingDirArg.cmake
@@ -0,0 +1,9 @@
+try_run(RUN_RESULT COMPILE_RESULT
+ ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ RUN_OUTPUT_VARIABLE OUTPUT_VARIABLE
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir
+ )
+
+if(RUN_RESULT)
+ message(SEND_ERROR "try run failed with result: ${RUN_RESULT}")
+endif()
diff --git a/Tests/RunCMake/while/EndAlone-stderr.txt b/Tests/RunCMake/while/EndAlone-stderr.txt
index 5fe665578..3195fa0ee 100644
--- a/Tests/RunCMake/while/EndAlone-stderr.txt
+++ b/Tests/RunCMake/while/EndAlone-stderr.txt
@@ -1,5 +1,4 @@
-^CMake Error at EndAlone.cmake:1 \(endwhile\):
- endwhile An ENDWHILE command was found outside of a proper WHILE ENDWHILE
- structure. Or its arguments did not match the opening WHILE command.
+^CMake Error at EndAlone\.cmake:[0-9]+ \(endwhile\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/while/EndAloneArgs-stderr.txt b/Tests/RunCMake/while/EndAloneArgs-stderr.txt
index a8c043d0f..1634e3bee 100644
--- a/Tests/RunCMake/while/EndAloneArgs-stderr.txt
+++ b/Tests/RunCMake/while/EndAloneArgs-stderr.txt
@@ -1,5 +1,4 @@
-^CMake Error at EndAloneArgs.cmake:1 \(endwhile\):
- endwhile An ENDWHILE command was found outside of a proper WHILE ENDWHILE
- structure. Or its arguments did not match the opening WHILE command.
+^CMake Error at EndAloneArgs\.cmake:[0-9]+ \(endwhile\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/while/EndMissing-stderr.txt b/Tests/RunCMake/while/EndMissing-stderr.txt
index 964792ff2..1e3be4db7 100644
--- a/Tests/RunCMake/while/EndMissing-stderr.txt
+++ b/Tests/RunCMake/while/EndMissing-stderr.txt
@@ -1,8 +1,4 @@
-^CMake Error in EndMissing.cmake:
- A logical block opening on the line
-
- .*/Tests/RunCMake/while/EndMissing.cmake:1 \(while\)
-
- is not closed.
+^CMake Error at EndMissing\.cmake:[0-9]+ \(while\):
+ Flow control statements are not properly nested\.
Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/while/MissingArgument-stderr.txt b/Tests/RunCMake/while/MissingArgument-stderr.txt
index 7ff0971f4..59e8ee399 100644
--- a/Tests/RunCMake/while/MissingArgument-stderr.txt
+++ b/Tests/RunCMake/while/MissingArgument-stderr.txt
@@ -1,4 +1,11 @@
-^CMake Error at MissingArgument.cmake:1 \(while\):
+^CMake Error at MissingArgument\.cmake:[0-9]+ \(while\):
while called with incorrect number of arguments
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)$
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at MissingArgument\.cmake:[0-9]+ \(endwhile\):
+ endwhile An ENDWHILE command was found outside of a proper WHILE ENDWHILE
+ structure\. Or its arguments did not match the opening WHILE command\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/while/MissingArgument.cmake b/Tests/RunCMake/while/MissingArgument.cmake
index 32eaa2698..3fe2d972e 100644
--- a/Tests/RunCMake/while/MissingArgument.cmake
+++ b/Tests/RunCMake/while/MissingArgument.cmake
@@ -1 +1,2 @@
while()
+endwhile()
diff --git a/Tests/Server/CMakeLists.txt b/Tests/Server/CMakeLists.txt
deleted file mode 100644
index 8321edb1d..000000000
--- a/Tests/Server/CMakeLists.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-cmake_minimum_required(VERSION 3.4)
-project(Server CXX)
-
-find_package(Python REQUIRED)
-
-macro(do_test bsname file type)
- execute_process(COMMAND ${Python_EXECUTABLE}
- -B # no .pyc files
- "${CMAKE_SOURCE_DIR}/${type}-test.py"
- "${CMAKE_COMMAND}"
- "${CMAKE_SOURCE_DIR}/${file}"
- "${CMAKE_SOURCE_DIR}"
- "${CMAKE_BINARY_DIR}"
- "${CMAKE_GENERATOR}"
- RESULT_VARIABLE test_result
- )
-
- if (NOT test_result EQUAL 0)
- message(SEND_ERROR "TEST FAILED: ${test_result}")
- endif()
-endmacro()
-
-do_test("test_cache" "tc_cache.json" "server")
-do_test("test_handshake" "tc_handshake.json" "server")
-do_test("test_globalSettings" "tc_globalSettings.json" "server")
-do_test("test_buildsystem1" "tc_buildsystem1.json" "server")
-
-add_executable(Server empty.cpp)
diff --git a/Tests/Server/buildsystem1/CMakeLists.txt b/Tests/Server/buildsystem1/CMakeLists.txt
deleted file mode 100644
index d690472d1..000000000
--- a/Tests/Server/buildsystem1/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-cmake_minimum_required(VERSION 3.4)
-
-project(buildsystem2)
-
-set(var1 123)
-
-set(var2 345)
-
-add_executable(main main.cpp)
-
-add_executable(m_other main.cpp)
-
-add_library(foo foo.cpp)
-
-function(f1)
-endfunction()
-
-set(var3 345)
-
-add_library(someImportedLib UNKNOWN IMPORTED)
-
-add_subdirectory(subdir)
diff --git a/Tests/Server/buildsystem1/subdir/CMakeLists.txt b/Tests/Server/buildsystem1/subdir/CMakeLists.txt
deleted file mode 100644
index 915731286..000000000
--- a/Tests/Server/buildsystem1/subdir/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-set(bar4 something)
-
-set(bar5 more)
-
-add_executable(ooo empty.cpp)
diff --git a/Tests/Server/cmakelib.py b/Tests/Server/cmakelib.py
deleted file mode 100644
index 546ae4cc5..000000000
--- a/Tests/Server/cmakelib.py
+++ /dev/null
@@ -1,380 +0,0 @@
-from __future__ import print_function
-import sys, subprocess, json, os, select, shutil, time, socket
-
-termwidth = 150
-
-print_communication = True
-
-def ordered(obj):
- if isinstance(obj, dict):
- return sorted((k, ordered(v)) for k, v in obj.items())
- if isinstance(obj, list):
- return sorted(ordered(x) for x in obj)
- else:
- return obj
-
-def col_print(title, array):
- print()
- print()
- print(title)
-
- indentwidth = 4
- indent = " " * indentwidth
-
- if not array:
- print(indent + "<None>")
- return
-
- padwidth = 2
-
- maxitemwidth = len(max(array, key=len))
-
- numCols = max(1, int((termwidth - indentwidth + padwidth) / (maxitemwidth + padwidth)))
-
- numRows = len(array) // numCols + 1
-
- pad = " " * padwidth
-
- for index in range(numRows):
- print(indent + pad.join(item.ljust(maxitemwidth) for item in array[index::numRows]))
-
-filterPacket = lambda x: x
-
-STDIN = 0
-PIPE = 1
-
-communicationMethods = [STDIN]
-
-if hasattr(socket, 'AF_UNIX'):
- communicationMethods.append(PIPE)
-
-def defaultExitWithError(proc):
- data = ""
- try:
- while select.select([proc.outPipe], [], [], 3.)[0]:
- data = data + proc.outPipe.read(1)
- if len(data):
- print("Rest of raw buffer from server:")
- printServer(data)
- except:
- pass
- proc.outPipe.close()
- proc.inPipe.close()
- proc.kill()
- sys.exit(1)
-
-exitWithError = lambda proc: defaultExitWithError(proc)
-
-serverTag = "SERVER"
-
-def printServer(*args):
- print(serverTag + ">", *args)
- print()
- sys.stdout.flush()
-
-def printClient(*args):
- print("CLIENT>", *args)
- print()
- sys.stdout.flush()
-
-def waitForRawMessage(cmakeCommand):
- stdoutdata = ""
- payload = ""
- while not cmakeCommand.poll():
- stdoutdataLine = cmakeCommand.outPipe.readline()
- if stdoutdataLine:
- stdoutdata += stdoutdataLine.decode('utf-8')
- else:
- break
- begin = stdoutdata.find('[== "CMake Server" ==[\n')
- end = stdoutdata.find(']== "CMake Server" ==]')
-
- if begin != -1 and end != -1:
- begin += len('[== "CMake Server" ==[\n')
- payload = stdoutdata[begin:end]
- jsonPayload = json.loads(payload)
- filteredPayload = filterPacket(jsonPayload)
- if print_communication and filteredPayload:
- printServer(filteredPayload)
- if filteredPayload is not None or jsonPayload is None:
- return jsonPayload
- stdoutdata = stdoutdata[(end+len(']== "CMake Server" ==]')):]
-
-# Python2 has no problem writing the output of encodes directly,
-# but Python3 returns only 'int's for encode and so must be turned
-# into bytes. We use the existence of 'to_bytes' on an int to
-# determine which behavior is appropriate. It might be more clear
-# to do this in the code which uses the flag, but introducing
-# this lookup cost at every byte sent isn't ideal.
-has_to_bytes = "to_bytes" in dir(10)
-
-def writeRawData(cmakeCommand, content):
- writeRawData.counter += 1
- payload = """
-[== "CMake Server" ==[
-%s
-]== "CMake Server" ==]
-""" % content
-
- rn = ( writeRawData.counter % 2 ) == 0
-
- if rn:
- payload = payload.replace('\n', '\r\n')
-
- if print_communication:
- printClient(content, "(Use \\r\\n:", rn, ")")
-
- # To stress test how cmake deals with fragmentation in the
- # communication channel, we send only one byte at a time.
- # Certain communication methods / platforms might still buffer
- # it all into one message since its so close together, but in
- # general this will catch places where we assume full buffers
- # come in all at once.
- encoded_payload = payload.encode('utf-8')
-
- # Python version 3+ can't write ints directly; but 'to_bytes'
- # for int was only added in python 3.2. If this is a 3+ version
- # of python without that conversion function; just write the whole
- # thing out at once.
- if sys.version_info[0] > 2 and not has_to_bytes:
- cmakeCommand.write(encoded_payload)
- else:
- for c in encoded_payload:
- if has_to_bytes:
- c = c.to_bytes(1, byteorder='big')
- cmakeCommand.write(c)
-
-writeRawData.counter = 0
-
-def writePayload(cmakeCommand, obj):
- writeRawData(cmakeCommand, json.dumps(obj))
-
-def getPipeName():
- return "/tmp/server-test-socket"
-
-def attachPipe(cmakeCommand, pipeName):
- time.sleep(1)
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- sock.connect(pipeName)
- global serverTag
- serverTag = "SERVER(PIPE)"
- cmakeCommand.outPipe = sock.makefile()
- cmakeCommand.inPipe = sock
- cmakeCommand.write = cmakeCommand.inPipe.sendall
-
-def writeAndFlush(pipe, val):
- pipe.write(val)
- pipe.flush()
-
-def initServerProc(cmakeCommand, comm):
- if comm == PIPE:
- pipeName = getPipeName()
- cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--pipe=" + pipeName])
- attachPipe(cmakeCommand, pipeName)
- else:
- cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--debug"],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
- cmakeCommand.outPipe = cmakeCommand.stdout
- cmakeCommand.inPipe = cmakeCommand.stdin
- cmakeCommand.write = lambda val: writeAndFlush(cmakeCommand.inPipe, val)
-
- packet = waitForRawMessage(cmakeCommand)
- if packet == None:
- print("Not in server mode")
- sys.exit(2)
-
- if packet['type'] != 'hello':
- print("No hello message")
- sys.exit(3)
-
- return cmakeCommand
-
-def exitProc(cmakeCommand):
- # Tell the server to exit.
- cmakeCommand.stdin.close()
- cmakeCommand.stdout.close()
-
- # Wait for the server to exit.
- # If this version of python supports it, terminate the server after a timeout.
- try:
- cmakeCommand.wait(timeout=5)
- except TypeError:
- cmakeCommand.wait()
- except:
- cmakeCommand.terminate()
- raise
-
-def waitForMessage(cmakeCommand, expected):
- data = ordered(expected)
- packet = ordered(waitForRawMessage(cmakeCommand))
-
- if packet != data:
- print ("Received unexpected message; test failed")
- exitWithError(cmakeCommand)
- return packet
-
-def waitForReply(cmakeCommand, originalType, cookie, skipProgress):
- gotResult = False
- while True:
- packet = waitForRawMessage(cmakeCommand)
- t = packet['type']
- if packet['cookie'] != cookie or packet['inReplyTo'] != originalType:
- print("cookie or inReplyTo mismatch")
- sys.exit(4)
- if t == 'message' or t == 'progress':
- if skipProgress:
- continue
- if t == 'reply':
- break
- print("Unrecognized message", packet)
- sys.exit(5)
-
- return packet
-
-def waitForError(cmakeCommand, originalType, cookie, message):
- packet = waitForRawMessage(cmakeCommand)
- if packet['cookie'] != cookie or packet['type'] != 'error' or packet['inReplyTo'] != originalType or packet['errorMessage'] != message:
- sys.exit(6)
-
-def waitForProgress(cmakeCommand, originalType, cookie, current, message):
- packet = waitForRawMessage(cmakeCommand)
- if packet['cookie'] != cookie or packet['type'] != 'progress' or packet['inReplyTo'] != originalType or packet['progressCurrent'] != current or packet['progressMessage'] != message:
- sys.exit(7)
-
-def handshake(cmakeCommand, major, minor, source, build, generator, extraGenerator):
- version = { 'major': major }
- if minor >= 0:
- version['minor'] = minor
-
- writePayload(cmakeCommand, { 'type': 'handshake', 'protocolVersion': version,
- 'cookie': 'TEST_HANDSHAKE', 'sourceDirectory': source, 'buildDirectory': build,
- 'generator': generator, 'extraGenerator': extraGenerator })
- waitForReply(cmakeCommand, 'handshake', 'TEST_HANDSHAKE', False)
-
-def validateGlobalSettings(cmakeCommand, cmakeCommandPath, data):
- packet = waitForReply(cmakeCommand, 'globalSettings', '', False)
-
- capabilities = packet['capabilities']
-
- # validate version:
- cmakeoutput = subprocess.check_output([ cmakeCommandPath, "--version" ], universal_newlines=True)
- cmakeVersion = cmakeoutput.splitlines()[0][14:]
-
- version = capabilities['version']
- versionString = version['string']
- vs = str(version['major']) + '.' + str(version['minor']) + '.' + str(version['patch'])
- if (versionString != vs and not versionString.startswith(vs + '-')):
- sys.exit(8)
- if (versionString != cmakeVersion):
- sys.exit(9)
-
- # validate generators:
- generatorObjects = capabilities['generators']
-
- cmakeoutput = subprocess.check_output([ cmakeCommandPath, "--help" ], universal_newlines=True)
- index = cmakeoutput.index('\nGenerators\n\n')
- cmakeGenerators = []
- for line in cmakeoutput[index + 12:].splitlines():
- if not line:
- continue
- if line[0] == '*': # default generator marker
- line = ' ' + line[1:]
- if not line.startswith(' '):
- continue
- if line.startswith(' '):
- continue
- equalPos = line.find('=')
- tmp = ''
- if (equalPos > 0):
- tmp = line[2:equalPos].strip()
- else:
- tmp = line.strip()
- if tmp.endswith(" [arch]"):
- tmp = tmp[0:len(tmp) - 7]
- if (len(tmp) > 0) and (" - " not in tmp):
- cmakeGenerators.append(tmp)
-
- generators = []
- for genObj in generatorObjects:
- generators.append(genObj['name'])
-
- generators.sort()
- cmakeGenerators.sort()
-
- for gen in cmakeGenerators:
- if (not gen in generators):
- sys.exit(10)
-
- gen = packet['generator']
- if (gen != '' and not (gen in generators)):
- sys.exit(11)
-
- for i in data:
- print("Validating", i)
- if (packet[i] != data[i]):
- sys.exit(12)
-
-def validateCache(cmakeCommand, data):
- packet = waitForReply(cmakeCommand, 'cache', '', False)
-
- cache = packet['cache']
-
- if (data['isEmpty']):
- if (cache != []):
- print('Expected empty cache, but got data.\n')
- sys.exit(1)
- return;
-
- if (cache == []):
- print('Expected cache contents, but got none.\n')
- sys.exit(1)
-
- hadHomeDir = False
- for value in cache:
- if (value['key'] == 'CMAKE_HOME_DIRECTORY'):
- hadHomeDir = True
-
- if (not hadHomeDir):
- print('No CMAKE_HOME_DIRECTORY found in cache.')
- sys.exit(1)
-
-def handleBasicMessage(proc, obj, debug):
- if 'sendRaw' in obj:
- data = obj['sendRaw']
- if debug: print("Sending raw:", data)
- writeRawData(proc, data)
- return True
- elif 'send' in obj:
- data = obj['send']
- if debug: print("Sending:", json.dumps(data))
- writePayload(proc, data)
- return True
- elif 'recv' in obj:
- data = obj['recv']
- if debug: print("Waiting for:", json.dumps(data))
- waitForMessage(proc, data)
- return True
- elif 'message' in obj:
- print("MESSAGE:", obj["message"])
- sys.stdout.flush()
- return True
- return False
-
-def shutdownProc(proc):
- # Tell the server to exit.
- proc.inPipe.close()
- proc.outPipe.close()
-
- # Wait for the server to exit.
- # If this version of python supports it, terminate the server after a timeout.
- try:
- proc.wait(timeout=5)
- except TypeError:
- proc.wait()
- except:
- proc.terminate()
- raise
-
- print('cmake-server exited: %d' % proc.returncode)
- sys.exit(proc.returncode)
diff --git a/Tests/Server/server-test.py b/Tests/Server/server-test.py
deleted file mode 100644
index 701c6e945..000000000
--- a/Tests/Server/server-test.py
+++ /dev/null
@@ -1,105 +0,0 @@
-from __future__ import print_function
-import sys, cmakelib, json, os, shutil
-
-debug = True
-
-cmakeCommand = sys.argv[1]
-testFile = sys.argv[2]
-sourceDir = sys.argv[3]
-buildDir = sys.argv[4] + "/" + os.path.splitext(os.path.basename(testFile))[0]
-cmakeGenerator = sys.argv[5]
-
-print("Server Test:", testFile,
- "\n-- SourceDir:", sourceDir,
- "\n-- BuildDir:", buildDir,
- "\n-- Generator:", cmakeGenerator)
-
-if os.path.exists(buildDir):
- shutil.rmtree(buildDir)
-
-cmakelib.filterBase = sourceDir
-
-with open(testFile) as f:
- testData = json.loads(f.read())
-
-for communicationMethod in cmakelib.communicationMethods:
- proc = cmakelib.initServerProc(cmakeCommand, communicationMethod)
- if proc is None:
- continue
-
- for obj in testData:
- if cmakelib.handleBasicMessage(proc, obj, debug):
- pass
- elif 'reply' in obj:
- data = obj['reply']
- if debug: print("Waiting for reply:", json.dumps(data))
- originalType = ""
- cookie = ""
- skipProgress = False;
- if 'cookie' in data: cookie = data['cookie']
- if 'type' in data: originalType = data['type']
- if 'skipProgress' in data: skipProgress = data['skipProgress']
- cmakelib.waitForReply(proc, originalType, cookie, skipProgress)
- elif 'error' in obj:
- data = obj['error']
- if debug: print("Waiting for error:", json.dumps(data))
- originalType = ""
- cookie = ""
- message = ""
- if 'cookie' in data: cookie = data['cookie']
- if 'type' in data: originalType = data['type']
- if 'message' in data: message = data['message']
- cmakelib.waitForError(proc, originalType, cookie, message)
- elif 'progress' in obj:
- data = obj['progress']
- if debug: print("Waiting for progress:", json.dumps(data))
- originalType = ''
- cookie = ""
- current = 0
- message = ""
- if 'cookie' in data: cookie = data['cookie']
- if 'type' in data: originalType = data['type']
- if 'current' in data: current = data['current']
- if 'message' in data: message = data['message']
- cmakelib.waitForProgress(proc, originalType, cookie, current, message)
- elif 'handshake' in obj:
- data = obj['handshake']
- if debug: print("Doing handshake:", json.dumps(data))
- major = -1
- minor = -1
- generator = cmakeGenerator
- extraGenerator = ''
- sourceDirectory = sourceDir
- buildDirectory = buildDir
- if 'major' in data: major = data['major']
- if 'minor' in data: minor = data['minor']
- if 'buildDirectory' in data: buildDirectory = data['buildDirectory']
- if 'sourceDirectory' in data: sourceDirectory = data['sourceDirectory']
- if 'generator' in data: generator = data['generator']
- if 'extraGenerator' in data: extraGenerator = data['extraGenerator']
-
- if not os.path.isabs(buildDirectory):
- buildDirectory = buildDir + "/" + buildDirectory
- if sourceDirectory != '' and not os.path.isabs(sourceDirectory):
- sourceDirectory = sourceDir + "/" + sourceDirectory
- cmakelib.handshake(proc, major, minor, sourceDirectory, buildDirectory,
- generator, extraGenerator)
- elif 'validateGlobalSettings' in obj:
- data = obj['validateGlobalSettings']
- if not 'buildDirectory' in data: data['buildDirectory'] = buildDir
- if not 'sourceDirectory' in data: data['sourceDirectory'] = sourceDir
- if not 'generator' in data: data['generator'] = cmakeGenerator
- if not 'extraGenerator' in data: data['extraGenerator'] = ''
- cmakelib.validateGlobalSettings(proc, cmakeCommand, data)
- elif 'validateCache' in obj:
- data = obj['validateCache']
- if not 'isEmpty' in data: data['isEmpty'] = false
- cmakelib.validateCache(proc, data)
- elif 'reconnect' in obj:
- cmakelib.exitProc(proc)
- proc = cmakelib.initServerProc(cmakeCommand, communicationMethod)
- else:
- print("Unknown command:", json.dumps(obj))
- sys.exit(2)
- cmakelib.shutdownProc(proc)
- print("Completed")
diff --git a/Tests/Server/tc_buildsystem1.json b/Tests/Server/tc_buildsystem1.json
deleted file mode 100644
index 08831b7c4..000000000
--- a/Tests/Server/tc_buildsystem1.json
+++ /dev/null
@@ -1,27 +0,0 @@
-[
-{ "message": "Testing globalSettings" },
-
-{ "handshake": {"major": 1, "sourceDirectory":"buildsystem1","buildDirectory":"buildsystem1"} },
-
-{ "message": "Configure:" },
-{ "send": { "type": "configure", "cookie":"CONFIG" } },
-{ "reply": { "type": "configure", "cookie":"CONFIG", "skipProgress":true } },
-
-{ "message": "Compute:" },
-{ "send": { "type": "compute", "cookie":"COMPUTE" } },
-{ "reply": { "type": "compute", "cookie":"COMPUTE", "skipProgress":true } },
-
-{ "message": "Codemodel:" },
-{ "send": { "type": "codemodel", "cookie":"CODEMODEL" } },
-{ "reply": { "type": "codemodel", "cookie":"CODEMODEL" } },
-
-{ "message": "CMake Inputs:"},
-{ "send": { "type": "cmakeInputs", "cookie":"INPUTS" } },
-{ "reply": { "type": "cmakeInputs", "cookie":"INPUTS" } },
-
-{ "message": "Cache:"},
-{ "send": { "type": "cache", "cookie":"CACHE" } },
-{ "reply": { "type": "cache", "cookie":"CACHE" } },
-
-{ "message": "Everything ok." }
-]
diff --git a/Tests/Server/tc_cache.json b/Tests/Server/tc_cache.json
deleted file mode 100644
index 74af6d93c..000000000
--- a/Tests/Server/tc_cache.json
+++ /dev/null
@@ -1,24 +0,0 @@
-[
-{ "message": "Testing cache" },
-
-{ "message": "Cache after first handshake is empty:" },
-{ "handshake": {"major": 1, "sourceDirectory": "buildsystem1", "buildDirectory": "buildsystem1"} },
-{ "send": { "type": "cache" } },
-{ "validateCache": { "isEmpty": true } },
-
-{ "message": "Cache after configure is populated:" },
-{ "send": { "type": "configure" } },
-{ "reply": { "type": "configure", "skipProgress":true } },
-{ "send": { "type": "cache" } },
-{ "validateCache": { "isEmpty": false } },
-
-{ "message": "Handshake for existing cache requires buildDirectory only:" },
-{ "reconnect": {} },
-{ "handshake": {"major": 1, "sourceDirectory": "", "buildDirectory": "buildsystem1"} },
-
-{ "message": "Cache after reconnect is again populated:" },
-{ "send": { "type": "cache" } },
-{ "validateCache": { "isEmpty": false } },
-
-{ "message": "Everything ok." }
-]
diff --git a/Tests/Server/tc_globalSettings.json b/Tests/Server/tc_globalSettings.json
deleted file mode 100644
index d72fb41ac..000000000
--- a/Tests/Server/tc_globalSettings.json
+++ /dev/null
@@ -1,140 +0,0 @@
-[
-{ "message": "Testing globalSettings" },
-
-{ "handshake": {"major": 1} },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-
-
-{ "message": "Change settings:" },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": true, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUninitialized": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": true, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUninitialized": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "traceExpand": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": true, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "traceExpand": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-
-
-{ "send": { "type": "setGlobalSettings", "trace": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": true, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "trace": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnusedCli": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": false, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnusedCli": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "checkSystemVars": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": true } },
-
-{ "send": { "type": "setGlobalSettings", "checkSystemVars": false } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": false, "debugOutput": false, "warnUninitialized": false, "traceExpand": false, "trace": false, "warnUnusedCli": true, "checkSystemVars": false } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-
-{ "message": "Ignore unknown/readonly" },
-
-{ "send": { "type": "setGlobalSettings", "unknownKey": "unknownValue", "extraGenerator": "XXX", "generator": "YYY", "sourceDirectory": "/tmp/source", "buildDirectory": "/tmp/build" } },
-{ "reply": { "type": "setGlobalSettings" } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-
-{ "message": "Error paths:" },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": true, "warnUnused": 1 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"warnUnused\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": 1 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"debugOutput\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUninitialized": 1, "warnUnused": true, "debugOutput": true } },
-{ "error": { "type": "setGlobalSettings", "message": "\"warnUninitialized\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "traceExpand": 1 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"traceExpand\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "debugOutput": true, "trace": 1, "warnUnused": true } },
-{ "error": { "type": "setGlobalSettings", "message": "\"trace\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "warnUnusedCli": 1.0 } },
-{ "error": { "type": "setGlobalSettings", "message": "\"warnUnusedCli\" must be unset or a bool value." } },
-
-{ "send": { "type": "setGlobalSettings", "warnUnused": true, "debugOutput": true, "checkSystemVars": "some string" } },
-{ "error": { "type": "setGlobalSettings", "message": "\"checkSystemVars\" must be unset or a bool value." } },
-
-{ "send": { "type": "globalSettings"} },
-{ "validateGlobalSettings": { "warnUnused": true, "debugOutput": true, "warnUninitialized": true, "traceExpand": true, "trace": true, "warnUnusedCli": false, "checkSystemVars": true } },
-
-{ "message": "Everything ok." }
-]
diff --git a/Tests/Server/tc_handshake.json b/Tests/Server/tc_handshake.json
deleted file mode 100644
index 4bb7fa7ac..000000000
--- a/Tests/Server/tc_handshake.json
+++ /dev/null
@@ -1,75 +0,0 @@
-[
-{ "message": "Testing basic message handling:" },
-
-{ "sendRaw": "Sometext"},
-{ "recv": {"cookie":"","errorMessage":"Failed to parse JSON input.","inReplyTo":"","type":"error"} },
-
-{ "message": "Testing invalid json input"},
-{ "send": { "test": "sometext" } },
-{ "recv": {"cookie":"","errorMessage":"No type given in request.","inReplyTo":"","type":"error"} },
-
-{ "send": {"test": "sometext","cookie":"monster"} },
-{ "recv": {"cookie":"monster","errorMessage":"No type given in request.","inReplyTo":"","type":"error"} },
-
-{ "message": "Testing commands before handshake" },
-{ "send": {"type": "cache","cookie":"monster"} },
-{ "recv": {"cookie":"monster","errorMessage":"Waiting for type \"handshake\".","inReplyTo":"cache","type":"error"} },
-
-{ "message": "Testing handshake" },
-{ "send": {"type": "sometype","cookie":"monster2"} },
-{ "recv": {"cookie":"monster2","errorMessage":"Waiting for type \"handshake\".","inReplyTo":"sometype","type":"error"} },
-
-{ "send": {"type": "handshake"} },
-{ "recv": {"cookie":"","errorMessage":"\"protocolVersion\" is required for \"handshake\".","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","foo":"bar"} },
-{ "recv": {"cookie":"","errorMessage":"\"protocolVersion\" is required for \"handshake\".","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":"bar"} },
-{ "recv": {"cookie":"","errorMessage":"\"protocolVersion\" must be a JSON object.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{}} },
-{ "recv": {"cookie":"","errorMessage":"\"major\" must be set and an integer.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":"foo"}} },
-{ "recv": {"cookie":"","errorMessage":"\"major\" must be set and an integer.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":1, "minor":"foo"}} },
-{ "recv": {"cookie":"","errorMessage":"\"minor\" must be unset or an integer.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":-1, "minor":-1}} },
-{ "recv": {"cookie":"","errorMessage":"\"major\" must be >= 0.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":10, "minor":-1}} },
-{ "recv": {"cookie":"","errorMessage":"\"minor\" must be >= 0 when set.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":10000}} },
-{ "recv": {"cookie":"","errorMessage":"Protocol version not supported.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"type": "handshake","protocolVersion":{"major":1, "minor":10000}} },
-{ "recv": {"cookie":"","errorMessage":"Protocol version not supported.","inReplyTo":"handshake","type":"error"} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1}} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"buildDirectory\" is missing."} },
-
-{ "message": "Testing protocol version specific options (1.0):" },
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":"/tmp/src"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"buildDirectory\" is missing."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":"/tmp/src","buildDirectory":"/tmp/build"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"sourceDirectory\" is not a directory."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","extraGenerator":"CodeBlocks"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: \"generator\" is unset but required."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","generator":"XXXX","extraGenerator":"CodeBlocks"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: Generator \"XXXX\" not supported."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","generator":"Ninja","extraGenerator":"XXXX"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"error","errorMessage":"Failed to activate protocol version: The combination of generator \"Ninja\" and extra generator \"XXXX\" is not supported."} },
-
-{ "send": {"cookie":"zimtstern","type": "handshake","protocolVersion":{"major":1},"sourceDirectory":".","buildDirectory":"/tmp/build","generator":"Ninja","extraGenerator":"CodeBlocks"} },
-{ "recv": {"cookie":"zimtstern","inReplyTo":"handshake","type":"reply"} },
-
-{ "message": "Everything ok." }
-]
diff --git a/Tests/SetLang/CMakeLists.txt b/Tests/SetLang/CMakeLists.txt
index 9de4fc61d..3eb918542 100644
--- a/Tests/SetLang/CMakeLists.txt
+++ b/Tests/SetLang/CMakeLists.txt
@@ -15,3 +15,11 @@ if(CMAKE_GENERATOR MATCHES "^Visual Studio" AND "x${CMAKE_C_COMPILER_ID}" STREQU
add_library(stay stay_c.c stay_cxx.cxx)
set_property(TARGET stay PROPERTY COMPILE_OPTIONS "-TP")
endif()
+
+if((CMAKE_C_COMPILER_ID MATCHES "(GNU|Clang|MSVC|Borland|Embarcadero|Intel|TI|XL)"))
+ cmake_policy(SET CMP0119 NEW)
+ add_library(zoom zoom.zzz)
+ set_source_files_properties(zoom.zzz PROPERTIES LANGUAGE CXX)
+ target_link_libraries(SetLang zoom)
+ target_compile_definitions(SetLang PRIVATE WITH_ZOOM)
+endif()
diff --git a/Tests/SetLang/bar.c b/Tests/SetLang/bar.c
index b934356fa..515e8c233 100644
--- a/Tests/SetLang/bar.c
+++ b/Tests/SetLang/bar.c
@@ -1,10 +1,22 @@
#include <stdio.h>
int foo();
+
+#ifdef WITH_ZOOM
+int zoom();
+#endif
+
class A
{
public:
- A() { this->i = foo(); }
+ A()
+ {
+ this->i = foo();
+#ifdef WITH_ZOOM
+ i += zoom();
+ i -= zoom();
+#endif
+ }
int i;
};
diff --git a/Tests/SetLang/zoom.zzz b/Tests/SetLang/zoom.zzz
new file mode 100644
index 000000000..a0c8899b6
--- /dev/null
+++ b/Tests/SetLang/zoom.zzz
@@ -0,0 +1,7 @@
+int zoom()
+{
+ int r = 10;
+ r++;
+ int ret = r + 10;
+ return ret;
+}
diff --git a/Tests/UseSWIG/BasicPerl/CMakeLists.txt b/Tests/UseSWIG/BasicPerl/CMakeLists.txt
index cf02de7de..671d52984 100644
--- a/Tests/UseSWIG/BasicPerl/CMakeLists.txt
+++ b/Tests/UseSWIG/BasicPerl/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.1...3.13)
+cmake_minimum_required(VERSION 3.1...3.20)
project(TestBasicPerl CXX)
diff --git a/Tests/UseSWIG/BasicPython/CMakeLists.txt b/Tests/UseSWIG/BasicPython/CMakeLists.txt
index 8bbd1cbe8..a1163a262 100644
--- a/Tests/UseSWIG/BasicPython/CMakeLists.txt
+++ b/Tests/UseSWIG/BasicPython/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.1...3.13)
+cmake_minimum_required(VERSION 3.1...3.20)
project(TestBasicPython CXX)
diff --git a/Tests/UseSWIG/CMakeLists.txt b/Tests/UseSWIG/CMakeLists.txt
index e1502239a..d08c59ca3 100644
--- a/Tests/UseSWIG/CMakeLists.txt
+++ b/Tests/UseSWIG/CMakeLists.txt
@@ -1,3 +1,5 @@
+find_package(SWIG QUIET)
+
add_test(NAME UseSWIG.LegacyPython COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
@@ -64,6 +66,28 @@ 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")
+ add_test(NAME UseSWIG.Depfile.BasicPython COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/BasicPython"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPython.Depfile"
+ ${build_generator_args}
+ --build-project TestBasicPython
+ --build-options ${build_options} -DSWIG_USE_SWIG_DEPENDENCIES=ON
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+ add_test(NAME UseSWIG.Depfile.BasicPerl COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/BasicPerl"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPerl.Depfile"
+ ${build_generator_args}
+ --build-project TestBasicPerl
+ --build-options ${build_options} -DSWIG_USE_SWIG_DEPENDENCIES=ON
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+endif()
if (CMake_TEST_UseSWIG_Fortran)
check_language(Fortran)
diff --git a/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt
index f68e38e20..abd062836 100644
--- a/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt
+++ b/Tests/VSGNUFortran/subdir/fortran/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(FortranHello Fortran C)
# add a function to test for -lsunquad on sunpro sun systems.
@@ -33,7 +33,7 @@ FortranCInterface_HEADER(HelloWorldFCMangle.h
SYMBOLS hello world)
add_library(hello SHARED hello.f)
add_library(world SHARED world.f)
-target_link_libraries(hello world)
+target_link_libraries(hello PRIVATE world)
if(CMAKE_Fortran_COMPILER_ID MATCHES SunPro)
target_link_libraries(hello PRIVATE fsu)
if(CMAKE_Fortran_PLATFORM_ID MATCHES SunOS)
diff --git a/Tests/VSMidl/CMakeLists.txt b/Tests/VSMidl/CMakeLists.txt
index 3ff7c2705..342b8fb67 100644
--- a/Tests/VSMidl/CMakeLists.txt
+++ b/Tests/VSMidl/CMakeLists.txt
@@ -12,7 +12,7 @@ endif()
message(STATUS "CMAKE_BUILDNAME='${CMAKE_BUILDNAME}'")
message(STATUS "THIS_TESTNAME='${THIS_TESTNAME}'")
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(${THIS_TESTNAME})
include(ExternalProject)
diff --git a/Tests/VSMidl/src/CMakeLists.txt b/Tests/VSMidl/src/CMakeLists.txt
index e745fdde4..7e838b459 100644
--- a/Tests/VSMidl/src/CMakeLists.txt
+++ b/Tests/VSMidl/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
project(VSMidl)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/\$(IntDir)")
diff --git a/Tests/VSWinStorePhone/CMakeLists.txt b/Tests/VSWinStorePhone/CMakeLists.txt
index 56e4c1d4e..edd43308f 100644
--- a/Tests/VSWinStorePhone/CMakeLists.txt
+++ b/Tests/VSWinStorePhone/CMakeLists.txt
@@ -119,13 +119,13 @@ set_property(SOURCE ${RELEASE_CONTENT_FILES} PROPERTY
set_property(SOURCE ${PIXELSHADER_FILES} PROPERTY VS_SHADER_TYPE Pixel)
set_property(SOURCE ${PIXELSHADER_FILES} PROPERTY VS_SHADER_ENTRYPOINT mainPS)
set_property(SOURCE ${PIXELSHADER_FILES} PROPERTY VS_SHADER_MODEL 4.0_level_9_3)
-set_property(SOURCE ${PIXELSHADER_FILES} PROPERTY VS_SHADER_FLAGS "/DFLAGS_ADDED")
+set_property(SOURCE ${PIXELSHADER_FILES} PROPERTY VS_SHADER_FLAGS $<1:/DFLAGS_ADDED>)
set_property(SOURCE ${PIXELSHADER_FILES} PROPERTY VS_SHADER_OUTPUT_HEADER_FILE "$(OutDir)%(Filename).h")
set_property(SOURCE ${VERTEXSHADER_FILES} PROPERTY VS_SHADER_TYPE Vertex)
set_property(SOURCE ${VERTEXSHADER_FILES} PROPERTY VS_SHADER_ENTRYPOINT mainVS)
set_property(SOURCE ${VERTEXSHADER_FILES} PROPERTY VS_SHADER_MODEL 4.0_level_9_3)
-set_property(SOURCE ${VERTEXSHADER_FILES} PROPERTY VS_SHADER_FLAGS "/DFLAGS_ADDED")
+set_property(SOURCE ${VERTEXSHADER_FILES} PROPERTY VS_SHADER_FLAGS $<1:/DFLAGS_ADDED>)
set_property(SOURCE ${VERTEXSHADER_FILES} PROPERTY VS_SHADER_OUTPUT_HEADER_FILE "$(OutDir)%(Filename).h")
set_property(SOURCE ${VERTEXSHADER_FILES} PROPERTY VS_SETTINGS "$<$<CONFIG:DEBUG>:SourceProperty1=SourceProperty1Value>")
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index 5bf13f3c9..a880f7a81 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.15 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.18 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/Release/README.rst b/Utilities/Release/README.rst
index 689268315..5d8e3181e 100644
--- a/Utilities/Release/README.rst
+++ b/Utilities/Release/README.rst
@@ -6,17 +6,6 @@ on ``cmake.org``. See also the `CMake Source Code Guide`_.
.. _`CMake Source Code Guide`: ../../Help/dev/source.rst
-File Table
-----------
-
-The set of package files distributed on ``cmake.org`` varies by CMake version.
-Clients providing automatic download functionality may query the set of
-package files available using a special file that lists them:
-
-* `File Table v1`_ Documentation
-
-.. _`File Table v1`: files-v1.rst
-
Docker
------
@@ -50,7 +39,7 @@ Each ``<os>/<arch>/`` directory contains the following:
-f cmake-src/Utilities/Release/linux/x86_64/Dockerfile cmake-src
$ docker container create --name cmake-build cmake:build
$ docker cp cmake-build:/out .
- $ ls out/cmake-*-Linux-x86_64.*
+ $ ls out/cmake-*-linux-x86_64.*
On Windows, the ``win/x86`` specifications support both the ``x86_64``
and ``i386`` architectures selected via ``--build-arg ARCH=...``.
@@ -69,8 +58,8 @@ Each ``<os>/<arch>/`` directory contains the following:
FROM cmake:test-base
COPY cmake-src /opt/cmake/src/cmake
- ADD out/cmake-<ver>-Linux-x86_64.tar.gz /opt/
- ENV PATH=/opt/cmake-<ver>-Linux-x86_64/bin:$PATH
+ ADD out/cmake-<ver>-linux-x86_64.tar.gz /opt/
+ ENV PATH=/opt/cmake-<ver>-linux-x86_64/bin:$PATH
Build the test image and run it to drive testing:
diff --git a/Utilities/Release/files-sign.bash b/Utilities/Release/files-sign.bash
deleted file mode 100755
index 414859dad..000000000
--- a/Utilities/Release/files-sign.bash
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-gpg --armor --detach-sign cmake-*-SHA-256.txt
diff --git a/Utilities/Release/files-v1.json.in b/Utilities/Release/files-v1.json.in
deleted file mode 100644
index 6bafa694f..000000000
--- a/Utilities/Release/files-v1.json.in
+++ /dev/null
@@ -1,106 +0,0 @@
-{
- "version": {
- "major": @version_major@,
- "minor": @version_minor@,
- "patch": @version_patch@,
- @maybe_version_suffix@
- "string": "@version@"
- },
- "files": [
- {
- "os": ["linux", "Linux"],
- "architecture": ["aarch64"],
- "class": "installer",
- "name": "cmake-@version@-Linux-aarch64.sh"
- },
- {
- "os": ["linux", "Linux"],
- "architecture": ["aarch64"],
- "class": "archive",
- "name": "cmake-@version@-Linux-aarch64.tar.gz"
- },
- {
- "os": ["linux", "Linux"],
- "architecture": ["x86_64"],
- "class": "installer",
- "name": "cmake-@version@-Linux-x86_64.sh"
- },
- {
- "os": ["linux", "Linux"],
- "architecture": ["x86_64"],
- "class": "archive",
- "name": "cmake-@version@-Linux-x86_64.tar.gz"
- },
- {
- "os": ["macos", "macOS"],
- "architecture": ["arm64", "x86_64"],
- "class": "volume",
- "name": "cmake-@version@-macos-universal.dmg",
- "macOSmin": "10.13"
- },
- {
- "os": ["macos", "macOS"],
- "architecture": ["arm64", "x86_64"],
- "class": "archive",
- "name": "cmake-@version@-macos-universal.tar.gz",
- "macOSmin": "10.13"
- },
- {
- "os": ["macos10.10", "macOS10.10"],
- "architecture": ["arm64", "x86_64"],
- "class": "volume",
- "name": "cmake-@version@-macos10.10-universal.dmg",
- "macOSmin": "10.10"
- },
- {
- "os": ["macos10.10", "macOS10.10"],
- "architecture": ["arm64", "x86_64"],
- "class": "archive",
- "name": "cmake-@version@-macos10.10-universal.tar.gz",
- "macOSmin": "10.10"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["i386"],
- "class": "installer",
- "name": "cmake-@version@-win32-x86.msi"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["i386"],
- "class": "archive",
- "name": "cmake-@version@-win32-x86.zip"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["x86_64"],
- "class": "installer",
- "name": "cmake-@version@-win64-x64.msi"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["x86_64"],
- "class": "archive",
- "name": "cmake-@version@-win64-x64.zip"
- },
- {
- "os": ["source"],
- "architecture": [],
- "class": "archive",
- "name": "cmake-@version@.tar.gz"
- },
- {
- "os": ["source"],
- "architecture": [],
- "class": "archive",
- "name": "cmake-@version@.zip"
- }
- ],
- "hashFiles": [
- {
- "algorithm": ["sha256", "SHA-256"],
- "name": "cmake-@version@-SHA-256.txt",
- "signature": ["cmake-@version@-SHA-256.txt.asc"]
- }
- ]
-}
diff --git a/Utilities/Release/files-v1.rst b/Utilities/Release/files-v1.rst
deleted file mode 100644
index 3b916d432..000000000
--- a/Utilities/Release/files-v1.rst
+++ /dev/null
@@ -1,166 +0,0 @@
-File Table v1
-*************
-
-The set of package files distributed on ``cmake.org`` varies by CMake version.
-One file, named ``cmake-<ver>-files-v1.json``, contains a table of the package
-files available for a given version. Clients may use this to find other files.
-
-Format
-------
-
-The format is a JSON object:
-
-.. code-block:: json
-
- {
- "version": {
- "major": 3, "minor": 18, "patch": 6,
- "string": "3.18.6"
- },
- "files": [
- {
- "os": ["...", "..."],
- "architecture": ["...", "..."],
- "class": "...",
- "name": "..."
- }
- ],
- "hashFiles": [
- {
- "algorithm": ["...", "..."],
- "name": "cmake-<version>-<algo>.txt",
- "signature": ["cmake-<version>-<algo>.txt.asc"]
- }
- ]
- }
-
-The members are:
-
-``version``
- A JSON object specifying the version of CMake with members:
-
- ``major``, ``minor``, ``patch``
- Integer values specifying the major, minor, and patch version components.
-
- ``suffix``
- A string specifying the version suffix, if any, e.g. ``rc1``.
-
- ``string``
- A string specifying the full version in the format
- ``<major>.<minor>.<patch>[-<suffix>]``.
-
-``files``
- A JSON array of entries corresponding to available package files.
- Each entry is a JSON object containing members:
-
- ``os``
- A JSON array of strings naming the operating system for which the
- package file is built, possibly using multiple alternative spellings.
- Possible names include:
-
- ``source``
- Source packages.
-
- ``Linux``, ``linux``
- Linux packages.
-
- ``macOS``, ``macos``
- macOS packages.
-
- ``Windows``, ``windows``
- Windows packages.
-
- ``architecture``
- A JSON array of strings naming the architecture(s) for which the
- package file is built, possibly using multiple alternative spellings.
- Source packages have an empty list of architectures (``[]``).
- Binary packages have a non-empty list of architectures, with at least
- one name matching the output of ``uname -m`` on corresponding hosts.
- On Windows, architecture names include ``x86_64`` and ``i386``.
- On macOS, universal binary packages list all architectures,
- e.g. ``["arm64","x86_64"]``.
-
- ``class``
- A JSON string naming the class of package. The value is one of:
-
- ``archive``
- A tarball or zip archive.
- The extension, such as ``.tar.gz`` or ``.zip``, indicates the format.
- The rest of the file name matches the top-level directory in the archive.
-
- ``installer``
- An interactive installer.
-
- ``volume``
- A disk image (``.dmg`` on macOS).
-
- ``name``
- A JSON string specifying the name of the package file.
-
- ``macOSmin``
- Optional member that is present on package files for macOS.
- The value is a JSON string specifying the minimum version of macOS
- required to run the binary, e.g. ``"10.13"``.
-
-``hashFiles``
- A JSON array of entries corresponding to files containing cryptographic
- hashes of the package file contents. Each entry is a JSON object
- containing members:
-
- ``algorithm``
- A JSON array of strings naming a cryptographic hash algorithm, possibly
- using multiple alternative spellings, e.g. ``["sha256", "SHA-256"]``.
-
- ``name``
- A JSON string specifying the name of the file containing hashes,
- e.g. ``"cmake-<version>-SHA-256.txt"``.
-
- ``signature``
- A JSON array of strings naming files containing a cryptographic
- signature of the hash file specified by ``name``, e.g.
- ``["cmake-<version>-SHA-256.txt.asc"]``.
-
-The table and hash files are generated by `files.bash`_ from
-the `files-v1.json.in`_ template and the package files themselves.
-
-.. _`files.bash`: files.bash
-.. _`files-v1.json.in`: files-v1.json.in
-
-Queries
--------
-
-Clients may download the `File Table v1`_ file ``cmake-<ver>-files-v1.json``
-and query it to get the name(s) of specific package files adjacent to it.
-Make queries as specific as possible in order to account for additional
-alternative binaries in future CMake versions.
-
-For example, one may use ``jq`` queries:
-
-* To select a Windows binary archive supporting ``x86_64`` hosts::
-
- .files[] | select((.os[] | . == "windows") and
- (.architecture[] | . == "x86_64") and
- (.class == "archive")) | .name
-
-* To select a Linux binary archive supporting ``aarch64`` hosts::
-
- .files[] | select((.os[] | . == "linux") and
- (.architecture[] | . == "aarch64") and
- (.class == "archive")) | .name
-
-* To select a macOS binary archive supporting ``arm64`` hosts::
-
- .files[] | select((.os[] | . == "macos") and
- (.architecture[] | . == "arm64") and
- (.class == "archive")) | .name
-
-* To select a macOS binary archive supporting macOS 10.12 on ``x86_64`` hosts::
-
- .files[] | select((.os[] | contains("macOS")) and
- (.architecture[] | . == "x86_64") and
- ([.macOSmin] | inside(["10.10", "10.11", "10.12"]))
- ) | .name
-
-* To select a SHA-256 hash file::
-
- .hashFiles[] | select(.algorithm[] | . == "SHA-256") | .name
diff --git a/Utilities/Release/files.bash b/Utilities/Release/files.bash
deleted file mode 100755
index 28ca8f1b0..000000000
--- a/Utilities/Release/files.bash
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-usage='usage: files.bash [<options>] [--]
-
-Options:
-
- --version <ver> CMake <major>.<minor> version number to push.
- Defaults to version of source tree.
-'
-
-die() {
- echo "$@" 1>&2; exit 1
-}
-
-readonly cmake_source_dir="${BASH_SOURCE%/*}/../.."
-
-cmake_version_component()
-{
- sed -n "
-/^set(CMake_VERSION_${1}/ {s/set(CMake_VERSION_${1} *\([0-9]*\))/\1/;p;}
-" "${cmake_source_dir}/Source/CMakeVersion.cmake"
-}
-
-
-version=''
-while test "$#" != 0; do
- case "$1" in
- --version) shift; version="$1" ;;
- --) shift ; break ;;
- -*) die "$usage" ;;
- *) break ;;
- esac
- shift
-done
-test "$#" = 0 || die "$usage"
-
-if test -z "$version"; then
- cmake_version_major="$(cmake_version_component MAJOR)"
- cmake_version_minor="$(cmake_version_component MINOR)"
- cmake_version_patch="$(cmake_version_component PATCH)"
- cmake_version_rc="$(cmake_version_component RC)"
- version="${cmake_version_major}.${cmake_version_minor}.${cmake_version_patch}"
- if test -n "$cmake_version_rc"; then
- version="$version-rc$cmake_version_rc"
- fi
-fi
-readonly version
-
-IFS='.-' read version_major version_minor version_patch version_suffix <<< "$version"
-readonly version_major
-readonly version_minor
-readonly version_patch
-readonly version_suffix
-
-if test -n "$version_suffix"; then
- maybe_version_suffix='"suffix": "'"$version_suffix"'",'
-else
- maybe_version_suffix=''
-fi
-readonly maybe_version_suffix
-
-readonly files_v1_in="${BASH_SOURCE%/*}/files-v1.json.in"
-sed "
- s/@version@/$version/g
- s/@version_major@/$version_major/g
- s/@version_minor@/$version_minor/g
- s/@version_patch@/$version_patch/g
- s/@maybe_version_suffix@/$maybe_version_suffix/g
-" "$files_v1_in" \
- | jq . \
- > "cmake-$version-files-v1.json"
-
-readonly algos='
- 256
-'
-for algo in $algos; do
- shasum -a $algo \
- "cmake-$version-files-v1.json" \
- $(jq -r '.files[].name' "cmake-$version-files-v1.json") \
- | LC_ALL=C sort -k 2 \
- > "cmake-$version-SHA-$algo.txt"
-done
diff --git a/Utilities/Release/linux/aarch64/Dockerfile b/Utilities/Release/linux/aarch64/Dockerfile
index 4077b79de..9abae2ab6 100644
--- a/Utilities/Release/linux/aarch64/Dockerfile
+++ b/Utilities/Release/linux/aarch64/Dockerfile
@@ -5,7 +5,7 @@
# Build using the CMake source directory as the build context.
# The resulting image will have an '/out' directory containing the package.
-# Keep this in sync with the `.gitlab-ci.yml` `release_linux` image.
+# Keep this in sync with the `.gitlab/os-linux.yml` `.linux_release_aarch64` image.
ARG FROM_IMAGE_NAME=kitware/cmake:build-linux-aarch64-deps-2020-12-21
ARG FROM_IMAGE_DIGEST=@sha256:0bd7dfe4e45593b04e39cd21e44011034610cfd376900558c5ef959bb1af15af
ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST
@@ -31,5 +31,5 @@ RUN : \
&& bin/cpack -G STGZ \
&& set +x \
&& mkdir /out \
- && mv cmake-*-Linux-aarch64.* /out \
+ && mv cmake-*-linux-aarch64.* /out \
&& :
diff --git a/Utilities/Release/linux/aarch64/cache.txt b/Utilities/Release/linux/aarch64/cache.txt
index 89050d1f1..0c2d9954f 100644
--- a/Utilities/Release/linux/aarch64/cache.txt
+++ b/Utilities/Release/linux/aarch64/cache.txt
@@ -41,4 +41,4 @@ CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=Linux-aarch64
+CPACK_SYSTEM_NAME:STRING=linux-aarch64
diff --git a/Utilities/Release/linux/x86_64/Dockerfile b/Utilities/Release/linux/x86_64/Dockerfile
index 972913e3c..8c98d3e4b 100644
--- a/Utilities/Release/linux/x86_64/Dockerfile
+++ b/Utilities/Release/linux/x86_64/Dockerfile
@@ -5,7 +5,7 @@
# Build using the CMake source directory as the build context.
# The resulting image will have an '/out' directory containing the package.
-# Keep this in sync with the `.gitlab-ci.yml` `release_linux` image.
+# Keep this in sync with the `.gitlab/os-linux.yml` `.linux_release_x86_64` image.
ARG FROM_IMAGE_NAME=kitware/cmake:build-linux-x86_64-deps-2020-04-02
ARG FROM_IMAGE_DIGEST=@sha256:77e9ab183f34680990db9da5945473e288f0d6556bce79ecc1589670d656e157
ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST
@@ -32,5 +32,5 @@ RUN : \
&& bin/cpack -G STGZ \
&& set +x \
&& mkdir /out \
- && mv cmake-*-Linux-x86_64.* /out \
+ && mv cmake-*-linux-x86_64.* /out \
&& :
diff --git a/Utilities/Release/linux/x86_64/cache.txt b/Utilities/Release/linux/x86_64/cache.txt
index a2864e98b..e1f9fe337 100644
--- a/Utilities/Release/linux/x86_64/cache.txt
+++ b/Utilities/Release/linux/x86_64/cache.txt
@@ -41,4 +41,4 @@ CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=Linux-x86_64
+CPACK_SYSTEM_NAME:STRING=linux-x86_64
diff --git a/Utilities/Release/win/x86/cache-i386.txt b/Utilities/Release/win/x86/cache-i386.txt
index 3c0ecc70e..54a45d8fc 100644
--- a/Utilities/Release/win/x86/cache-i386.txt
+++ b/Utilities/Release/win/x86/cache-i386.txt
@@ -42,4 +42,4 @@ CMAKE_Swift_COMPILER:FILEPATH=FALSE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=win32-x86
+CPACK_SYSTEM_NAME:STRING=windows-i386
diff --git a/Utilities/Release/win/x86/cache-x86_64.txt b/Utilities/Release/win/x86/cache-x86_64.txt
index 2ccf93b5c..0b78c72b9 100644
--- a/Utilities/Release/win/x86/cache-x86_64.txt
+++ b/Utilities/Release/win/x86/cache-x86_64.txt
@@ -42,4 +42,4 @@ CMAKE_Swift_COMPILER:FILEPATH=FALSE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=win64-x64
+CPACK_SYSTEM_NAME:STRING=windows-x86_64
diff --git a/Utilities/Scripts/regenerate-parsers.bash b/Utilities/Scripts/regenerate-parsers.bash
index 6fb35c028..33b59f730 100755
--- a/Utilities/Scripts/regenerate-parsers.bash
+++ b/Utilities/Scripts/regenerate-parsers.bash
@@ -22,12 +22,7 @@ do
if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
echo "Generating Parser ${parser}"
- bison --yacc --name-prefix=${prefix} --defines=${h_file} -o${cxx_file} ${in_file}
- sed -i '/\/\* Else will try to reuse/ i\
-#if 0
-/^yyerrlab1:/ a\
-#endif
-' ${cxx_file}
+ bison --name-prefix=${prefix} --defines=${h_file} -o${cxx_file} ${in_file}
else
echo "Skipped generating Parser ${parser}"
fi
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 94a42e925..16cdd6575 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_72_0"
+readonly tag="curl-7_75_0"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index e5be43ad8..f989907b4 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.15 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.18 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/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index e175d0df8..ece4bf56b 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -191,6 +191,7 @@ _cmake_index_objs = {
'cpack_gen': _cmake_index_entry('cpack generator'),
'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
+ 'genex': _cmake_index_entry('genex'),
'guide': _cmake_index_entry('guide'),
'manual': _cmake_index_entry('manual'),
'module': _cmake_index_entry('module'),
@@ -224,7 +225,7 @@ class CMakeTransform(Transform):
self.titles = {}
def parse_title(self, docname):
- """Parse a document title as the first line starting in [A-Za-z0-9<]
+ """Parse a document title as the first line starting in [A-Za-z0-9<$]
or fall back to the document basename if no such line exists.
The cmake --help-*-list commands also depend on this convention.
Return the title or False if the document file does not exist.
@@ -239,7 +240,7 @@ class CMakeTransform(Transform):
title = False
else:
for line in f:
- if len(line) > 0 and (line[0].isalnum() or line[0] == '<'):
+ if len(line) > 0 and (line[0].isalnum() or line[0] == '<' or line[0] == '$'):
title = line.rstrip()
break
f.close()
@@ -260,6 +261,10 @@ class CMakeTransform(Transform):
if objtype == 'command':
targetname = title.lower()
else:
+ if objtype == 'genex':
+ m = CMakeXRefRole._re_genex.match(title)
+ if m:
+ title = m.group(1)
targetname = title
targetid = '%s:%s' % (objtype, targetname)
targetnode = nodes.target('', '', ids=[targetid])
@@ -277,6 +282,10 @@ class CMakeObject(ObjectDescription):
def handle_signature(self, sig, signode):
# called from sphinx.directives.ObjectDescription.run()
signode += addnodes.desc_name(sig, sig)
+ if self.objtype == 'genex':
+ m = CMakeXRefRole._re_genex.match(sig)
+ if m:
+ sig = m.group(1)
return sig
def add_target_and_index(self, name, sig, signode):
@@ -302,6 +311,7 @@ class CMakeXRefRole(XRefRole):
# See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
_re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
_re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL)
+ _re_genex = re.compile(r'^\$<([^<>:]+)(:[^<>]+)?>$', re.DOTALL)
def __call__(self, typ, rawtext, text, *args, **keys):
# Translate CMake command cross-references of the form:
@@ -312,6 +322,10 @@ class CMakeXRefRole(XRefRole):
m = CMakeXRefRole._re_sub.match(text)
if m:
text = '%s <%s>' % (text, m.group(1))
+ elif typ == 'cmake:genex':
+ m = CMakeXRefRole._re_genex.match(text)
+ if m:
+ text = '%s <%s>' % (text, m.group(1))
# CMake cross-reference targets frequently contain '<' so escape
# any explicit `<target>` with '<' not preceded by whitespace.
while True:
@@ -374,6 +388,7 @@ class CMakeDomain(Domain):
'cpack_gen': ObjType('cpack_gen', 'cpack_gen'),
'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
+ 'genex': ObjType('genex', 'genex'),
'guide': ObjType('guide', 'guide'),
'variable': ObjType('variable', 'variable'),
'module': ObjType('module', 'module'),
@@ -390,6 +405,7 @@ class CMakeDomain(Domain):
directives = {
'command': CMakeObject,
'envvar': CMakeObject,
+ 'genex': CMakeObject,
'variable': CMakeObject,
# Other object types cannot be created except by the CMakeTransform
# 'generator': CMakeObject,
@@ -409,6 +425,7 @@ class CMakeDomain(Domain):
'cpack_gen': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
+ 'genex': CMakeXRefRole(),
'guide': CMakeXRefRole(),
'variable': CMakeXRefRole(),
'module': CMakeXRefRole(),
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 42b095162..5def681dc 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -29,6 +29,7 @@ extensions = ['cmake']
templates_path = ['@conf_path@/templates']
nitpicky = True
+smartquotes = False
cmake_manuals = sorted(glob.glob(r'@conf_docs@/manual/*.rst'))
cmake_manual_description = re.compile('^\.\. cmake-manual-description:(.*)$')
diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py
index e35f12770..0ff39a0c2 100755
--- a/Utilities/Sphinx/create_identifiers.py
+++ b/Utilities/Sphinx/create_identifiers.py
@@ -25,6 +25,7 @@ for line in lines:
("envvar", "envvar"),
("variable", "variable"),
("generator", "generator"),
+ ("genex", "genex"),
("guide", "guide"),
("target property", "prop_tgt"),
("test property", "prop_test"),
diff --git a/Utilities/Sphinx/static/cmake.css b/Utilities/Sphinx/static/cmake.css
index b082edec8..029eb1b2f 100644
--- a/Utilities/Sphinx/static/cmake.css
+++ b/Utilities/Sphinx/static/cmake.css
@@ -16,3 +16,9 @@ div.sphinxsidebarwrapper {
.literal-block a.reference.internal {
background-color: #dfdfdf;
}
+
+/* Remove unwanted margin in case list item contains a div-wrapping
+ directive like `.. versionadded` or `.. deprecated`. */
+dd > :first-child > p {
+ margin-top: 0px;
+}
diff --git a/Utilities/cmbzip2/CMakeLists.txt b/Utilities/cmbzip2/CMakeLists.txt
index cb4a038fa..9b53b0f12 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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/CMakeConfigurableFile.in b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
index 2bafe2c10..8ccd016a6 100644
--- a/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
+++ b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
index aaac9fead..e99ea6f64 100644
--- a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
+++ b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
@@ -27,7 +27,7 @@ mark_as_advanced(CURL_HIDDEN_SYMBOLS)
if(CURL_HIDDEN_SYMBOLS)
set(SUPPORTS_SYMBOL_HIDING FALSE)
- if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT MSVC)
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index 3ef35f025..949910d5e 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/CMake/FindBearSSL.cmake b/Utilities/cmcurl/CMake/FindBearSSL.cmake
index a8f72c92d..9455f4ba3 100644
--- a/Utilities/cmcurl/CMake/FindBearSSL.cmake
+++ b/Utilities/cmcurl/CMake/FindBearSSL.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindBrotli.cmake b/Utilities/cmcurl/CMake/FindBrotli.cmake
index c43172b64..0ed08550d 100644
--- a/Utilities/cmcurl/CMake/FindBrotli.cmake
+++ b/Utilities/cmcurl/CMake/FindBrotli.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindCARES.cmake b/Utilities/cmcurl/CMake/FindCARES.cmake
index 9160ae5fd..71806823d 100644
--- a/Utilities/cmcurl/CMake/FindCARES.cmake
+++ b/Utilities/cmcurl/CMake/FindCARES.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindGSS.cmake b/Utilities/cmcurl/CMake/FindGSS.cmake
index 02111a20f..4e4747d6c 100644
--- a/Utilities/cmcurl/CMake/FindGSS.cmake
+++ b/Utilities/cmcurl/CMake/FindGSS.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindLibSSH2.cmake b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
index 4cdf3e310..ce46a408b 100644
--- a/Utilities/cmcurl/CMake/FindLibSSH2.cmake
+++ b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindMbedTLS.cmake b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
index 2ebe721a6..1746093df 100644
--- a/Utilities/cmcurl/CMake/FindMbedTLS.cmake
+++ b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
index e1eba0532..8614492b1 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
index 73ce9e188..643b60097 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNGTCP2.cmake b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
index a1ed8cd4b..5757009a5 100644
--- a/Utilities/cmcurl/CMake/FindNGTCP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNSS.cmake b/Utilities/cmcurl/CMake/FindNSS.cmake
index 5fdb2b776..899c6b075 100644
--- a/Utilities/cmcurl/CMake/FindNSS.cmake
+++ b/Utilities/cmcurl/CMake/FindNSS.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindQUICHE.cmake b/Utilities/cmcurl/CMake/FindQUICHE.cmake
index 01d17582b..0247364d4 100644
--- a/Utilities/cmcurl/CMake/FindQUICHE.cmake
+++ b/Utilities/cmcurl/CMake/FindQUICHE.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindWolfSSL.cmake b/Utilities/cmcurl/CMake/FindWolfSSL.cmake
index 54df1a86c..42256b3cd 100644
--- a/Utilities/cmcurl/CMake/FindWolfSSL.cmake
+++ b/Utilities/cmcurl/CMake/FindWolfSSL.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindZstd.cmake b/Utilities/cmcurl/CMake/FindZstd.cmake
index 44c741ae8..eaba39746 100644
--- a/Utilities/cmcurl/CMake/FindZstd.cmake
+++ b/Utilities/cmcurl/CMake/FindZstd.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/Macros.cmake b/Utilities/cmcurl/CMake/Macros.cmake
index 65a41e484..d57dd6ad5 100644
--- a/Utilities/cmcurl/CMake/Macros.cmake
+++ b/Utilities/cmcurl/CMake/Macros.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
@@ -107,3 +107,14 @@ macro(curl_nroff_check)
message(WARNING "Found no *nroff program")
endif()
endmacro()
+
+macro(optional_dependency DEPENDENCY)
+ set(CURL_${DEPENDENCY} AUTO CACHE STRING "Build curl with ${DEPENDENCY} support (AUTO, ON or OFF)")
+ set_property(CACHE CURL_${DEPENDENCY} PROPERTY STRINGS AUTO ON OFF)
+
+ if(CURL_${DEPENDENCY} STREQUAL AUTO)
+ find_package(${DEPENDENCY})
+ elseif(CURL_${DEPENDENCY})
+ find_package(${DEPENDENCY} REQUIRED)
+ endif()
+endmacro()
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index 8c9a49194..bbd463250 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/CMake/OtherTests.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
index 7c020bd49..9307381ef 100644
--- a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
+++ b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake
index 59b17d074..8f9b861ba 100644
--- a/Utilities/cmcurl/CMake/Utilities.cmake
+++ b/Utilities/cmcurl/CMake/Utilities.cmake
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
index 74e56a29c..d9d9c4e3a 100644
--- a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
+++ b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/curl-config.cmake.in b/Utilities/cmcurl/CMake/curl-config.cmake.in
index ae8cc30f1..957148ecc 100644
--- a/Utilities/cmcurl/CMake/curl-config.cmake.in
+++ b/Utilities/cmcurl/CMake/curl-config.cmake.in
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 4821656af..4fb93615c 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -8,6 +8,7 @@ set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2")
set(CMAKE_USE_LIBSSH OFF)
set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP")
set(CURL_BROTLI OFF)
+set(CURL_DISABLE_ALTSVC ON)
set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support")
set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth")
set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
@@ -18,6 +19,8 @@ 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?")
set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?")
+set(CURL_DISABLE_MQTT ON)
+set(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG OFF)
set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?")
set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy")
set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?")
@@ -25,7 +28,6 @@ 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_MQTT 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).")
@@ -40,9 +42,11 @@ set(ENABLE_INET_PTON OFF CACHE INTERNAL "Set to OFF to prevent usage of inet_pto
set(ENABLE_IPV6 ON CACHE INTERNAL "Enable curl IPv6 support detection")
set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual")
set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup")
+set(ENABLE_UNICODE OFF)
set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support")
set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only")
set(PICKY_COMPILER OFF CACHE INTERNAL "Enable picky compiler options")
+set(USE_LIBIDN2 ON)
set(USE_NGHTTP2 ON)
set(USE_NGTCP2 OFF)
set(USE_QUICHE OFF)
@@ -93,7 +97,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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
@@ -106,11 +110,11 @@ endif()
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# 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
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
@@ -146,10 +150,6 @@ include(CheckCCompilerFlag)
project(CURL C)
-if(0) # This code not needed for building within CMake.
-message(WARNING "the curl cmake build system is poorly maintained. Be aware")
-endif()
-
file(STRINGS ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS REGEX "#define LIBCURL_VERSION( |_NUM )")
string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
CURL_VERSION ${CURL_VERSION_H_CONTENTS})
@@ -168,7 +168,7 @@ endif()
# SET(PACKAGE_NAME "curl")
# SET(PACKAGE_VERSION "-")
# SET(PACKAGE_STRING "curl-")
-# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/")
+# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.se/mail/")
set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
set(OS "\"${CMAKE_SYSTEM_NAME}\"")
@@ -182,6 +182,7 @@ option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
+ option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF)
if(0) # This code not needed for building within CMake.
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
if(CURL_TARGET_WINDOWS_VERSION)
@@ -197,6 +198,12 @@ if(WIN32)
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0501")
endif()
endif()
+ if(ENABLE_UNICODE)
+ add_definitions(-DUNICODE -D_UNICODE)
+ if(MINGW)
+ add_compile_options(-municode)
+ endif()
+ endif()
endif()
option(CURL_LTO "Turn on compiler Link Time Optimizations" OFF)
@@ -294,28 +301,30 @@ option(CURL_DISABLE_SMTP "to disable SMTP" OFF)
mark_as_advanced(CURL_DISABLE_SMTP)
option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
mark_as_advanced(CURL_DISABLE_GOPHER)
-option(CURL_ENABLE_MQTT "to enable MQTT" OFF)
-mark_as_advanced(CURL_ENABLE_MQTT)
+option(CURL_DISABLE_MQTT "to disable MQTT" OFF)
+mark_as_advanced(CURL_DISABLE_MQTT)
if(HTTP_ONLY)
+ set(CURL_DISABLE_DICT ON)
+ set(CURL_DISABLE_FILE ON)
set(CURL_DISABLE_FTP ON)
+ set(CURL_DISABLE_GOPHER ON)
+ set(CURL_DISABLE_IMAP ON)
set(CURL_DISABLE_LDAP ON)
set(CURL_DISABLE_LDAPS ON)
- set(CURL_DISABLE_TELNET ON)
- set(CURL_DISABLE_DICT ON)
- set(CURL_DISABLE_FILE ON)
- set(CURL_DISABLE_TFTP ON)
- set(CURL_DISABLE_RTSP ON)
+ set(CURL_DISABLE_MQTT ON)
set(CURL_DISABLE_POP3 ON)
- set(CURL_DISABLE_IMAP ON)
+ set(CURL_DISABLE_RTSP ON)
set(CURL_DISABLE_SMB ON)
set(CURL_DISABLE_SMTP ON)
- set(CURL_DISABLE_GOPHER ON)
+ set(CURL_DISABLE_TELNET ON)
+ set(CURL_DISABLE_TFTP ON)
endif()
+option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF)
+mark_as_advanced(CURL_DISABLE_ALTSVC)
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)
mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF)
@@ -352,10 +361,6 @@ if(ENABLE_MANUAL)
endif()
endif()
-# We need ansi c-flags, especially on HP
-set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
-set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
-
if(CURL_STATIC_CRT)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
@@ -454,6 +459,7 @@ set(openssl_default ON)
if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_SCHANNEL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL)
set(openssl_default OFF)
endif()
+option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF)
count_true(enabled_ssl_options_count
CMAKE_USE_SCHANNEL
@@ -741,34 +747,35 @@ if(NOT CURL_DISABLE_LDAPS)
endif()
# Check for idn
-check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
+option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
+set(HAVE_LIBIDN2 OFF)
+if(USE_LIBIDN2)
+ check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
+endif()
# Check for symbol dlopen (same as HAVE_LIBDL)
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
if(0) # This code not needed for building within CMake.
-option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
set(USE_ZLIB OFF)
-if(CURL_ZLIB)
- find_package(ZLIB QUIET)
- if(ZLIB_FOUND)
- set(HAVE_ZLIB_H ON)
- set(HAVE_LIBZ ON)
- set(USE_ZLIB ON)
-
- # Depend on ZLIB via imported targets if supported by the running
- # version of CMake. This allows our dependents to get our dependencies
- # transitively.
- if(NOT CMAKE_VERSION VERSION_LESS 3.4)
- list(APPEND CURL_LIBS ZLIB::ZLIB)
- else()
- list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
- include_directories(${ZLIB_INCLUDE_DIRS})
- endif()
- list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
+optional_dependency(ZLIB)
+if(ZLIB_FOUND)
+ set(HAVE_ZLIB_H ON)
+ set(HAVE_LIBZ ON)
+ set(USE_ZLIB ON)
+
+ # Depend on ZLIB via imported targets if supported by the running
+ # version of CMake. This allows our dependents to get our dependencies
+ # transitively.
+ if(NOT CMAKE_VERSION VERSION_LESS 3.4)
+ list(APPEND CURL_LIBS ZLIB::ZLIB)
+ else()
+ list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
+ include_directories(${ZLIB_INCLUDE_DIRS})
endif()
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
endif()
endif()
@@ -911,6 +918,7 @@ if(CMAKE_USE_GSSAPI)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
+ set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
list(APPEND CURL_LIBS ${GSS_LIBRARIES})
else()
@@ -926,8 +934,6 @@ else()
unset(USE_UNIX_SOCKETS CACHE)
endif()
-option(ENABLE_ALT_SVC "Enable alt-svc support" OFF)
-set(USE_ALTSVC ${ENABLE_ALT_SVC})
if(0) # This code not needed for building within CMake.
#
@@ -1055,6 +1061,7 @@ check_include_file_concat("net/if.h" HAVE_NET_IF_H)
check_include_file_concat("netdb.h" HAVE_NETDB_H)
check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H)
check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H)
+check_include_file("linux/tcp.h" HAVE_LINUX_TCP_H)
check_include_file_concat("pem.h" HAVE_PEM_H)
check_include_file_concat("poll.h" HAVE_POLL_H)
@@ -1465,16 +1472,16 @@ install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl)
#-----------------------------------------------------------------------------
if(0) # This code not needed for building within CMake.
-option(BUILD_TESTING "Build tests" "${PERL_FOUND}")
-if(NOT PERL_FOUND)
- message(STATUS "Perl not found, testing disabled.")
-elseif(BUILD_TESTING)
+cmake_dependent_option(BUILD_TESTING "Build tests"
+ ON "PERL_FOUND;NOT CURL_DISABLE_TESTS"
+ OFF)
+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_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO))
+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)
@@ -1493,7 +1500,7 @@ endmacro()
set(_items)
_add_if("SSL" SSL_ENABLED)
_add_if("IPv6" ENABLE_IPV6)
-_add_if("unix-sockets" USE_UNIX_SOCKETS)
+_add_if("unixsockets" USE_UNIX_SOCKETS)
_add_if("libz" HAVE_LIBZ)
_add_if("brotli" HAVE_BROTLI)
_add_if("zstd" HAVE_ZSTD)
@@ -1504,7 +1511,7 @@ _add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
# TODO SSP1 (Schannel) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
-_add_if("alt-svc" ENABLE_ALT_SVC)
+_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
# TODO SSP1 missing for SPNEGO
_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
@@ -1512,7 +1519,7 @@ _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)
+_add_if("NTLM" use_ntlm 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)
# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
@@ -1522,6 +1529,7 @@ _add_if("HTTP2" USE_NGHTTP2)
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
+_add_if("unicode" ENABLE_UNICODE)
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
@@ -1542,6 +1550,7 @@ _add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
_add_if("DICT" NOT CURL_DISABLE_DICT)
_add_if("TFTP" NOT CURL_DISABLE_TFTP)
_add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
+_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
_add_if("POP3" NOT CURL_DISABLE_POP3)
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
@@ -1554,7 +1563,7 @@ _add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
_add_if("RTMP" USE_LIBRTMP)
-_add_if("MQTT" CURL_ENABLE_MQTT)
+_add_if("MQTT" NOT CURL_DISABLE_MQTT)
if(_items)
list(SORT _items)
endif()
diff --git a/Utilities/cmcurl/COPYING b/Utilities/cmcurl/COPYING
index 9d9e4af8d..48f144758 100644
--- a/Utilities/cmcurl/COPYING
+++ b/Utilities/cmcurl/COPYING
@@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE
-Copyright (c) 1996 - 2020, Daniel Stenberg, <daniel@haxx.se>, and many
+Copyright (c) 1996 - 2021, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index e8e3ed137..676dce38e 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -24,7 +24,7 @@
/*
* If you have libcurl problems, all docs and details are found here:
- * https://curl.haxx.se/libcurl/
+ * https://curl.se/libcurl/
*
* curl-library mailing list subscription and unsubscription web interface:
* https://cool.haxx.se/mailman/listinfo/curl-library/
@@ -74,7 +74,7 @@
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
- defined(__CYGWIN__) || \
+ defined(__CYGWIN__) || defined(AMIGA) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
#include <sys/select.h>
#endif
@@ -610,6 +610,7 @@ typedef enum {
error */
CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */
CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */
+ CURLE_PROXY, /* 97 - proxy handshake error */
CURL_LAST /* never use! */
} CURLcode;
@@ -689,6 +690,48 @@ typedef enum {
#endif /*!CURL_NO_OLDIES*/
+/*
+ * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was
+ * return for the transfers.
+ */
+typedef enum {
+ CURLPX_OK,
+ CURLPX_BAD_ADDRESS_TYPE,
+ CURLPX_BAD_VERSION,
+ CURLPX_CLOSED,
+ CURLPX_GSSAPI,
+ CURLPX_GSSAPI_PERMSG,
+ CURLPX_GSSAPI_PROTECTION,
+ CURLPX_IDENTD,
+ CURLPX_IDENTD_DIFFER,
+ CURLPX_LONG_HOSTNAME,
+ CURLPX_LONG_PASSWD,
+ CURLPX_LONG_USER,
+ CURLPX_NO_AUTH,
+ CURLPX_RECV_ADDRESS,
+ CURLPX_RECV_AUTH,
+ CURLPX_RECV_CONNECT,
+ CURLPX_RECV_REQACK,
+ CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+ CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+ CURLPX_REPLY_CONNECTION_REFUSED,
+ CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+ CURLPX_REPLY_HOST_UNREACHABLE,
+ CURLPX_REPLY_NETWORK_UNREACHABLE,
+ CURLPX_REPLY_NOT_ALLOWED,
+ CURLPX_REPLY_TTL_EXPIRED,
+ CURLPX_REPLY_UNASSIGNED,
+ CURLPX_REQUEST_FAILED,
+ CURLPX_RESOLVE_HOST,
+ CURLPX_SEND_AUTH,
+ CURLPX_SEND_CONNECT,
+ CURLPX_SEND_REQUEST,
+ CURLPX_UNKNOWN_FAIL,
+ CURLPX_UNKNOWN_MODE,
+ CURLPX_USER_REJECTED,
+ CURLPX_LAST /* never use */
+} CURLproxycode;
+
/* This prototype applies to all conversion callbacks */
typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
@@ -744,6 +787,7 @@ typedef enum {
#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
#define CURLAUTH_BEARER (((unsigned long)1)<<6)
+#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7)
#define CURLAUTH_ONLY (((unsigned long)1)<<31)
#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
@@ -789,6 +833,7 @@ enum curl_khstat {
CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
this causes a CURLE_DEFER error but otherwise the
connection will be left intact etc */
+ CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/
CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
};
@@ -905,13 +950,42 @@ typedef enum {
#define CURLHEADER_SEPARATE (1<<0)
/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
-#define CURLALTSVC_IMMEDIATELY (1<<0)
-
#define CURLALTSVC_READONLYFILE (1<<2)
#define CURLALTSVC_H1 (1<<3)
#define CURLALTSVC_H2 (1<<4)
#define CURLALTSVC_H3 (1<<5)
+
+struct curl_hstsentry {
+ char *name;
+ size_t namelen;
+ unsigned int includeSubDomains:1;
+ char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
+};
+
+struct curl_index {
+ size_t index; /* the provided entry's "index" or count */
+ size_t total; /* total number of entries to save */
+};
+
+typedef enum {
+ CURLSTS_OK,
+ CURLSTS_DONE,
+ CURLSTS_FAIL
+} CURLSTScode;
+
+typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy,
+ struct curl_hstsentry *e,
+ void *userp);
+typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
+ struct curl_hstsentry *e,
+ struct curl_index *i,
+ void *userp);
+
+/* CURLHSTS_* are bits for the CURLOPT_HSTS option */
+#define CURLHSTS_ENABLE (long)(1<<0)
+#define CURLHSTS_READONLYFILE (long)(1<<1)
+
/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
#define CURLPROTO_HTTP (1<<0)
#define CURLPROTO_HTTPS (1<<1)
@@ -942,6 +1016,7 @@ typedef enum {
#define CURLPROTO_SMB (1<<26)
#define CURLPROTO_SMBS (1<<27)
#define CURLPROTO_MQTT (1<<28)
+#define CURLPROTO_GOPHERS (1<<29)
#define CURLPROTO_ALL (~0) /* enable everything */
/* long may be 32 or 64 bits, but we should never depend on anything else
@@ -958,17 +1033,27 @@ typedef enum {
#define CURLOPT(na,t,nu) na = t + nu
-/* handy aliases that make no run-time difference */
-#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT
+/* CURLOPT aliases that make no run-time difference */
+
+/* 'char *' argument to a string with a trailing zero */
+#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT
+
+/* 'struct curl_slist *' argument */
#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT
+/* 'void *' argument passed untouched to callback */
+#define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT
+
+/* 'long' argument with a set of values/bitmask */
+#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG
+
/*
* All CURLOPT_* values.
*/
typedef enum {
/* This is the FILE * or void * the regular output should be written to. */
- CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_OBJECTPOINT, 1),
+ CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_CBPOINT, 1),
/* The full URL to get/put */
CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2),
@@ -991,7 +1076,7 @@ typedef enum {
/* not used */
/* Specified file stream to upload from (use as input): */
- CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_OBJECTPOINT, 9),
+ CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_CBPOINT, 9),
/* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
* bytes big. */
@@ -1076,7 +1161,7 @@ typedef enum {
/* send FILE * or void * to store headers to, if you use a callback it
is simply passed to the callback unmodified */
- CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_OBJECTPOINT, 29),
+ CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29),
/* point to a file to read the initial cookies from, also enables
"cookie awareness" */
@@ -1084,10 +1169,10 @@ typedef enum {
/* What version to specifically try to use.
See CURL_SSLVERSION defines below. */
- CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_LONG, 32),
+ CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_VALUES, 32),
/* What kind of HTTP time condition to use, see defines */
- CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_LONG, 33),
+ CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_VALUES, 33),
/* Time to use with the above condition. Specified in number of seconds
since 1 Jan 1970 */
@@ -1141,7 +1226,7 @@ typedef enum {
/* Specify whether to read the user+password from the .netrc or the URL.
* This must be one of the CURL_NETRC_* enums below. */
- CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_LONG, 51),
+ CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_VALUES, 51),
/* use Location: Luke! */
CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52),
@@ -1162,8 +1247,8 @@ typedef enum {
/* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
callbacks */
- CURLOPT(CURLOPT_PROGRESSDATA, CURLOPTTYPE_OBJECTPOINT, 57),
-#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+ CURLOPT(CURLOPT_XFERINFODATA, CURLOPTTYPE_CBPOINT, 57),
+#define CURLOPT_PROGRESSDATA CURLOPT_XFERINFODATA
/* We want the referrer field set automatically when following locations */
CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58),
@@ -1258,7 +1343,7 @@ typedef enum {
/* Specify which HTTP version to use! This must be set to one of the
CURL_HTTP_VERSION* enums set below. */
- CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_LONG, 84),
+ CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_VALUES, 84),
/* Specifically switch on or off the FTP engine's use of the EPSV command. By
default, that one will always be attempted before the more traditional
@@ -1296,7 +1381,7 @@ typedef enum {
CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94),
/* set the data for the debug function */
- CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_OBJECTPOINT, 95),
+ CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_CBPOINT, 95),
/* mark this as start of a cookie session */
CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96),
@@ -1319,7 +1404,7 @@ typedef enum {
/* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
CURLPROXY_SOCKS5. */
- CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_LONG, 101),
+ CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_VALUES, 101),
/* Set the Accept-Encoding string. Use this to tell a server you would like
the response to be compressed. Before 7.21.6, this was known as
@@ -1345,7 +1430,7 @@ typedef enum {
/* Set this to a bitmask value to enable the particular authentications
methods you like. Use this in combination with CURLOPT_USERPWD.
Note that setting multiple bits may cause extra network round-trips. */
- CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_LONG, 107),
+ CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_VALUES, 107),
/* Set the ssl context callback function, currently only for OpenSSL or
WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument.
@@ -1354,7 +1439,7 @@ typedef enum {
/* Set the userdata for the ssl context callback function's third
argument */
- CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_OBJECTPOINT, 109),
+ CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_CBPOINT, 109),
/* FTP Option that causes missing dirs to be created on the remote server.
In 7.19.4 we introduced the convenience enums for this option using the
@@ -1365,7 +1450,7 @@ typedef enum {
/* Set this to a bitmask value to enable the particular authentications
methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
Note that setting multiple bits may cause extra network round-trips. */
- CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_LONG, 111),
+ CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111),
/* FTP option that changes the timeout, in seconds, associated with
getting a response. This is different from transfer timeout time and
@@ -1377,7 +1462,7 @@ typedef enum {
/* 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. */
- CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_LONG, 113),
+ CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113),
/* Set this option to limit the size of a file that will be downloaded from
an HTTP or FTP server.
@@ -1412,7 +1497,7 @@ typedef enum {
CURLUSESSL_CONTROL - SSL for the control connection or fail
CURLUSESSL_ALL - SSL for all communication or fail
*/
- CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_LONG, 119),
+ CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119),
/* The _LARGE version of the standard POSTFIELDSIZE option */
CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120),
@@ -1438,10 +1523,10 @@ typedef enum {
CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
*/
- CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_LONG, 129),
+ CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129),
CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130),
- CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_OBJECTPOINT, 131),
+ CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131),
/* 132 OBSOLETE. Gone in 7.16.0 */
/* 133 OBSOLETE. Gone in 7.16.0 */
@@ -1464,7 +1549,7 @@ typedef enum {
/* Select "file method" to use when doing FTP, see the curl_ftpmethod
above. */
- CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_LONG, 138),
+ CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_VALUES, 138),
/* Local port number to bind the socket to */
CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139),
@@ -1501,14 +1586,14 @@ typedef enum {
/* callback function for setting socket options */
CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148),
- CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_OBJECTPOINT, 149),
+ CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149),
/* set to 0 to disable session ID re-use for this transfer, default is
enabled (== 1) */
CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150),
/* allowed SSH authentication methods */
- CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_LONG, 151),
+ CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_VALUES, 151),
/* Used by scp/sftp to do public/private key authentication */
CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152),
@@ -1531,9 +1616,9 @@ typedef enum {
CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159),
CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160),
- /* Set the behaviour of POST when redirecting. Values must be set to one
+ /* Set the behavior of POST when redirecting. Values must be set to one
of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
- CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_LONG, 161),
+ CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161),
/* used by scp/sftp to verify the host's public key */
CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162),
@@ -1543,7 +1628,7 @@ typedef enum {
CURL_SOCKET_BAD. The callback should have type
curl_opensocket_callback */
CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163),
- CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 164),
+ CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_CBPOINT, 164),
/* POST volatile input fields. */
CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165),
@@ -1553,7 +1638,7 @@ typedef enum {
/* Callback function for seeking in the input stream */
CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167),
- CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_OBJECTPOINT, 168),
+ CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_CBPOINT, 168),
/* CRL file */
CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169),
@@ -1614,7 +1699,7 @@ typedef enum {
CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184),
/* set the SSH host key callback custom pointer */
- CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_OBJECTPOINT, 185),
+ CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_CBPOINT, 185),
/* set the SMTP mail originator */
CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186),
@@ -1626,7 +1711,7 @@ typedef enum {
CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188),
/* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
- CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_LONG, 189),
+ CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_VALUES, 189),
/* The RTSP session identifier */
CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190),
@@ -1644,7 +1729,7 @@ typedef enum {
CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194),
/* The stream to pass to INTERLEAVEFUNCTION. */
- CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_OBJECTPOINT, 195),
+ CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_CBPOINT, 195),
/* Let the application define a custom write method for RTP data */
CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196),
@@ -1664,10 +1749,10 @@ typedef enum {
CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200),
/* Let the application define custom chunk data pointer */
- CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_OBJECTPOINT, 201),
+ CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_CBPOINT, 201),
/* FNMATCH_FUNCTION user pointer */
- CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_OBJECTPOINT, 202),
+ CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_CBPOINT, 202),
/* send linked-list of name:port:address sets */
CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203),
@@ -1696,10 +1781,10 @@ typedef enum {
/* Callback function for closing socket (instead of close(2)). The callback
should have type curl_closesocket_callback */
CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208),
- CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 209),
+ CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_CBPOINT, 209),
/* allow GSSAPI credential delegation */
- CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_LONG, 210),
+ CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210),
/* Set the name servers to use for DNS resolution */
CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211),
@@ -1716,7 +1801,7 @@ typedef enum {
CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215),
/* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
- CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_LONG, 216),
+ CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_VALUES, 216),
/* Set the SMTP auth originator */
CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217),
@@ -1763,7 +1848,7 @@ typedef enum {
CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228),
/* Pass in a bitmask of "header options" */
- CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_LONG, 229),
+ CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229),
/* The public key in DER form used to validate the peer public key
this option is used only if SSL_VERIFYPEER is true */
@@ -1835,7 +1920,7 @@ typedef enum {
/* What version to specifically try to use for proxy.
See CURL_SSLVERSION defines below. */
- CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_LONG, 250),
+ CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_VALUES, 250),
/* Set a username for authenticated TLS for proxy */
CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251),
@@ -1909,7 +1994,7 @@ typedef enum {
CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272),
/* User data to pass to the resolver start callback. */
- CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_OBJECTPOINT, 273),
+ CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_CBPOINT, 273),
/* send HAProxy PROXY protocol header? */
CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274),
@@ -1940,7 +2025,7 @@ typedef enum {
CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283),
/* pointer to be passed to HTTP_TRAILER_FUNCTION */
- CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_OBJECTPOINT, 284),
+ CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_CBPOINT, 284),
/* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285),
@@ -1971,6 +2056,28 @@ typedef enum {
CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296),
CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297),
+ /* the EC curves requested by the TLS client (RFC 8422, 5.1);
+ * OpenSSL support via 'set_groups'/'set_curves':
+ * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
+ */
+ CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298),
+
+ /* HSTS bitmask */
+ CURLOPT(CURLOPT_HSTS_CTRL, CURLOPTTYPE_LONG, 299),
+ /* HSTS file name */
+ CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300),
+
+ /* HSTS read callback */
+ CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301),
+ CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302),
+
+ /* HSTS write callback */
+ CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303),
+ CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304),
+
+ /* Parameters for V4 signature */
+ CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2643,8 +2750,9 @@ typedef enum {
CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57,
CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
+ CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59,
- CURLINFO_LASTONE = 58
+ CURLINFO_LASTONE = 59
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2746,6 +2854,7 @@ typedef enum {
CURLVERSION_SIXTH,
CURLVERSION_SEVENTH,
CURLVERSION_EIGHTH,
+ CURLVERSION_NINTH,
CURLVERSION_LAST /* never actually use this */
} CURLversion;
@@ -2754,7 +2863,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_EIGHTH
+#define CURLVERSION_NOW CURLVERSION_NINTH
struct curl_version_info_data {
CURLversion age; /* age of the returned struct */
@@ -2805,6 +2914,8 @@ struct curl_version_info_data {
(MAJOR << 24) | (MINOR << 12) | PATCH */
const char *zstd_version; /* human readable string. */
+ /* These fields were added in CURLVERSION_NINTH */
+ const char *hyper_version; /* human readable string. */
};
typedef struct curl_version_info_data curl_version_info_data;
@@ -2841,6 +2952,7 @@ typedef struct curl_version_info_data curl_version_info_data;
#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */
#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 */
/*
* NAME curl_version_info()
@@ -2903,6 +3015,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#include "easy.h" /* nothing in curl is fun without the easy stuff */
#include "multi.h"
#include "urlapi.h"
+#include "options.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index a881bb7ca..71a64505a 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -30,12 +30,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.72.0"
+#define LIBCURL_VERSION "7.75.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 72
+#define LIBCURL_VERSION_MINOR 75
#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 0x074800
+#define LIBCURL_VERSION_NUM 0x074b00
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h
index 9aef13396..2dbfb26b5 100644
--- a/Utilities/cmcurl/include/curl/easy.h
+++ b/Utilities/cmcurl/include/curl/easy.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/include/curl/mprintf.h b/Utilities/cmcurl/include/curl/mprintf.h
index f615ed7d6..3549552db 100644
--- a/Utilities/cmcurl/include/curl/mprintf.h
+++ b/Utilities/cmcurl/include/curl/mprintf.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/include/curl/multi.h b/Utilities/cmcurl/include/curl/multi.h
index b911ba92d..37f9829b3 100644
--- a/Utilities/cmcurl/include/curl/multi.h
+++ b/Utilities/cmcurl/include/curl/multi.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/include/curl/options.h b/Utilities/cmcurl/include/curl/options.h
new file mode 100644
index 000000000..14373b551
--- /dev/null
+++ b/Utilities/cmcurl/include/curl/options.h
@@ -0,0 +1,68 @@
+#ifndef CURLINC_OPTIONS_H
+#define CURLINC_OPTIONS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2018 - 2020, 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.
+ *
+ ***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ CURLOT_LONG, /* long (a range of values) */
+ CURLOT_VALUES, /* (a defined set or bitmask) */
+ CURLOT_OFF_T, /* curl_off_t (a range of values) */
+ CURLOT_OBJECT, /* pointer (void *) */
+ CURLOT_STRING, /* (char * to zero terminated buffer) */
+ CURLOT_SLIST, /* (struct curl_slist *) */
+ CURLOT_CBPTR, /* (void * passed as-is to a callback) */
+ CURLOT_BLOB, /* blob (struct curl_blob *) */
+ CURLOT_FUNCTION /* function pointer */
+} curl_easytype;
+
+/* Flag bits */
+
+/* "alias" means it is provided for old programs to remain functional,
+ we prefer another name */
+#define CURLOT_FLAG_ALIAS (1<<0)
+
+/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
+ to use for curl_easy_setopt() for the given id */
+struct curl_easyoption {
+ const char *name;
+ CURLoption id;
+ curl_easytype type;
+ unsigned int flags;
+};
+
+CURL_EXTERN const struct curl_easyoption *
+curl_easy_option_by_name(const char *name);
+
+CURL_EXTERN const struct curl_easyoption *
+curl_easy_option_by_id (CURLoption id);
+
+CURL_EXTERN const struct curl_easyoption *
+curl_easy_option_next(const struct curl_easyoption *prev);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+#endif /* CURLINC_OPTIONS_H */
diff --git a/Utilities/cmcurl/include/curl/stdcheaders.h b/Utilities/cmcurl/include/curl/stdcheaders.h
index a6bdc1a25..60596c756 100644
--- a/Utilities/cmcurl/include/curl/stdcheaders.h
+++ b/Utilities/cmcurl/include/curl/stdcheaders.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index 867af6141..faf8fcf84 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index f8cb921f2..230f4c106 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -273,6 +273,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_HSTS || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
@@ -292,6 +293,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \
+ (option) == CURLOPT_PROXY_ISSUERCERT || \
(option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
@@ -332,8 +334,10 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_URL || \
(option) == CURLOPT_USERAGENT || \
(option) == CURLOPT_USERNAME || \
+ (option) == CURLOPT_AWS_SIGV4 || \
(option) == CURLOPT_USERPWD || \
(option) == CURLOPT_XOAUTH2_BEARER || \
+ (option) == CURLOPT_SSL_EC_CURVES || \
0)
/* evaluates to true if option takes a curl_write_callback argument */
@@ -354,10 +358,11 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_FNMATCH_DATA || \
(option) == CURLOPT_HEADERDATA || \
+ (option) == CURLOPT_HSTSREADDATA || \
+ (option) == CURLOPT_HSTSWRITEDATA || \
(option) == CURLOPT_INTERLEAVEDATA || \
(option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \
- (option) == CURLOPT_PRIVATE || \
(option) == CURLOPT_PROGRESSDATA || \
(option) == CURLOPT_READDATA || \
(option) == CURLOPT_SEEKDATA || \
diff --git a/Utilities/cmcurl/include/curl/urlapi.h b/Utilities/cmcurl/include/curl/urlapi.h
index f2d06770d..7343cb659 100644
--- a/Utilities/cmcurl/include/curl/urlapi.h
+++ b/Utilities/cmcurl/include/curl/urlapi.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/CMakeLists.txt b/Utilities/cmcurl/lib/CMakeLists.txt
index 32bea68c3..703d0ad02 100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@ -9,7 +9,7 @@
#
# 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.haxx.se/docs/copyright.html.
+# 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
@@ -39,7 +39,7 @@ list(APPEND HHEADERS
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
)
-if(MSVC AND NOT CURL_STATICLIB)
+if(WIN32 AND NOT CURL_STATICLIB)
list(APPEND CSOURCES libcurl.rc)
endif()
@@ -50,15 +50,6 @@ endif()
# # strtoofft.c - specify later
# )
-# # if we have Kerberos 4, right now this is never on
-# #OPTION(CURL_KRB4 "Use Kerberos 4" OFF)
-# IF(CURL_KRB4)
-# SET(CSOURCES ${CSOURCES}
-# krb4.c
-# security.c
-# )
-# ENDIF(CURL_KRB4)
-
# #OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
# MARK_AS_ADVANCED(CURL_MALLOC_DEBUG)
# IF(CURL_MALLOC_DEBUG)
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index ae3f961cf..e8d2259f2 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -5,11 +5,11 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# 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
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
@@ -20,67 +20,314 @@
#
###########################################################################
-LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c \
- vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c \
- vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \
+LIB_VAUTH_CFILES = \
+ vauth/cleartext.c \
+ vauth/cram.c \
+ vauth/digest.c \
+ vauth/digest_sspi.c \
+ vauth/krb5_gssapi.c \
+ vauth/krb5_sspi.c \
+ vauth/ntlm.c \
+ vauth/ntlm_sspi.c \
+ vauth/oauth2.c \
+ vauth/spnego_gssapi.c \
+ vauth/spnego_sspi.c \
vauth/vauth.c
-LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h
+LIB_VAUTH_HFILES = \
+ vauth/digest.h \
+ vauth/ntlm.h \
+ vauth/vauth.h
-LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c \
- vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c \
- vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \
- vtls/vtls.c vtls/wolfssl.c
+LIB_VTLS_CFILES = \
+ vtls/bearssl.c \
+ vtls/gskit.c \
+ vtls/gtls.c \
+ vtls/keylog.c \
+ vtls/mbedtls.c \
+ vtls/mbedtls_threadlock.c \
+ vtls/mesalink.c \
+ vtls/nss.c \
+ vtls/openssl.c \
+ vtls/schannel.c \
+ vtls/schannel_verify.c \
+ vtls/sectransp.c \
+ vtls/vtls.c \
+ vtls/wolfssl.c
-LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h \
- vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h \
- vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h
+LIB_VTLS_HFILES = \
+ vtls/bearssl.h \
+ vtls/gskit.h \
+ vtls/gtls.h \
+ vtls/keylog.h \
+ vtls/mbedtls.h \
+ vtls/mbedtls_threadlock.h \
+ vtls/mesalink.h \
+ vtls/nssg.h \
+ vtls/openssl.h \
+ vtls/schannel.h \
+ vtls/sectransp.h \
+ vtls/vtls.h \
+ vtls/wolfssl.h
-LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c
+LIB_VQUIC_CFILES = \
+ vquic/ngtcp2.c \
+ vquic/quiche.c \
+ vquic/vquic.c
-LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h
+LIB_VQUIC_HFILES = \
+ vquic/ngtcp2.h \
+ vquic/quiche.h \
+ vquic/vquic.h
-LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c
+LIB_VSSH_CFILES = \
+ vssh/libssh.c \
+ vssh/libssh2.c \
+ vssh/wolfssh.c
-LIB_VSSH_HFILES = vssh/ssh.h
+LIB_VSSH_HFILES = \
+ vssh/ssh.h
-LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c \
- conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c \
- curl_ctype.c curl_des.c curl_endian.c curl_fnmatch.c curl_get_line.c \
- curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c \
- curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c \
- curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c \
- file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \
- gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c \
- hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c \
- http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \
- krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c \
- multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c \
- pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c security.c select.c \
- sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \
- socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c \
- strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c \
- transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c \
- version_win32.c
+LIB_CFILES = \
+ altsvc.c \
+ amigaos.c \
+ asyn-ares.c \
+ asyn-thread.c \
+ base64.c \
+ c-hyper.c \
+ conncache.c \
+ connect.c \
+ content_encoding.c \
+ cookie.c \
+ curl_addrinfo.c \
+ curl_ctype.c \
+ curl_des.c \
+ curl_endian.c \
+ curl_fnmatch.c \
+ curl_get_line.c \
+ curl_gethostname.c \
+ curl_gssapi.c \
+ curl_memrchr.c \
+ curl_multibyte.c \
+ curl_ntlm_core.c \
+ curl_ntlm_wb.c \
+ curl_path.c \
+ curl_range.c \
+ curl_rtmp.c \
+ curl_sasl.c \
+ curl_sspi.c \
+ curl_threads.c \
+ dict.c \
+ doh.c \
+ dotdot.c \
+ dynbuf.c \
+ easy.c \
+ easygetopt.c \
+ easyoptions.c \
+ escape.c \
+ file.c \
+ fileinfo.c \
+ formdata.c \
+ ftp.c \
+ ftplistparser.c \
+ getenv.c \
+ getinfo.c \
+ gopher.c \
+ hash.c \
+ hmac.c \
+ hostasyn.c \
+ hostcheck.c \
+ hostip.c \
+ hostip4.c \
+ hostip6.c \
+ hostsyn.c \
+ hsts.c \
+ http.c \
+ http2.c \
+ http_chunks.c \
+ http_digest.c \
+ http_negotiate.c \
+ http_ntlm.c \
+ http_proxy.c \
+ http_aws_sigv4.c \
+ idn_win32.c \
+ if2ip.c \
+ imap.c \
+ inet_ntop.c \
+ inet_pton.c \
+ krb5.c \
+ ldap.c \
+ llist.c \
+ md4.c \
+ md5.c \
+ memdebug.c \
+ mime.c \
+ mprintf.c \
+ mqtt.c \
+ multi.c \
+ netrc.c \
+ non-ascii.c \
+ nonblock.c \
+ openldap.c \
+ parsedate.c \
+ pingpong.c \
+ pop3.c \
+ progress.c \
+ psl.c \
+ rand.c \
+ rename.c \
+ rtsp.c \
+ select.c \
+ sendf.c \
+ setopt.c \
+ sha256.c \
+ share.c \
+ slist.c \
+ smb.c \
+ smtp.c \
+ socketpair.c \
+ socks.c \
+ socks_gssapi.c \
+ socks_sspi.c \
+ speedcheck.c \
+ splay.c \
+ strcase.c \
+ strdup.c \
+ strerror.c \
+ strtok.c \
+ strtoofft.c \
+ system_win32.c \
+ telnet.c \
+ tftp.c \
+ timeval.c \
+ transfer.c \
+ url.c \
+ urlapi.c \
+ version.c \
+ version_win32.c \
+ warnless.c \
+ wildcard.c \
+ x509asn1.c
-LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \
- content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h \
- curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h \
- curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h \
- curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \
- curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_sec.h curl_setup.h \
- curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h \
- dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h \
- ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h \
- http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h \
- http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h \
- mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h \
- parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \
- rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h \
- smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \
- strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h \
- timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h \
- x509asn1.h dynbuf.h version_win32.h
+LIB_HFILES = \
+ altsvc.h \
+ amigaos.h \
+ arpa_telnet.h \
+ asyn.h \
+ c-hyper.h \
+ conncache.h \
+ connect.h \
+ content_encoding.h \
+ cookie.h \
+ curl_addrinfo.h \
+ curl_base64.h \
+ curl_ctype.h \
+ curl_des.h \
+ curl_endian.h \
+ curl_fnmatch.h \
+ curl_get_line.h \
+ curl_gethostname.h \
+ curl_gssapi.h \
+ curl_hmac.h \
+ curl_krb5.h \
+ curl_ldap.h \
+ curl_md4.h \
+ curl_md5.h \
+ curl_memory.h \
+ curl_memrchr.h \
+ curl_multibyte.h \
+ curl_ntlm_core.h \
+ curl_ntlm_wb.h \
+ curl_path.h \
+ curl_printf.h \
+ curl_range.h \
+ curl_rtmp.h \
+ curl_sasl.h \
+ curl_setup.h \
+ curl_setup_once.h \
+ curl_sha256.h \
+ curl_sspi.h \
+ curl_threads.h \
+ curlx.h \
+ dict.h \
+ doh.h \
+ dotdot.h \
+ dynbuf.h \
+ easyif.h \
+ easyoptions.h \
+ escape.h \
+ file.h \
+ fileinfo.h \
+ formdata.h \
+ ftp.h \
+ ftplistparser.h \
+ getinfo.h \
+ gopher.h \
+ hash.h \
+ hostcheck.h \
+ hostip.h \
+ hsts.h \
+ http.h \
+ http2.h \
+ http_chunks.h \
+ http_digest.h \
+ http_negotiate.h \
+ http_ntlm.h \
+ http_proxy.h \
+ http_aws_sigv4.h \
+ if2ip.h \
+ imap.h \
+ inet_ntop.h \
+ inet_pton.h \
+ llist.h \
+ memdebug.h \
+ mime.h \
+ mqtt.h \
+ multihandle.h \
+ multiif.h \
+ netrc.h \
+ non-ascii.h \
+ nonblock.h \
+ parsedate.h \
+ pingpong.h \
+ pop3.h \
+ progress.h \
+ psl.h \
+ quic.h \
+ rand.h \
+ rename.h \
+ rtsp.h \
+ select.h \
+ sendf.h \
+ setopt.h \
+ setup-vms.h \
+ share.h \
+ sigpipe.h \
+ slist.h \
+ smb.h \
+ smtp.h \
+ sockaddr.h \
+ socketpair.h \
+ socks.h \
+ speedcheck.h \
+ splay.h \
+ strcase.h \
+ strdup.h \
+ strerror.h \
+ strtok.h \
+ strtoofft.h \
+ system_win32.h \
+ telnet.h \
+ tftp.h \
+ timeval.h \
+ transfer.h \
+ url.h \
+ urlapi-int.h \
+ urldata.h \
+ version_win32.h \
+ warnless.h \
+ wildcard.h \
+ x509asn1.h
LIB_RCFILES = libcurl.rc
diff --git a/Utilities/cmcurl/lib/altsvc.c b/Utilities/cmcurl/lib/altsvc.c
index c2ec489d9..4ab77fdfc 100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -25,7 +25,7 @@
*/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
#include <curl/curl.h>
#include "urldata.h"
#include "altsvc.h"
@@ -302,11 +302,12 @@ CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
* Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
* resources.
*/
-void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
+void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
- if(altsvc) {
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ if(*altsvcp) {
+ struct altsvcinfo *altsvc = *altsvcp;
for(e = altsvc->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
@@ -314,6 +315,7 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
}
free(altsvc->filename);
free(altsvc);
+ *altsvcp = NULL; /* clear the pointer */
}
}
@@ -323,8 +325,8 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *altsvc, const char *file)
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
CURLcode result = CURLE_OK;
FILE *out;
char *tempstore;
@@ -353,7 +355,7 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
if(!out)
result = CURLE_WRITE_ERROR;
else {
- fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
+ fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
for(e = altsvc->list.head; e; e = n) {
@@ -399,8 +401,8 @@ static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
const char *srchost, unsigned short srcport)
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
for(e = asi->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
@@ -449,12 +451,14 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
{
const char *p = value;
size_t len;
- enum alpnid dstalpnid = srcalpnid; /* the same by default */
char namebuf[MAX_ALTSVC_HOSTLEN] = "";
char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
if(result) {
infof(data, "Excessive alt-svc header, ignoring...\n");
return CURLE_OK;
@@ -473,7 +477,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
do {
if(*p == '=') {
/* [protocol]="[host][:port]" */
- dstalpnid = alpn2alpnid(alpnbuf);
+ enum alpnid dstalpnid = alpn2alpnid(alpnbuf); /* the same by default */
p++;
if(*p == '\"') {
const char *dsthost = "";
@@ -612,8 +616,8 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
struct altsvc **dstentry,
const int versions) /* one or more bits */
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
time_t now = time(NULL);
DEBUGASSERT(asi);
DEBUGASSERT(srchost);
@@ -640,4 +644,4 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
return FALSE;
}
-#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */
diff --git a/Utilities/cmcurl/lib/altsvc.h b/Utilities/cmcurl/lib/altsvc.h
index 578a4fbfb..2ab89e705 100644
--- a/Utilities/cmcurl/lib/altsvc.h
+++ b/Utilities/cmcurl/lib/altsvc.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
#include <curl/curl.h>
#include "llist.h"
@@ -46,12 +46,12 @@ struct altsvc {
time_t expires;
bool persist;
int prio;
- struct curl_llist_element node;
+ struct Curl_llist_element node;
};
struct altsvcinfo {
char *filename;
- struct curl_llist list; /* list of entries */
+ struct Curl_llist list; /* list of entries */
long flags; /* the publicly set bitmask */
};
@@ -61,7 +61,7 @@ CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *asi, const char *file);
CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
-void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
+void Curl_altsvc_cleanup(struct altsvcinfo **altsvc);
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvcinfo *altsvc, const char *value,
enum alpnid srcalpn, const char *srchost,
@@ -74,5 +74,6 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
#else
/* disabled */
#define Curl_altsvc_save(a,b,c)
-#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
+#define Curl_altsvc_cleanup(x)
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */
#endif /* HEADER_CURL_ALTSVC_H */
diff --git a/Utilities/cmcurl/lib/amigaos.c b/Utilities/cmcurl/lib/amigaos.c
index cf44bdc8d..d3b00d908 100644
--- a/Utilities/cmcurl/lib/amigaos.c
+++ b/Utilities/cmcurl/lib/amigaos.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/amigaos.h b/Utilities/cmcurl/lib/amigaos.h
index c776c9c9b..02e5bb546 100644
--- a/Utilities/cmcurl/lib/amigaos.h
+++ b/Utilities/cmcurl/lib/amigaos.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/arpa_telnet.h b/Utilities/cmcurl/lib/arpa_telnet.h
index 232680e7d..cbe31de5a 100644
--- a/Utilities/cmcurl/lib/arpa_telnet.h
+++ b/Utilities/cmcurl/lib/arpa_telnet.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index e65150744..2484a7b49 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -67,8 +67,8 @@
#include "select.h"
#include "progress.h"
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- (defined(WIN32) || defined(__SYMBIAN32__))
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ defined(WIN32)
# define CARES_STATICLIB
# endif
# include <ares.h>
@@ -85,7 +85,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-struct ResolverResults {
+struct thread_data {
int num_pending; /* number of ares_gethostbyname() requests */
struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
parts */
@@ -133,8 +133,8 @@ void Curl_resolver_global_cleanup(void)
}
-static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd,
- int readable, int writable)
+static void sock_state_cb(void *data, ares_socket_t socket_fd,
+ int readable, int writable)
{
struct Curl_easy *easy = data;
if(!readable && !writable) {
@@ -155,7 +155,7 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
int status;
struct ares_options options;
int optmask = ARES_OPT_SOCK_STATE_CB;
- options.sock_state_cb = Curl_ares_sock_state_cb;
+ options.sock_state_cb = sock_state_cb;
options.sock_state_cb_data = easy;
status = ares_init_options((ares_channel*)resolver, &options, optmask);
if(status != ARES_SUCCESS) {
@@ -204,22 +204,22 @@ static void destroy_async_data(struct Curl_async *async);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
-void Curl_resolver_cancel(struct connectdata *conn)
+void Curl_resolver_cancel(struct Curl_easy *data)
{
- if(conn->data && conn->data->state.resolver)
- ares_cancel((ares_channel)conn->data->state.resolver);
- destroy_async_data(&conn->async);
+ if(data && data->state.async.resolver)
+ ares_cancel((ares_channel)data->state.async.resolver);
+ destroy_async_data(&data->state.async);
}
/*
* We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We
* never block.
*/
-void Curl_resolver_kill(struct connectdata *conn)
+void Curl_resolver_kill(struct Curl_easy *data)
{
/* We don't need to check the resolver state because we can be called safely
at any time and we always do the same thing. */
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
}
/*
@@ -229,8 +229,8 @@ static void destroy_async_data(struct Curl_async *async)
{
free(async->hostname);
- if(async->os_specific) {
- struct ResolverResults *res = (struct ResolverResults *)async->os_specific;
+ if(async->tdata) {
+ struct thread_data *res = async->tdata;
if(res) {
if(res->temp_ai) {
Curl_freeaddrinfo(res->temp_ai);
@@ -238,7 +238,7 @@ static void destroy_async_data(struct Curl_async *async)
}
free(res);
}
- async->os_specific = NULL;
+ async->tdata = NULL;
}
async->hostname = NULL;
@@ -253,25 +253,25 @@ static void destroy_async_data(struct Curl_async *async)
* Returns: sockets-in-use-bitmap
*/
-int Curl_resolver_getsock(struct connectdata *conn,
+int Curl_resolver_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
struct timeval maxtime;
struct timeval timebuf;
struct timeval *timeout;
long milli;
- int max = ares_getsock((ares_channel)conn->data->state.resolver,
+ int max = ares_getsock((ares_channel)data->state.async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0;
- timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime,
+ timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
&timebuf);
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
if(milli == 0)
milli += 10;
- Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME);
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max;
}
@@ -286,9 +286,8 @@ int Curl_resolver_getsock(struct connectdata *conn,
* return number of sockets it worked on
*/
-static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
+static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
{
- struct Curl_easy *data = conn->data;
int nfds;
int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
@@ -296,7 +295,7 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
int i;
int num = 0;
- bitmask = ares_getsock((ares_channel)data->state.resolver, socks,
+ bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
@@ -324,12 +323,12 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
if(!nfds)
/* Call ares_process() unconditonally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
- ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD,
+ ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
ARES_SOCKET_BAD);
else {
/* move through the descriptors and ask for processing on them */
for(i = 0; i < num; i++)
- ares_process_fd((ares_channel)data->state.resolver,
+ ares_process_fd((ares_channel)data->state.async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))?
@@ -345,18 +344,16 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
*
* Returns normal CURLcode errors.
*/
-CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
- struct Curl_easy *data = conn->data;
- struct ResolverResults *res = (struct ResolverResults *)
- conn->async.os_specific;
+ struct thread_data *res = data->state.async.tdata;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
*dns = NULL;
- waitperform(conn, 0);
+ waitperform(data, 0);
/* Now that we've checked for any last minute results above, see if there are
any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
@@ -377,26 +374,27 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next
block. */
- ares_cancel((ares_channel)data->state.resolver);
+ ares_cancel((ares_channel)data->state.async.resolver);
DEBUGASSERT(res->num_pending == 0);
}
if(res && !res->num_pending) {
- (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+ (void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai);
/* temp_ai ownership is moved to the connection, so we need not free-up
them */
res->temp_ai = NULL;
- if(!conn->async.dns) {
+ if(!data->state.async.dns) {
failf(data, "Could not resolve: %s (%s)",
- conn->async.hostname, ares_strerror(conn->async.status));
- result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ data->state.async.hostname,
+ ares_strerror(data->state.async.status));
+ result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
else
- *dns = conn->async.dns;
+ *dns = data->state.async.dns;
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
}
return result;
@@ -413,11 +411,10 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
-CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
timediff_t timeout;
struct curltime now = Curl_now();
@@ -427,7 +424,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
timeout = Curl_timeleft(data, &now, TRUE);
if(timeout < 0) {
/* already expired! */
- connclose(conn, "Timed out before name resolve started");
+ connclose(data->conn, "Timed out before name resolve started");
return CURLE_OPERATION_TIMEDOUT;
}
if(!timeout)
@@ -448,7 +445,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
- tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv);
+ tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
/* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress
@@ -458,13 +455,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
else
timeout_ms = 1000;
- waitperform(conn, timeout_ms);
- result = Curl_resolver_is_resolved(conn, entry);
+ waitperform(data, timeout_ms);
+ result = Curl_resolver_is_resolved(data, entry);
- if(result || conn->async.done)
+ if(result || data->state.async.done)
break;
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else {
struct curltime now2 = Curl_now();
@@ -482,23 +479,23 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
}
if(result)
/* failure, so we cancel the ares operation */
- ares_cancel((ares_channel)data->state.resolver);
+ ares_cancel((ares_channel)data->state.async.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
if(entry)
- *entry = conn->async.dns;
+ *entry = data->state.async.dns;
if(result)
/* close the connection, since we can't return failure here without
cleaning up this connection properly. */
- connclose(conn, "c-ares resolve failed");
+ connclose(data->conn, "c-ares resolve failed");
return result;
}
/* Connects results to the list */
-static void compound_results(struct ResolverResults *res,
+static void compound_results(struct thread_data *res,
struct Curl_addrinfo *ai)
{
struct Curl_addrinfo *ai_tail;
@@ -526,8 +523,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
#endif
struct hostent *hostent)
{
- struct connectdata *conn = (struct connectdata *)arg;
- struct ResolverResults *res;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct thread_data *res;
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
(void)timeouts; /* ignored */
@@ -538,12 +535,12 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
be valid so only defer it when we know the 'status' says its fine! */
return;
- res = (struct ResolverResults *)conn->async.os_specific;
+ res = data->state.async.tdata;
if(res) {
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
- struct Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+ struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
if(ai) {
compound_results(res, ai);
}
@@ -608,8 +605,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
c-ares retry cycle each request is.
*/
res->happy_eyeballs_dns_time = Curl_now();
- Curl_expire(
- conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
+ Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
+ EXPIRE_HAPPY_EYEBALLS_DNS);
}
}
}
@@ -622,19 +619,18 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
char *bufp;
- struct Curl_easy *data = conn->data;
int family = PF_INET;
*waitp = 0; /* default to synchronous response */
#ifdef ENABLE_IPV6
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
default:
#if ARES_VERSION >= 0x010601
family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
@@ -653,40 +649,40 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
bufp = strdup(hostname);
if(bufp) {
- struct ResolverResults *res = NULL;
- free(conn->async.hostname);
- conn->async.hostname = bufp;
- conn->async.port = port;
- conn->async.done = FALSE; /* not done */
- conn->async.status = 0; /* clear */
- conn->async.dns = NULL; /* clear */
- res = calloc(sizeof(struct ResolverResults), 1);
+ struct thread_data *res = NULL;
+ free(data->state.async.hostname);
+ data->state.async.hostname = bufp;
+ data->state.async.port = port;
+ data->state.async.done = FALSE; /* not done */
+ data->state.async.status = 0; /* clear */
+ data->state.async.dns = NULL; /* clear */
+ res = calloc(sizeof(struct thread_data), 1);
if(!res) {
- free(conn->async.hostname);
- conn->async.hostname = NULL;
+ free(data->state.async.hostname);
+ data->state.async.hostname = NULL;
return NULL;
}
- conn->async.os_specific = res;
+ data->state.async.tdata = res;
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
#ifdef ENABLE_IPV6
if(family == PF_UNSPEC) {
- if(Curl_ipv6works(conn)) {
+ if(Curl_ipv6works(data)) {
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET, query_completed_cb, conn);
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET6, query_completed_cb, conn);
+ 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.resolver, hostname,
- PF_INET, query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
+ PF_INET, query_completed_cb, data);
}
}
else
@@ -695,8 +691,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname, family,
- query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.async.resolver,
+ hostname, family,
+ query_completed_cb, data);
}
*waitp = 1; /* expect asynchronous response */
@@ -721,9 +718,10 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
#if (ARES_VERSION >= 0x010704)
#if (ARES_VERSION >= 0x010b00)
- ares_result = ares_set_servers_ports_csv(data->state.resolver, servers);
+ ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
+ servers);
#else
- ares_result = ares_set_servers_csv(data->state.resolver, servers);
+ ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
@@ -753,7 +751,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
if(!interf)
interf = "";
- ares_set_local_dev((ares_channel)data->state.resolver, interf);
+ ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
return CURLE_OK;
#else /* c-ares version too old! */
@@ -778,7 +776,8 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
}
}
- ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr));
+ ares_set_local_ip4((ares_channel)data->state.async.resolver,
+ ntohl(a4.s_addr));
return CURLE_OK;
#else /* c-ares version too old! */
@@ -804,7 +803,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
}
}
- ares_set_local_ip6((ares_channel)data->state.resolver, a6);
+ ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
return CURLE_OK;
#else /* c-ares version too old! */
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index a60f4f066..9fcbc3c1f 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -145,13 +145,13 @@ static void destroy_async_data(struct Curl_async *);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
-void Curl_resolver_cancel(struct connectdata *conn)
+void Curl_resolver_cancel(struct Curl_easy *data)
{
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
}
/* This function is used to init a threaded resolve */
-static bool init_resolve_thread(struct connectdata *conn,
+static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints);
@@ -160,12 +160,11 @@ static bool init_resolve_thread(struct connectdata *conn,
struct thread_sync_data {
curl_mutex_t *mtx;
int done;
-
+ int port;
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
- int port;
#ifdef USE_SOCKETPAIR
- struct connectdata *conn;
+ struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error;
@@ -183,9 +182,9 @@ struct thread_data {
struct thread_sync_data tsd;
};
-static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
+static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{
- return &(((struct thread_data *)conn->async.os_specific)->tsd);
+ return &(data->state.async.tdata->tsd);
}
/* Destroy resolver thread synchronization data */
@@ -269,12 +268,12 @@ int init_thread_sync_data(struct thread_data *td,
return 0;
}
-static int getaddrinfo_complete(struct connectdata *conn)
+static int getaddrinfo_complete(struct Curl_easy *data)
{
- struct thread_sync_data *tsd = conn_thread_sync_data(conn);
+ struct thread_sync_data *tsd = conn_thread_sync_data(data);
int rc;
- rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res);
+ rc = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
/* The tsd->res structure has been copied to async.dns and perhaps the DNS
cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/
@@ -294,7 +293,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
*/
static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
{
- struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
+ struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
struct thread_data *td = tsd->td;
char service[12];
int rc;
@@ -380,12 +379,12 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
*/
static void destroy_async_data(struct Curl_async *async)
{
- if(async->os_specific) {
- struct thread_data *td = (struct thread_data*) async->os_specific;
+ if(async->tdata) {
+ struct thread_data *td = async->tdata;
int done;
#ifdef USE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
- struct connectdata *conn = td->tsd.conn;
+ struct Curl_easy *data = td->tsd.data;
#endif
/*
@@ -406,19 +405,18 @@ static void destroy_async_data(struct Curl_async *async)
destroy_thread_sync_data(&td->tsd);
- free(async->os_specific);
+ free(async->tdata);
}
#ifdef USE_SOCKETPAIR
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
*/
- if(conn)
- Curl_multi_closed(conn->data, sock_rd);
+ Curl_multi_closed(data, sock_rd);
sclose(sock_rd);
#endif
}
- async->os_specific = NULL;
+ async->tdata = NULL;
free(async->hostname);
async->hostname = NULL;
@@ -430,32 +428,33 @@ static void destroy_async_data(struct Curl_async *async)
*
* Returns FALSE in case of failure, otherwise TRUE.
*/
-static bool init_resolve_thread(struct connectdata *conn,
+static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints)
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM;
+ struct Curl_async *asp = &data->state.async;
- conn->async.os_specific = (void *)td;
+ data->state.async.tdata = td;
if(!td)
goto errno_exit;
- conn->async.port = port;
- conn->async.done = FALSE;
- conn->async.status = 0;
- conn->async.dns = NULL;
+ asp->port = port;
+ asp->done = FALSE;
+ asp->status = 0;
+ asp->dns = NULL;
td->thread_hnd = curl_thread_t_null;
if(!init_thread_sync_data(td, hostname, port, hints)) {
- conn->async.os_specific = NULL;
+ asp->tdata = NULL;
free(td);
goto errno_exit;
}
- free(conn->async.hostname);
- conn->async.hostname = strdup(hostname);
- if(!conn->async.hostname)
+ free(asp->hostname);
+ asp->hostname = strdup(hostname);
+ if(!asp->hostname)
goto err_exit;
/* The thread will set this to 1 when complete. */
@@ -477,7 +476,7 @@ static bool init_resolve_thread(struct connectdata *conn,
return TRUE;
err_exit:
- destroy_async_data(&conn->async);
+ destroy_async_data(asp);
errno_exit:
errno = err;
@@ -489,12 +488,13 @@ static bool init_resolve_thread(struct connectdata *conn,
* error
*/
-static CURLcode resolver_error(struct connectdata *conn)
+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;
@@ -506,8 +506,8 @@ static CURLcode resolver_error(struct connectdata *conn)
result = CURLE_COULDNT_RESOLVE_HOST;
}
- failf(conn->data, "Could not resolve %s: %s", host_or_proxy,
- conn->async.hostname);
+ failf(data, "Could not resolve %s: %s", host_or_proxy,
+ data->state.async.hostname);
return result;
}
@@ -515,37 +515,39 @@ static CURLcode resolver_error(struct connectdata *conn)
/*
* 'entry' may be NULL and then no data is returned
*/
-static CURLcode thread_wait_resolv(struct connectdata *conn,
+static CURLcode thread_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry,
bool report)
{
- struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ struct thread_data *td;
CURLcode result = CURLE_OK;
- DEBUGASSERT(conn && td);
+ DEBUGASSERT(data);
+ td = data->state.async.tdata;
+ DEBUGASSERT(td);
DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
/* wait for the thread to resolve the name */
if(Curl_thread_join(&td->thread_hnd)) {
if(entry)
- result = getaddrinfo_complete(conn);
+ result = getaddrinfo_complete(data);
}
else
DEBUGASSERT(0);
- conn->async.done = TRUE;
+ data->state.async.done = TRUE;
if(entry)
- *entry = conn->async.dns;
+ *entry = data->state.async.dns;
- if(!conn->async.dns && report)
+ if(!data->state.async.dns && report)
/* a name was not resolved, report error */
- result = resolver_error(conn);
+ result = resolver_error(data);
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
- if(!conn->async.dns && report)
- connclose(conn, "asynch resolve failed");
+ if(!data->state.async.dns && report)
+ connclose(data->conn, "asynch resolve failed");
return result;
}
@@ -555,17 +557,17 @@ static CURLcode thread_wait_resolv(struct connectdata *conn,
* Until we gain a way to signal the resolver threads to stop early, we must
* simply wait for them and ignore their results.
*/
-void Curl_resolver_kill(struct connectdata *conn)
+void Curl_resolver_kill(struct Curl_easy *data)
{
- struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ struct thread_data *td = data->state.async.tdata;
/* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */
if(td && td->thread_hnd != curl_thread_t_null)
- (void)thread_wait_resolv(conn, NULL, FALSE);
+ (void)thread_wait_resolv(data, NULL, FALSE);
else
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
}
/*
@@ -581,10 +583,10 @@ void Curl_resolver_kill(struct connectdata *conn)
*
* This is the version for resolves-in-a-thread.
*/
-CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
- return thread_wait_resolv(conn, entry, TRUE);
+ return thread_wait_resolv(data, entry, TRUE);
}
/*
@@ -592,11 +594,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* name resolve request has completed. It should also make sure to time-out if
* the operation seems to take too long.
*/
-CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
- struct Curl_easy *data = conn->data;
- struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ struct thread_data *td = data->state.async.tdata;
int done = 0;
DEBUGASSERT(entry);
@@ -612,15 +613,15 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
Curl_mutex_release(td->tsd.mtx);
if(done) {
- getaddrinfo_complete(conn);
+ getaddrinfo_complete(data);
- if(!conn->async.dns) {
- CURLcode result = resolver_error(conn);
- destroy_async_data(&conn->async);
+ if(!data->state.async.dns) {
+ CURLcode result = resolver_error(data);
+ destroy_async_data(&data->state.async);
return result;
}
- destroy_async_data(&conn->async);
- *entry = conn->async.dns;
+ destroy_async_data(&data->state.async);
+ *entry = data->state.async.dns;
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
@@ -641,22 +642,20 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval;
- Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME);
+ Curl_expire(data, td->poll_interval, EXPIRE_ASYNC_NAME);
}
return CURLE_OK;
}
-int Curl_resolver_getsock(struct connectdata *conn,
- curl_socket_t *socks)
+int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
int ret_val = 0;
timediff_t milli;
timediff_t ms;
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
#ifdef USE_SOCKETPAIR
- struct thread_data *td = (struct thread_data*)conn->async.os_specific;
+ struct thread_data *td = data->state.async.tdata;
#else
(void)socks;
#endif
@@ -665,8 +664,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
if(td) {
/* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0];
- DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
- td->tsd.conn = conn;
+ td->tsd.data = data;
ret_val = GETSOCK_READSOCK(0);
}
else {
@@ -693,25 +691,24 @@ int Curl_resolver_getsock(struct connectdata *conn,
/*
* Curl_getaddrinfo() - for platforms without getaddrinfo
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
*waitp = 0; /* default to synchronous response */
reslv->start = Curl_now();
/* fire up a new resolver thread! */
- if(init_resolve_thread(conn, hostname, port, NULL)) {
+ if(init_resolve_thread(data, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- failf(conn->data, "getaddrinfo() thread failed\n");
+ failf(data, "getaddrinfo() thread failed");
return NULL;
}
@@ -721,15 +718,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/*
* Curl_resolver_getaddrinfo() - for getaddrinfo
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
struct addrinfo hints;
int pf = PF_INET;
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
*waitp = 0; /* default to synchronous response */
@@ -737,7 +733,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/*
* Check if a limited name resolve has been requested.
*/
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
@@ -749,24 +745,24 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
break;
}
- if((pf != PF_INET) && !Curl_ipv6works(conn))
+ 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));
hints.ai_family = pf;
- hints.ai_socktype = (conn->transport == TRNSPRT_TCP)?
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
reslv->start = Curl_now();
/* fire up a new resolver thread! */
- if(init_resolve_thread(conn, hostname, port, &hints)) {
+ if(init_resolve_thread(data, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- failf(data, "getaddrinfo() thread failed to start\n");
+ failf(data, "getaddrinfo() thread failed to start");
return NULL;
}
diff --git a/Utilities/cmcurl/lib/asyn.h b/Utilities/cmcurl/lib/asyn.h
index bd3c3c123..313039582 100644
--- a/Utilities/cmcurl/lib/asyn.h
+++ b/Utilities/cmcurl/lib/asyn.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -91,7 +91,7 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
*
* It is safe to call this when conn is in any state.
*/
-void Curl_resolver_cancel(struct connectdata *conn);
+void Curl_resolver_cancel(struct Curl_easy *data);
/*
* Curl_resolver_kill().
@@ -104,7 +104,7 @@ void Curl_resolver_cancel(struct connectdata *conn);
*
* It is safe to call this when conn is in any state.
*/
-void Curl_resolver_kill(struct connectdata *conn);
+void Curl_resolver_kill(struct Curl_easy *data);
/* Curl_resolver_getsock()
*
@@ -114,7 +114,7 @@ void Curl_resolver_kill(struct connectdata *conn);
* return bitmask indicating what file descriptors (referring to array indexes
* in the 'sock' array) to wait for, read/write.
*/
-int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock);
+int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);
/*
* Curl_resolver_is_resolved()
@@ -125,7 +125,7 @@ int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock);
*
* Returns normal CURLcode errors.
*/
-CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns);
/*
@@ -139,7 +139,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
-CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **dnsentry);
/*
@@ -153,7 +153,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* Each resolver backend must of course make sure to return data in the
* correct format to comply with this.
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
diff --git a/Utilities/cmcurl/lib/base64.c b/Utilities/cmcurl/lib/base64.c
index 643cef625..be6f163dc 100644
--- a/Utilities/cmcurl/lib/base64.c
+++ b/Utilities/cmcurl/lib/base64.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -26,6 +26,9 @@
#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_SSH) || \
!defined(CURL_DISABLE_LDAP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_POP3) || \
+ !defined(CURL_DISABLE_IMAP) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL)
#include "urldata.h" /* for the Curl_easy definition */
diff --git a/Utilities/cmcurl/lib/c-hyper.c b/Utilities/cmcurl/lib/c-hyper.c
new file mode 100644
index 000000000..10bd7ef9b
--- /dev/null
+++ b/Utilities/cmcurl/lib/c-hyper.c
@@ -0,0 +1,908 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * 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
+ * are also available at https://curl.haxx.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"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include <hyper.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "transfer.h"
+#include "multiif.h"
+#include "progress.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
+ uint8_t *buf, size_t buflen)
+{
+ struct Curl_easy *data = userp;
+ struct connectdata *conn = data->conn;
+ CURLcode result;
+ ssize_t nread;
+ DEBUGASSERT(conn);
+ (void)ctx;
+
+ result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
+ if(result == CURLE_AGAIN) {
+ /* would block, register interest */
+ if(data->hyp.read_waker)
+ hyper_waker_free(data->hyp.read_waker);
+ data->hyp.read_waker = hyper_context_waker(ctx);
+ if(!data->hyp.read_waker) {
+ failf(data, "Couldn't make the read hyper_context_waker");
+ return HYPER_IO_ERROR;
+ }
+ return HYPER_IO_PENDING;
+ }
+ else if(result) {
+ failf(data, "Curl_read failed");
+ return HYPER_IO_ERROR;
+ }
+ return (size_t)nread;
+}
+
+size_t Curl_hyper_send(void *userp, hyper_context *ctx,
+ const uint8_t *buf, size_t buflen)
+{
+ struct Curl_easy *data = userp;
+ struct connectdata *conn = data->conn;
+ CURLcode result;
+ ssize_t nwrote;
+
+ result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
+ if(result == CURLE_AGAIN) {
+ /* would block, register interest */
+ if(data->hyp.write_waker)
+ hyper_waker_free(data->hyp.write_waker);
+ data->hyp.write_waker = hyper_context_waker(ctx);
+ if(!data->hyp.write_waker) {
+ failf(data, "Couldn't make the write hyper_context_waker");
+ return HYPER_IO_ERROR;
+ }
+ return HYPER_IO_PENDING;
+ }
+ else if(result) {
+ failf(data, "Curl_write failed");
+ return HYPER_IO_ERROR;
+ }
+ return (size_t)nwrote;
+}
+
+static int hyper_each_header(void *userdata,
+ const uint8_t *name,
+ size_t name_len,
+ const uint8_t *value,
+ size_t value_len)
+{
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ size_t len;
+ char *headp;
+ CURLcode result;
+ Curl_dyn_reset(&data->state.headerb);
+ if(name_len) {
+ if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
+ (int) name_len, name, (int) value_len, value))
+ return HYPER_ITER_BREAK;
+ }
+ else {
+ if(Curl_dyn_add(&data->state.headerb, "\r\n"))
+ return HYPER_ITER_BREAK;
+ }
+ len = Curl_dyn_len(&data->state.headerb);
+ headp = Curl_dyn_ptr(&data->state.headerb);
+
+ result = Curl_http_header(data, data->conn, headp);
+ if(result) {
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
+
+ Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
+
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, headp, 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;
+ return HYPER_ITER_CONTINUE;
+}
+
+static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
+{
+ char *buf = (char *)hyper_buf_bytes(chunk);
+ size_t len = hyper_buf_len(chunk);
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ struct SingleRequest *k = &data->req;
+ CURLcode result;
+
+ if(0 == k->bodywrites++) {
+ bool done = FALSE;
+ result = Curl_http_firstwrite(data, data->conn, &done);
+ if(result || done) {
+ infof(data, "Return early from hyper_body_chunk\n");
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
+ }
+ if(k->ignorebody)
+ return HYPER_ITER_CONTINUE;
+ Curl_debug(data, CURLINFO_DATA_IN, buf, len);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
+
+ if(result) {
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
+
+ data->req.bytecount += len;
+ Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ return HYPER_ITER_CONTINUE;
+}
+
+/*
+ * Hyper does not consider the status line, the first line in a HTTP/1
+ * response, to be a header. The libcurl API does. This function sends the
+ * status line in the header callback. */
+static CURLcode status_line(struct Curl_easy *data,
+ struct connectdata *conn,
+ uint16_t http_status,
+ int http_version,
+ 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 =
+ http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
+ (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
+ data->req.httpcode = http_status;
+
+ result = Curl_http_statusline(data, conn);
+ if(result)
+ return result;
+
+ Curl_dyn_reset(&data->state.headerb);
+
+ result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n",
+ vstr,
+ (int)http_status,
+ (int)rlen, reason);
+ if(result)
+ return result;
+ 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;
+
+ data->info.header_size += (long)len;
+ data->req.headerbytecount += (long)len;
+ data->req.httpcode = http_status;
+ return CURLE_OK;
+}
+
+/*
+ * Hyper does not pass on the last empty response header. The libcurl API
+ * does. This function sends an empty header in the header callback.
+ */
+static CURLcode empty_header(struct Curl_easy *data)
+{
+ return hyper_each_header(data, NULL, 0, NULL, 0) ?
+ CURLE_WRITE_ERROR : CURLE_OK;
+}
+
+CURLcode Curl_hyper_stream(struct Curl_easy *data,
+ struct connectdata *conn,
+ int *didwhat,
+ bool *done,
+ int select_res)
+{
+ hyper_response *resp = NULL;
+ uint16_t http_status;
+ int http_version;
+ hyper_headers *headers = NULL;
+ hyper_body *resp_body = NULL;
+ struct hyptransfer *h = &data->hyp;
+ hyper_task *task;
+ hyper_task *foreach;
+ hyper_error *hypererr = NULL;
+ const uint8_t *reasonp;
+ size_t reason_len;
+ CURLcode result = CURLE_OK;
+ (void)conn;
+
+ if(select_res & CURL_CSELECT_IN) {
+ if(h->read_waker)
+ hyper_waker_wake(h->read_waker);
+ h->read_waker = NULL;
+ }
+ if(select_res & CURL_CSELECT_OUT) {
+ if(h->write_waker)
+ hyper_waker_wake(h->write_waker);
+ h->write_waker = NULL;
+ }
+
+ *done = FALSE;
+ do {
+ hyper_task_return_type t;
+ task = hyper_executor_poll(h->exec);
+ if(!task) {
+ *didwhat = KEEP_RECV;
+ break;
+ }
+ t = hyper_task_type(task);
+ switch(t) {
+ case HYPER_TASK_ERROR:
+ hypererr = hyper_task_value(task);
+ break;
+ case HYPER_TASK_RESPONSE:
+ resp = hyper_task_value(task);
+ break;
+ default:
+ break;
+ }
+ hyper_task_free(task);
+
+ if(t == HYPER_TASK_ERROR) {
+ hyper_code errnum = hyper_error_code(hypererr);
+ if(errnum == HYPERE_ABORTED_BY_CALLBACK) {
+ /* override Hyper's view, might not even be an error */
+ result = data->state.hresult;
+ infof(data, "hyperstream is done (by early callback)\n");
+ }
+ else {
+ uint8_t errbuf[256];
+ size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
+ hyper_code code = hyper_error_code(hypererr);
+ failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
+ if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
+ result = CURLE_GOT_NOTHING;
+ else
+ result = CURLE_RECV_ERROR;
+ }
+ *done = TRUE;
+ hyper_error_free(hypererr);
+ break;
+ }
+ else if(h->endtask == task) {
+ /* end of transfer */
+ *done = TRUE;
+ infof(data, "hyperstream is done!\n");
+ break;
+ }
+ else if(t != HYPER_TASK_RESPONSE) {
+ *didwhat = KEEP_RECV;
+ break;
+ }
+ /* HYPER_TASK_RESPONSE */
+
+ *didwhat = KEEP_RECV;
+ if(!resp) {
+ failf(data, "hyperstream: couldn't get response");
+ return CURLE_RECV_ERROR;
+ }
+
+ http_status = hyper_response_status(resp);
+ http_version = hyper_response_version(resp);
+ reasonp = hyper_response_reason_phrase(resp);
+ reason_len = hyper_response_reason_phrase_len(resp);
+
+ result = status_line(data, conn,
+ http_status, http_version, reasonp, reason_len);
+ if(result)
+ break;
+
+ headers = hyper_response_headers(resp);
+ if(!headers) {
+ failf(data, "hyperstream: couldn't get response headers");
+ result = CURLE_RECV_ERROR;
+ break;
+ }
+
+ /* the headers are already received */
+ hyper_headers_foreach(headers, hyper_each_header, data);
+ if(data->state.hresult) {
+ result = data->state.hresult;
+ break;
+ }
+
+ if(empty_header(data)) {
+ failf(data, "hyperstream: couldn't pass blank header");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ /* Curl_http_auth_act() checks what authentication methods that are
+ * available and decides which one (if any) to use. It will set 'newurl'
+ * if an auth method was picked. */
+ result = Curl_http_auth_act(data);
+ if(result)
+ break;
+
+ resp_body = hyper_response_body(resp);
+ if(!resp_body) {
+ failf(data, "hyperstream: couldn't get response body");
+ result = CURLE_RECV_ERROR;
+ break;
+ }
+ foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
+ if(!foreach) {
+ failf(data, "hyperstream: body foreach failed");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ DEBUGASSERT(hyper_task_type(foreach) == HYPER_TASK_EMPTY);
+ if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
+ failf(data, "Couldn't hyper_executor_push the body-foreach");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ h->endtask = foreach;
+
+ hyper_response_free(resp);
+ resp = NULL;
+ } while(1);
+ if(resp)
+ hyper_response_free(resp);
+ return result;
+}
+
+static CURLcode debug_request(struct Curl_easy *data,
+ const char *method,
+ const char *path,
+ bool h2)
+{
+ char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
+ h2?"2":"1.1");
+ if(!req)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
+ free(req);
+ return CURLE_OK;
+}
+
+/*
+ * Given a full header line "name: value" (optional CRLF in the input, should
+ * be in the output), add to Hyper and send to the debug callback.
+ *
+ * Supports multiple headers.
+ */
+
+CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
+ const char *line)
+{
+ const char *p;
+ const char *n;
+ size_t nlen;
+ const char *v;
+ size_t vlen;
+ bool newline = TRUE;
+ int numh = 0;
+
+ if(!line)
+ return CURLE_OK;
+ n = line;
+ do {
+ size_t linelen = 0;
+
+ p = strchr(n, ':');
+ if(!p)
+ /* this is fine if we already added at least one header */
+ return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
+ nlen = p - n;
+ p++; /* move past the colon */
+ while(*p == ' ')
+ p++;
+ v = p;
+ p = strchr(v, '\r');
+ if(!p) {
+ p = strchr(v, '\n');
+ if(p)
+ linelen = 1; /* LF only */
+ else {
+ p = strchr(v, '\0');
+ newline = FALSE; /* no newline */
+ }
+ }
+ 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,
+ (uint8_t *)v, vlen)) {
+ failf(data, "hyper_headers_add host");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(data->set.verbose) {
+ char *ptr = NULL;
+ if(!newline) {
+ ptr = aprintf("%.*s\r\n", (int)linelen, line);
+ if(!ptr)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2);
+ free(ptr);
+ }
+ else
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen);
+ }
+ numh++;
+ n += linelen;
+ } while(newline);
+ return CURLE_OK;
+}
+
+static CURLcode request_target(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *method,
+ bool h2,
+ hyper_request *req)
+{
+ CURLcode result;
+ struct dynbuf r;
+
+ Curl_dyn_init(&r, DYN_HTTP_REQUEST);
+
+ result = Curl_http_target(data, conn, &r);
+ if(result)
+ return result;
+
+ if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
+ Curl_dyn_len(&r))) {
+ failf(data, "error setting path");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else
+ result = debug_request(data, method, Curl_dyn_ptr(&r), h2);
+
+ Curl_dyn_free(&r);
+
+ return result;
+}
+
+static int uploadpostfields(void *userdata, hyper_context *ctx,
+ hyper_buf **chunk)
+{
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ (void)ctx;
+ if(data->req.upload_done)
+ *chunk = NULL; /* nothing more to deliver */
+ else {
+ /* send everything off in a single go */
+ *chunk = hyper_buf_copy(data->set.postfields,
+ (size_t)data->req.p.http->postsize);
+ data->req.upload_done = TRUE;
+ }
+ return HYPER_POLL_READY;
+}
+
+static int uploadstreamed(void *userdata, hyper_context *ctx,
+ hyper_buf **chunk)
+{
+ size_t fillcount;
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ CURLcode result =
+ Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
+ (void)ctx;
+ if(result)
+ return HYPER_POLL_ERROR;
+ if(!fillcount)
+ /* done! */
+ *chunk = NULL;
+ else
+ *chunk = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
+ return HYPER_POLL_READY;
+}
+
+/*
+ * bodysend() sets up headers in the outgoing request for a HTTP transfer that
+ * sends a body
+ */
+
+static CURLcode bodysend(struct Curl_easy *data,
+ struct connectdata *conn,
+ hyper_headers *headers,
+ hyper_request *hyperreq,
+ Curl_HttpReq httpreq)
+{
+ CURLcode result = CURLE_OK;
+ struct dynbuf req;
+ if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD))
+ Curl_pgrsSetUploadSize(data, 0); /* no request body */
+ else {
+ hyper_body *body;
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+ result = Curl_http_bodysend(data, conn, &req, httpreq);
+
+ if(!result)
+ result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
+
+ Curl_dyn_free(&req);
+
+ body = hyper_body_new();
+ hyper_body_set_userdata(body, data);
+ if(data->set.postfields)
+ hyper_body_set_data_func(body, uploadpostfields);
+ else {
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+ /* init the "upload from here" pointer */
+ data->req.upload_fromhere = data->state.ulbuf;
+ hyper_body_set_data_func(body, uploadstreamed);
+ }
+ if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
+ /* fail */
+ hyper_body_free(body);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ return result;
+}
+
+static CURLcode cookies(struct Curl_easy *data,
+ struct connectdata *conn,
+ hyper_headers *headers)
+{
+ struct dynbuf req;
+ CURLcode result;
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+
+ result = Curl_http_cookies(data, conn, &req);
+ if(!result)
+ result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
+ Curl_dyn_free(&req);
+ return result;
+}
+
+/*
+ * Curl_http() gets called from the generic multi_do() function when a HTTP
+ * request is to be performed. This creates and sends a properly constructed
+ * HTTP request.
+ */
+CURLcode Curl_http(struct Curl_easy *data, bool *done)
+{
+ struct connectdata *conn = data->conn;
+ struct hyptransfer *h = &data->hyp;
+ hyper_io *io = NULL;
+ hyper_clientconn_options *options = NULL;
+ hyper_task *task = NULL; /* for the handshake */
+ hyper_task *sendtask = NULL; /* for the send */
+ hyper_clientconn *client = NULL;
+ hyper_request *req = NULL;
+ hyper_headers *headers = NULL;
+ hyper_task *handshake = NULL;
+ hyper_error *hypererr = NULL;
+ CURLcode result;
+ const char *p_accept; /* Accept: string */
+ const char *method;
+ Curl_HttpReq httpreq;
+ bool h2 = FALSE;
+ const char *te = NULL; /* transfer-encoding */
+
+ /* Always consider the DO phase done after this function call, even if there
+ may be parts of the request that is not yet sent, since we can deal with
+ the rest of the request in the PERFORM phase. */
+ *done = TRUE;
+
+ infof(data, "Time for the Hyper dance\n");
+ memset(h, 0, sizeof(struct hyptransfer));
+
+ result = Curl_http_host(data, conn);
+ if(result)
+ return result;
+
+ Curl_http_method(data, conn, &method, &httpreq);
+
+ /* setup the authentication headers */
+ {
+ char *pq = NULL;
+ if(data->state.up.query) {
+ pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
+ if(!pq)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result = Curl_http_output_auth(data, conn, method, httpreq,
+ (pq ? pq : data->state.up.path), FALSE);
+ free(pq);
+ if(result)
+ return result;
+ }
+
+ result = Curl_http_resume(data, conn, httpreq);
+ if(result)
+ return result;
+
+ result = Curl_http_range(data, httpreq);
+ if(result)
+ return result;
+
+ result = Curl_http_useragent(data);
+ if(result)
+ return result;
+
+ io = hyper_io_new();
+ if(!io) {
+ failf(data, "Couldn't create hyper IO");
+ goto error;
+ }
+ /* tell Hyper how to read/write network data */
+ hyper_io_set_userdata(io, data);
+ hyper_io_set_read(io, Curl_hyper_recv);
+ hyper_io_set_write(io, Curl_hyper_send);
+
+ /* create an executor to poll futures */
+ if(!h->exec) {
+ h->exec = hyper_executor_new();
+ if(!h->exec) {
+ failf(data, "Couldn't create hyper executor");
+ goto error;
+ }
+ }
+
+ options = hyper_clientconn_options_new();
+ if(!options) {
+ failf(data, "Couldn't create hyper client options");
+ goto error;
+ }
+ if(conn->negnpn == CURL_HTTP_VERSION_2) {
+ hyper_clientconn_options_http2(options, 1);
+ h2 = TRUE;
+ }
+
+ hyper_clientconn_options_exec(options, h->exec);
+
+ /* "Both the `io` and the `options` are consumed in this function call" */
+ handshake = hyper_clientconn_handshake(io, options);
+ if(!handshake) {
+ failf(data, "Couldn't create hyper client handshake");
+ goto error;
+ }
+ io = NULL;
+ options = NULL;
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
+ failf(data, "Couldn't hyper_executor_push the handshake");
+ goto error;
+ }
+ handshake = NULL; /* ownership passed on */
+
+ task = hyper_executor_poll(h->exec);
+ if(!task) {
+ failf(data, "Couldn't hyper_executor_poll the handshake");
+ goto error;
+ }
+
+ client = hyper_task_value(task);
+ hyper_task_free(task);
+
+ req = hyper_request_new();
+ if(!req) {
+ failf(data, "Couldn't hyper_request_new");
+ goto error;
+ }
+
+ if(data->set.httpversion == CURL_HTTP_VERSION_1_0) {
+ if(HYPERE_OK != hyper_request_set_version(req,
+ HYPER_HTTP_VERSION_1_0)) {
+ failf(data, "error setting HTTP version");
+ goto error;
+ }
+ }
+
+ if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
+ failf(data, "error setting method");
+ goto error;
+ }
+
+ result = request_target(data, conn, method, h2, req);
+ if(result)
+ goto error;
+
+ headers = hyper_request_headers(req);
+ if(!headers) {
+ failf(data, "hyper_request_headers");
+ goto error;
+ }
+
+ result = Curl_http_body(data, conn, httpreq, &te);
+ if(result)
+ return result;
+
+ if(data->state.aptr.host &&
+ Curl_hyper_header(data, headers, data->state.aptr.host))
+ goto error;
+
+ if(data->state.aptr.proxyuserpwd &&
+ Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd))
+ goto error;
+
+ if(data->state.aptr.userpwd &&
+ Curl_hyper_header(data, headers, data->state.aptr.userpwd))
+ goto error;
+
+ if((data->state.use_range && data->state.aptr.rangeline) &&
+ Curl_hyper_header(data, headers, data->state.aptr.rangeline))
+ goto error;
+
+ if(data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ data->state.aptr.uagent &&
+ Curl_hyper_header(data, headers, data->state.aptr.uagent))
+ goto error;
+
+ p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
+ if(p_accept && Curl_hyper_header(data, headers, p_accept))
+ goto error;
+
+ if(te && Curl_hyper_header(data, headers, te))
+ goto error;
+
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
+ !Curl_checkheaders(data, "Proxy-Connection") &&
+ !Curl_checkProxyheaders(data, conn, "Proxy-Connection")) {
+ if(Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
+ goto error;
+ }
+#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.aptr.ref)
+ return CURLE_OUT_OF_MEMORY;
+ if(Curl_hyper_header(data, headers, data->state.aptr.ref))
+ goto error;
+ }
+
+ result = cookies(data, conn, headers);
+ if(result)
+ return result;
+
+ result = Curl_add_timecondition(data, headers);
+ if(result)
+ return result;
+
+ result = Curl_add_custom_headers(data, FALSE, headers);
+ if(result)
+ return result;
+
+ result = bodysend(data, conn, headers, req, httpreq);
+ if(result)
+ return result;
+
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
+
+ data->req.upload_chunky = FALSE;
+ sendtask = hyper_clientconn_send(client, req);
+ if(!sendtask) {
+ failf(data, "hyper_clientconn_send");
+ goto error;
+ }
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
+ failf(data, "Couldn't hyper_executor_push the send");
+ goto error;
+ }
+
+ hyper_clientconn_free(client);
+
+ do {
+ task = hyper_executor_poll(h->exec);
+ if(task) {
+ bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
+ if(error)
+ hypererr = hyper_task_value(task);
+ hyper_task_free(task);
+ if(error)
+ goto error;
+ }
+ } while(task);
+
+ if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
+ /* HTTP GET/HEAD download */
+ Curl_pgrsSetUploadSize(data, 0); /* nothing */
+ Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
+ }
+ conn->datastream = Curl_hyper_stream;
+
+ return CURLE_OK;
+ error:
+
+ if(io)
+ hyper_io_free(io);
+
+ if(options)
+ hyper_clientconn_options_free(options);
+
+ if(handshake)
+ hyper_task_free(handshake);
+
+ if(hypererr) {
+ uint8_t errbuf[256];
+ size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
+ hyper_code code = hyper_error_code(hypererr);
+ failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
+ hyper_error_free(hypererr);
+ }
+ return CURLE_OUT_OF_MEMORY;
+}
+
+void Curl_hyper_done(struct Curl_easy *data)
+{
+ struct hyptransfer *h = &data->hyp;
+ if(h->exec) {
+ hyper_executor_free(h->exec);
+ h->exec = NULL;
+ }
+ if(h->read_waker) {
+ hyper_waker_free(h->read_waker);
+ h->read_waker = NULL;
+ }
+ if(h->write_waker) {
+ hyper_waker_free(h->write_waker);
+ h->write_waker = NULL;
+ }
+}
+
+#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
diff --git a/Utilities/cmcurl/lib/c-hyper.h b/Utilities/cmcurl/lib/c-hyper.h
new file mode 100644
index 000000000..d60ed78d1
--- /dev/null
+++ b/Utilities/cmcurl/lib/c-hyper.h
@@ -0,0 +1,56 @@
+#ifndef HEADER_CURL_HYPER_H
+#define HEADER_CURL_HYPER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * 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
+ * are also available at https://curl.haxx.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"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
+
+#include <hyper.h>
+
+/* per-transfer data for the Hyper backend */
+struct hyptransfer {
+ hyper_waker *write_waker;
+ hyper_waker *read_waker;
+ const hyper_executor *exec;
+ hyper_task *endtask;
+};
+
+size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
+ uint8_t *buf, size_t buflen);
+size_t Curl_hyper_send(void *userp, hyper_context *ctx,
+ const uint8_t *buf, size_t buflen);
+CURLcode Curl_hyper_stream(struct Curl_easy *data,
+ struct connectdata *conn,
+ int *didwhat,
+ bool *done,
+ int select_res);
+
+CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
+ const char *line);
+void Curl_hyper_done(struct Curl_easy *);
+
+#else
+#define Curl_hyper_done(x)
+
+#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
+#endif /* HEADER_CURL_HYPER_H */
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index d21a00cfd..8dfdc0ac8 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -6,11 +6,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -59,7 +59,7 @@ static CURLcode bundle_create(struct connectbundle **bundlep)
(*bundlep)->num_connections = 0;
(*bundlep)->multiuse = BUNDLE_UNKNOWN;
- Curl_llist_init(&(*bundlep)->conn_list, (curl_llist_dtor) conn_llist_dtor);
+ Curl_llist_init(&(*bundlep)->conn_list, (Curl_llist_dtor) conn_llist_dtor);
return CURLE_OK;
}
@@ -87,7 +87,7 @@ static void bundle_add_conn(struct connectbundle *bundle,
static int bundle_remove_conn(struct connectbundle *bundle,
struct connectdata *conn)
{
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
curr = bundle->conn_list.head;
while(curr) {
@@ -179,12 +179,14 @@ size_t Curl_conncache_size(struct Curl_easy *data)
connectdata struct is setup to use.
**NOTE**: When it returns, it holds the connection cache lock! */
-struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
- struct conncache *connc,
- const char **hostp)
+struct connectbundle *
+Curl_conncache_find_bundle(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct conncache *connc,
+ const char **hostp)
{
struct connectbundle *bundle = NULL;
- CONNCACHE_LOCK(conn->data);
+ CONNCACHE_LOCK(data);
if(connc) {
char key[HASHKEY_SIZE];
hashkey(conn, key, sizeof(key), hostp);
@@ -206,8 +208,8 @@ static bool conncache_add_bundle(struct conncache *connc,
static void conncache_remove_bundle(struct conncache *connc,
struct connectbundle *bundle)
{
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
if(!connc)
return;
@@ -227,15 +229,17 @@ static void conncache_remove_bundle(struct conncache *connc,
}
}
-CURLcode Curl_conncache_add_conn(struct conncache *connc,
- struct connectdata *conn)
+CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct connectbundle *bundle = NULL;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
+ struct conncache *connc = data->state.conn_cache;
+ DEBUGASSERT(conn);
/* *find_bundle() locks the connection cache */
- bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache, NULL);
+ bundle = Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
+ NULL);
if(!bundle) {
int rc;
char key[HASHKEY_SIZE];
@@ -259,7 +263,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
- DEBUGF(infof(conn->data, "Added connection %ld. "
+ DEBUGF(infof(data, "Added connection %ld. "
"The cache now contains %zu members\n",
conn->connection_id, connc->num_conn));
@@ -270,8 +274,8 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
}
/*
- * Removes the connectdata object from the connection cache, but does *not*
- * clear the conn->data association. The transfer still owns this connection.
+ * Removes the connectdata object from the connection cache, but the transfer
+ * still owns this connection.
*
* Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
* already holds the lock or not.
@@ -318,11 +322,12 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param,
- int (*func)(struct connectdata *conn, void *param))
+ int (*func)(struct Curl_easy *data,
+ struct connectdata *conn, void *param))
{
- struct curl_hash_iterator iter;
- struct curl_llist_element *curr;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_llist_element *curr;
+ struct Curl_hash_element *he;
if(!connc)
return FALSE;
@@ -344,7 +349,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
struct connectdata *conn = curr->ptr;
curr = curr->next;
- if(1 == func(conn, param)) {
+ if(1 == func(data, conn, param)) {
CONNCACHE_UNLOCK(data);
return TRUE;
}
@@ -363,15 +368,15 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
static struct connectdata *
conncache_find_first_connection(struct conncache *connc)
{
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
struct connectbundle *bundle;
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
bundle = he->ptr;
curr = bundle->conn_list.head;
@@ -429,7 +434,7 @@ struct connectdata *
Curl_conncache_extract_bundle(struct Curl_easy *data,
struct connectbundle *bundle)
{
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
timediff_t highscore = -1;
timediff_t score;
struct curltime now;
@@ -444,7 +449,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
while(curr) {
conn = curr->ptr;
- if(!CONN_INUSE(conn) && !conn->data) {
+ if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
@@ -477,9 +482,9 @@ struct connectdata *
Curl_conncache_extract_oldest(struct Curl_easy *data)
{
struct conncache *connc = data->state.conn_cache;
- struct curl_hash_iterator iter;
- struct curl_llist_element *curr;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_llist_element *curr;
+ struct Curl_hash_element *he;
timediff_t highscore =- 1;
timediff_t score;
struct curltime now;
@@ -502,7 +507,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
while(curr) {
conn = curr->ptr;
- if(!CONN_INUSE(conn) && !conn->data && !conn->bits.close &&
+ if(!CONN_INUSE(conn) && !conn->bits.close &&
!conn->bits.connect_only) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
@@ -543,12 +548,10 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
conn = conncache_find_first_connection(connc);
while(conn) {
SIGPIPE_VARIABLE(pipe_st);
- conn->data = connc->closure_handle;
-
- sigpipe_ignore(conn->data, &pipe_st);
+ sigpipe_ignore(connc->closure_handle, &pipe_st);
/* This will remove the connection from the cache */
connclose(conn, "kill all");
- Curl_conncache_remove_conn(conn->data, conn, TRUE);
+ Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE);
(void)Curl_disconnect(connc->closure_handle, conn, FALSE);
sigpipe_restore(&pipe_st);
@@ -571,9 +574,9 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
/* Useful for debugging the connection cache */
void Curl_conncache_print(struct conncache *connc)
{
- struct curl_hash_iterator iter;
- struct curl_llist_element *curr;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_llist_element *curr;
+ struct Curl_hash_element *he;
if(!connc)
return;
diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h
index 3dda21cdc..e9c1e32f8 100644
--- a/Utilities/cmcurl/lib/conncache.h
+++ b/Utilities/cmcurl/lib/conncache.h
@@ -7,12 +7,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -29,8 +29,12 @@
* be shared.
*/
+#include "timeval.h"
+
+struct connectdata;
+
struct conncache {
- struct curl_hash hash;
+ struct Curl_hash hash;
size_t num_conn;
long next_connection_id;
struct curltime last_cleanup;
@@ -45,17 +49,24 @@ struct conncache {
#ifdef CURLDEBUG
/* the debug versions of these macros make extra certain that the lock is
never doubly locked or unlocked */
-#define CONNCACHE_LOCK(x) if((x)->share) { \
- Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
- DEBUGASSERT(!(x)->state.conncache_lock); \
- (x)->state.conncache_lock = TRUE; \
- }
+#define CONNCACHE_LOCK(x) \
+ do { \
+ if((x)->share) { \
+ Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, \
+ CURL_LOCK_ACCESS_SINGLE); \
+ DEBUGASSERT(!(x)->state.conncache_lock); \
+ (x)->state.conncache_lock = TRUE; \
+ } \
+ } while(0)
-#define CONNCACHE_UNLOCK(x) if((x)->share) { \
- DEBUGASSERT((x)->state.conncache_lock); \
- (x)->state.conncache_lock = FALSE; \
- Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
- }
+#define CONNCACHE_UNLOCK(x) \
+ do { \
+ if((x)->share) { \
+ DEBUGASSERT((x)->state.conncache_lock); \
+ (x)->state.conncache_lock = FALSE; \
+ Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
+ } \
+ } while(0)
#else
#define CONNCACHE_LOCK(x) if((x)->share) \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
@@ -66,7 +77,7 @@ struct conncache {
struct connectbundle {
int multiuse; /* supports multi-use */
size_t num_connections; /* Number of connections in the bundle */
- struct curl_llist conn_list; /* The connectdata members of the bundle */
+ struct Curl_llist conn_list; /* The connectdata members of the bundle */
};
/* returns 1 on error, 0 is fine */
@@ -74,7 +85,8 @@ int Curl_conncache_init(struct conncache *, int size);
void Curl_conncache_destroy(struct conncache *connc);
/* return the correct bundle, to a host or a proxy */
-struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
+struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data,
+ struct connectdata *conn,
struct conncache *connc,
const char **hostp);
/* returns number of connections currently held in the connection cache */
@@ -82,15 +94,15 @@ size_t Curl_conncache_size(struct Curl_easy *data);
bool Curl_conncache_return_conn(struct Curl_easy *data,
struct connectdata *conn);
-CURLcode Curl_conncache_add_conn(struct conncache *connc,
- struct connectdata *conn) WARN_UNUSED_RESULT;
+CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct Curl_easy *data,
struct connectdata *conn,
bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param,
- int (*func)(struct connectdata *conn,
+ int (*func)(struct Curl_easy *data,
+ struct connectdata *conn,
void *param));
struct connectdata *
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index b000b1b2c..baab1840e 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -83,11 +83,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef __SYMBIAN32__
-/* This isn't actually supported under Symbian OS */
-#undef SO_NOSIGPIPE
-#endif
-
static bool verifyconnect(curl_socket_t sockfd, int *error);
#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
@@ -165,7 +160,8 @@ tcpkeepalive(struct Curl_easy *data,
}
static CURLcode
-singleipconnect(struct connectdata *conn,
+singleipconnect(struct Curl_easy *data,
+ struct connectdata *conn,
const struct Curl_addrinfo *ai, /* start connecting to this */
int tempindex); /* 0 or 1 among the temp ones */
@@ -241,11 +237,10 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
return timeout_ms;
}
-static CURLcode bindlocal(struct connectdata *conn,
+static CURLcode bindlocal(struct Curl_easy *data,
curl_socket_t sockfd, int af, unsigned int scope)
{
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
struct Curl_sockaddr_storage sa;
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
@@ -261,6 +256,9 @@ static CURLcode bindlocal(struct connectdata *conn,
int portnum = data->set.localportrange;
const char *dev = data->set.str[STRING_DEVICE];
int error;
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ int on = 1;
+#endif
/*************************************************************
* Select device to bind socket to
@@ -350,7 +348,7 @@ static CURLcode bindlocal(struct connectdata *conn,
* of the connection. The resolve functions should really be changed
* to take a type parameter instead.
*/
- long ipver = conn->ip_version;
+ unsigned char ipver = conn->ip_version;
int rc;
if(af == AF_INET)
@@ -360,9 +358,9 @@ static CURLcode bindlocal(struct connectdata *conn,
conn->ip_version = CURL_IPRESOLVE_V6;
#endif
- rc = Curl_resolv(conn, dev, 0, FALSE, &h);
+ rc = Curl_resolv(data, dev, 0, FALSE, &h);
if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(conn, &h);
+ (void)Curl_resolver_wait_resolv(data, &h);
conn->ip_version = ipver;
if(h) {
@@ -446,7 +444,9 @@ static CURLcode bindlocal(struct connectdata *conn,
sizeof_sa = sizeof(struct sockaddr_in);
}
}
-
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ (void)setsockopt(sockfd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &on, sizeof(on));
+#endif
for(;;) {
if(bind(sockfd, sock, sizeof_sa) >= 0) {
/* we succeeded to bind */
@@ -573,7 +573,8 @@ static struct Curl_addrinfo *ainext(struct connectdata *conn,
/* Used within the multi interface. Try next IP address, returns error if no
more address exists or error */
-static CURLcode trynextip(struct connectdata *conn,
+static CURLcode trynextip(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
int tempindex)
{
@@ -591,7 +592,7 @@ static CURLcode trynextip(struct connectdata *conn,
while(ai) {
if(ai) {
- result = singleipconnect(conn, ai, tempindex);
+ result = singleipconnect(data, conn, ai, tempindex);
if(result == CURLE_COULDNT_CONNECT) {
ai = ainext(conn, tempindex, TRUE);
continue;
@@ -602,21 +603,25 @@ static CURLcode trynextip(struct connectdata *conn,
}
if(fd_to_close != CURL_SOCKET_BAD)
- Curl_closesocket(conn, fd_to_close);
+ Curl_closesocket(data, conn, fd_to_close);
return result;
}
-/* Copies connection info into the session handle to make it available
- when the session handle is no longer associated with a connection. */
-void Curl_persistconninfo(struct connectdata *conn)
+/* 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)
{
- memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
- memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
- conn->data->info.conn_scheme = conn->handler->scheme;
- conn->data->info.conn_protocol = conn->handler->protocol;
- conn->data->info.conn_primary_port = conn->primary_port;
- conn->data->info.conn_local_port = conn->local_port;
+ memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
+ if(local_ip && local_ip[0])
+ memcpy(data->info.conn_local_ip, local_ip, MAX_IPADR_LEN);
+ else
+ data->info.conn_local_ip[0] = 0;
+ data->info.conn_scheme = conn->handler->scheme;
+ data->info.conn_protocol = conn->handler->protocol;
+ data->info.conn_primary_port = conn->port;
+ data->info.conn_local_port = local_port;
}
/* retrieves ip address and port from a sockaddr structure.
@@ -678,61 +683,86 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
/* retrieves the start/end point information of a socket of an established
connection */
-void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
+void Curl_conninfo_remote(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t sockfd)
{
- if(conn->transport == TRNSPRT_TCP) {
-#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
- if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
- struct Curl_easy *data = conn->data;
- char buffer[STRERROR_LEN];
- struct Curl_sockaddr_storage ssrem;
- struct Curl_sockaddr_storage ssloc;
- curl_socklen_t plen;
- curl_socklen_t slen;
#ifdef HAVE_GETPEERNAME
- plen = sizeof(struct Curl_sockaddr_storage);
- if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
- int error = SOCKERRNO;
- failf(data, "getpeername() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
-#endif
-#ifdef HAVE_GETSOCKNAME
- slen = sizeof(struct Curl_sockaddr_storage);
- memset(&ssloc, 0, sizeof(ssloc));
- if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
- int error = SOCKERRNO;
- failf(data, "getsockname() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
-#endif
-#ifdef HAVE_GETPEERNAME
- if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
- conn->primary_ip, &conn->primary_port)) {
- failf(data, "ssrem inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
- }
- memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssrem;
+ curl_socklen_t plen;
+ long port;
+ plen = sizeof(struct Curl_sockaddr_storage);
+ memset(&ssrem, 0, sizeof(ssrem));
+ if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
+ int error = SOCKERRNO;
+ failf(data, "getpeername() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
+ conn->primary_ip, &port)) {
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return;
+ }
+#else
+ (void)data;
+ (void)conn;
+ (void)sockfd;
#endif
+}
+
+/* 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)
+{
#ifdef HAVE_GETSOCKNAME
- if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
- conn->local_ip, &conn->local_port)) {
- failf(data, "ssloc inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
- }
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssloc;
+ curl_socklen_t slen;
+ slen = sizeof(struct Curl_sockaddr_storage);
+ memset(&ssloc, 0, sizeof(ssloc));
+ if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
+ int error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
+ local_ip, local_port)) {
+ failf(data, "ssloc inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return;
+ }
+#else
+ (void)data;
+ (void)sockfd;
+ (void)local_ip;
+ (void)local_port;
#endif
+}
+
+/* retrieves the start/end point information of a socket of an established
+ connection */
+void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sockfd)
+{
+ /* 'local_ip' and 'local_port' get filled with local's numerical
+ 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;
+
+ if(conn->transport == TRNSPRT_TCP) {
+ if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
+ Curl_conninfo_remote(data, conn, sockfd);
+ Curl_conninfo_local(data, sockfd, local_ip, &local_port);
}
-#else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */
- (void)sockfd; /* unused */
-#endif
} /* end of TCP-only section */
/* persist connection info in session handle */
- Curl_persistconninfo(conn);
+ Curl_persistconninfo(data, conn, local_ip, local_port);
}
/* After a TCP connection to the proxy has been verified, this function does
@@ -742,12 +772,13 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
Note: this function's sub-functions call failf()
*/
-static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
+static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex,
bool *done)
{
CURLcode result = CURLE_OK;
-
#ifndef CURL_DISABLE_PROXY
+ CURLproxycode pxresult = CURLPX_OK;
+ struct connectdata *conn = data->conn;
if(conn->bits.socksproxy) {
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
@@ -767,24 +798,28 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
switch(conn->socks_proxy.proxytype) {
case CURLPROXY_SOCKS5:
case CURLPROXY_SOCKS5_HOSTNAME:
- result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
- host, port, sockindex, conn, done);
+ pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
+ host, port, sockindex, data, done);
break;
case CURLPROXY_SOCKS4:
case CURLPROXY_SOCKS4A:
- result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
- conn, done);
+ pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+ data, done);
break;
default:
- failf(conn->data, "unknown proxytype option given");
+ failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
} /* switch proxytype */
+ if(pxresult) {
+ result = CURLE_PROXY;
+ data->info.pxcode = pxresult;
+ }
}
else
#else
- (void)conn;
+ (void)data;
(void)sockindex;
#endif /* CURL_DISABLE_PROXY */
*done = TRUE; /* no SOCKS proxy, so consider us connected */
@@ -796,7 +831,8 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
* post_SOCKS() is called after a successful connect to the peer, which
* *could* be a SOCKS proxy
*/
-static void post_SOCKS(struct connectdata *conn,
+static void post_SOCKS(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *connected)
{
@@ -804,21 +840,21 @@ static void post_SOCKS(struct connectdata *conn,
*connected = TRUE;
if(sockindex == FIRSTSOCKET)
- Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */
- Curl_updateconninfo(conn, conn->sock[sockindex]);
- Curl_verboseconnect(conn);
- conn->data->info.numconnects++; /* to track the number of connections made */
+ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
+ Curl_updateconninfo(data, conn, conn->sock[sockindex]);
+ Curl_verboseconnect(data, conn);
+ data->info.numconnects++; /* to track the number of connections made */
}
/*
* Curl_is_connected() checks if the socket has connected.
*/
-CURLcode Curl_is_connected(struct connectdata *conn,
+CURLcode Curl_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *connected)
{
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
timediff_t allow;
int error = 0;
@@ -849,9 +885,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
if(SOCKS_STATE(conn->cnnct.state)) {
/* still doing SOCKS */
- result = connect_SOCKS(conn, sockindex, connected);
+ result = connect_SOCKS(data, sockindex, connected);
if(!result && *connected)
- post_SOCKS(conn, sockindex, connected);
+ post_SOCKS(data, conn, sockindex, connected);
return result;
}
@@ -862,13 +898,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
error = 0;
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC) {
- result = Curl_quic_is_connected(conn, i, connected);
+ result = Curl_quic_is_connected(data, conn, i, connected);
if(!result && *connected) {
/* use this socket from now on */
conn->sock[sockindex] = conn->tempsock[i];
conn->ip_addr = conn->tempaddr[i];
conn->tempsock[i] = CURL_SOCKET_BAD;
- post_SOCKS(conn, sockindex, connected);
+ post_SOCKS(data, conn, sockindex, connected);
connkeep(conn, "HTTP/3 default");
return CURLE_OK;
}
@@ -903,7 +939,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
(Curl_timediff(now, conn->connecttime) >=
data->set.happy_eyeballs_timeout)) {
conn->bits.parallel_connect = TRUE; /* starting now */
- trynextip(conn, sockindex, 1);
+ trynextip(data, conn, sockindex, 1);
}
}
else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
@@ -920,17 +956,17 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* close the other socket, if open */
if(conn->tempsock[other] != CURL_SOCKET_BAD) {
- Curl_closesocket(conn, conn->tempsock[other]);
+ Curl_closesocket(data, conn, conn->tempsock[other]);
conn->tempsock[other] = CURL_SOCKET_BAD;
}
/* see if we need to kick off any SOCKS proxy magic once we
connected */
- result = connect_SOCKS(conn, sockindex, connected);
+ result = connect_SOCKS(data, sockindex, connected);
if(result || !*connected)
return result;
- post_SOCKS(conn, sockindex, connected);
+ post_SOCKS(data, conn, sockindex, connected);
return CURLE_OK;
}
@@ -961,7 +997,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
allow : allow / 2;
ainext(conn, i, TRUE);
- status = trynextip(conn, sockindex, i);
+ status = trynextip(data, conn, sockindex, i);
if((status != CURLE_COULDNT_CONNECT) ||
conn->tempsock[other] == CURL_SOCKET_BAD)
/* the last attempt failed and no other sockets remain open */
@@ -979,7 +1015,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* if the first address family runs out of addresses to try before the
happy eyeball timeout, go ahead and try the next family now */
- result = trynextip(conn, sockindex, 1);
+ result = trynextip(data, conn, sockindex, 1);
if(!result)
return result;
@@ -999,8 +1035,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
hostname, conn->port,
Curl_strerror(error, buffer, sizeof(buffer)));
- Curl_quic_disconnect(conn, 0);
- Curl_quic_disconnect(conn, 1);
+ Curl_quic_disconnect(data, conn, 0);
+ Curl_quic_disconnect(data, conn, 1);
#ifdef WSAETIMEDOUT
if(WSAETIMEDOUT == data->state.os_errno)
@@ -1016,16 +1052,15 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return result;
}
-static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
+static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
{
#if defined(TCP_NODELAY)
curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
- struct Curl_easy *data = conn->data;
char buffer[STRERROR_LEN];
#else
- (void) conn;
+ (void) data;
#endif
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
@@ -1033,7 +1068,7 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
#else
- (void)conn;
+ (void)data;
(void)sockfd;
#endif
}
@@ -1043,10 +1078,9 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
sending data to a dead peer (instead of relying on the 4th argument to send
being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
systems? */
-static void nosigpipe(struct connectdata *conn,
+static void nosigpipe(struct Curl_easy *data,
curl_socket_t sockfd)
{
- struct Curl_easy *data = conn->data;
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0) {
@@ -1112,7 +1146,8 @@ void Curl_sndbufset(curl_socket_t sockfd)
* singleipconnect() connects to the given IP only, and it may return without
* having connected.
*/
-static CURLcode singleipconnect(struct connectdata *conn,
+static CURLcode singleipconnect(struct Curl_easy *data,
+ struct connectdata *conn,
const struct Curl_addrinfo *ai,
int tempindex)
{
@@ -1120,7 +1155,6 @@ static CURLcode singleipconnect(struct connectdata *conn,
int rc = -1;
int error = 0;
bool isconnected = FALSE;
- struct Curl_easy *data = conn->data;
curl_socket_t sockfd;
CURLcode result;
char ipaddress[MAX_IPADR_LEN];
@@ -1133,7 +1167,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
curl_socket_t *sockp = &conn->tempsock[tempindex];
*sockp = CURL_SOCKET_BAD;
- result = Curl_socket(conn, ai, &addr, &sockfd);
+ result = Curl_socket(data, ai, &addr, &sockfd);
if(result)
return result;
@@ -1143,7 +1177,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- Curl_closesocket(conn, sockfd);
+ Curl_closesocket(data, conn, sockfd);
return CURLE_OK;
}
infof(data, " Trying %s:%ld...\n", ipaddress, port);
@@ -1155,9 +1189,9 @@ static CURLcode singleipconnect(struct connectdata *conn,
is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
#endif
if(is_tcp && data->set.tcp_nodelay)
- tcpnodelay(conn, sockfd);
+ tcpnodelay(data, sockfd);
- nosigpipe(conn, sockfd);
+ nosigpipe(data, sockfd);
Curl_sndbufset(sockfd);
@@ -1175,7 +1209,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
isconnected = TRUE;
else if(error) {
- Curl_closesocket(conn, sockfd); /* close the socket and bail out */
+ Curl_closesocket(data, conn, sockfd); /* close the socket and bail out */
return CURLE_ABORTED_BY_CALLBACK;
}
}
@@ -1186,10 +1220,10 @@ static CURLcode singleipconnect(struct connectdata *conn,
|| addr.family == AF_INET6
#endif
) {
- result = bindlocal(conn, sockfd, addr.family,
+ result = bindlocal(data, sockfd, addr.family,
Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
if(result) {
- Curl_closesocket(conn, sockfd); /* close socket and bail out */
+ Curl_closesocket(data, conn, sockfd); /* close socket and bail out */
if(result == CURLE_UNSUPPORTED_PROTOCOL) {
/* The address family is not supported on this interface.
We can continue trying addresses */
@@ -1257,7 +1291,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
else if(conn->transport == TRNSPRT_QUIC) {
/* pass in 'sockfd' separately since it hasn't been put into the
tempsock array at this point */
- result = Curl_quic_connect(conn, sockfd, tempindex,
+ result = Curl_quic_connect(data, conn, sockfd, tempindex,
&addr.sa_addr, addr.addrlen);
if(result)
error = SOCKERRNO;
@@ -1292,7 +1326,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
data->state.os_errno = error;
/* connect failed */
- Curl_closesocket(conn, sockfd);
+ Curl_closesocket(data, conn, sockfd);
result = CURLE_COULDNT_CONNECT;
}
}
@@ -1309,14 +1343,13 @@ static CURLcode singleipconnect(struct connectdata *conn,
* pointer with the connected socket.
*/
-CURLcode Curl_connecthost(struct connectdata *conn, /* context */
+CURLcode Curl_connecthost(struct Curl_easy *data,
+ struct connectdata *conn, /* context */
const struct Curl_dns_entry *remotehost)
{
- struct Curl_easy *data = conn->data;
- struct curltime before = Curl_now();
CURLcode result = CURLE_COULDNT_CONNECT;
int i;
- timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
@@ -1336,8 +1369,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
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
ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */
DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
@@ -1347,7 +1384,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* get through the list in family order in case of quick failures */
for(i = 0; (i < 2) && result; i++) {
while(conn->tempaddr[i]) {
- result = singleipconnect(conn, conn->tempaddr[i], i);
+ result = singleipconnect(data, conn, conn->tempaddr[i], i);
if(!result)
break;
ainext(conn, i, TRUE);
@@ -1356,7 +1393,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if(result)
return result;
- Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
+ Curl_expire(data, data->set.happy_eyeballs_timeout,
EXPIRE_HAPPY_EYEBALLS);
return CURLE_OK;
@@ -1367,9 +1404,11 @@ struct connfind {
struct connectdata *found;
};
-static int conn_is_conn(struct connectdata *conn, void *param)
+static int conn_is_conn(struct Curl_easy *data,
+ struct connectdata *conn, void *param)
{
struct connfind *f = (struct connfind *)param;
+ (void)data;
if(conn->connection_id == f->id_tofind) {
f->found = conn;
return 1;
@@ -1416,8 +1455,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
}
return c->sock[FIRSTSOCKET];
}
- else
- return CURL_SOCKET_BAD;
+ return CURL_SOCKET_BAD;
}
/*
@@ -1452,8 +1490,8 @@ bool Curl_connalive(struct connectdata *conn)
*
* 'conn' can be NULL, beware!
*/
-int Curl_closesocket(struct connectdata *conn,
- curl_socket_t sock)
+int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sock)
{
if(conn && conn->fclosesocket) {
if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
@@ -1463,17 +1501,17 @@ int Curl_closesocket(struct connectdata *conn,
conn->bits.sock_accepted = FALSE;
else {
int rc;
- Curl_multi_closed(conn->data, sock);
- Curl_set_in_callback(conn->data, true);
+ Curl_multi_closed(data, sock);
+ Curl_set_in_callback(data, true);
rc = conn->fclosesocket(conn->closesocket_client, sock);
- Curl_set_in_callback(conn->data, false);
+ Curl_set_in_callback(data, false);
return rc;
}
}
if(conn)
/* tell the multi-socket code about this */
- Curl_multi_closed(conn->data, sock);
+ Curl_multi_closed(data, sock);
sclose(sock);
@@ -1489,12 +1527,12 @@ int Curl_closesocket(struct connectdata *conn,
* If the open socket callback is set, used that!
*
*/
-CURLcode Curl_socket(struct connectdata *conn,
+CURLcode Curl_socket(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct Curl_sockaddr_ex dummy;
if(!addr)
@@ -1555,8 +1593,21 @@ CURLcode Curl_socket(struct connectdata *conn,
}
#endif
- return CURLE_OK;
+#if defined(__linux__) && defined(IP_RECVERR)
+ if(addr->socktype == SOCK_DGRAM) {
+ int one = 1;
+ switch(addr->family) {
+ case AF_INET:
+ (void)setsockopt(*sockfd, SOL_IP, IP_RECVERR, &one, sizeof(one));
+ break;
+ case AF_INET6:
+ (void)setsockopt(*sockfd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));
+ break;
+ }
+ }
+#endif
+ return CURLE_OK;
}
/*
@@ -1569,16 +1620,20 @@ void Curl_conncontrol(struct connectdata *conn,
#endif
)
{
- /* close if a connection, or a stream that isn't multiplexed */
- bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
- ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
+ /* close if a connection, or a stream that isn't multiplexed. */
+ /* This function will be called both before and after this connection is
+ associated with a transfer. */
+ bool closeit;
DEBUGASSERT(conn);
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void)reason; /* useful for debugging */
+#endif
+ closeit = (ctrl == CONNCTRL_CONNECTION) ||
+ ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
if((ctrl == CONNCTRL_STREAM) &&
(conn->handler->flags & PROTOPT_STREAM))
- DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
+ ;
else if((bit)closeit != conn->bits.close) {
- DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
- closeit?"closure":"keep alive", reason));
conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */
}
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index 6fd9ea878..566b3531d 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,11 +27,13 @@
#include "sockaddr.h"
#include "timeval.h"
-CURLcode Curl_is_connected(struct connectdata *conn,
+CURLcode Curl_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *connected);
-CURLcode Curl_connecthost(struct connectdata *conn,
+CURLcode Curl_connecthost(struct Curl_easy *data,
+ struct connectdata *conn,
const struct Curl_dns_entry *host);
/* generic function that returns how much time there's left to run, according
@@ -74,9 +76,16 @@ void Curl_sndbufset(curl_socket_t sockfd);
#define Curl_sndbufset(y) Curl_nop_stmt
#endif
-void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
-void Curl_persistconninfo(struct connectdata *conn);
-int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
+void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sockfd);
+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);
+void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
+ char *local_ip, long local_port);
+int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sock);
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
@@ -104,7 +113,7 @@ struct Curl_sockaddr_ex {
* socket callback is set, used that!
*
*/
-CURLcode Curl_socket(struct connectdata *conn,
+CURLcode Curl_socket(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd);
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index 2fc3d43c4..f179b8179 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -28,10 +28,6 @@
#ifdef HAVE_ZLIB_H
#include <zlib.h>
-#ifdef __SYMBIAN32__
-/* zlib pollutes the namespace with this definition */
-#undef WIN32
-#endif
#endif
#ifdef HAVE_BROTLI
@@ -108,9 +104,8 @@ zfree_cb(voidpf opaque, voidpf ptr)
}
static CURLcode
-process_zlib_error(struct connectdata *conn, z_stream *z)
+process_zlib_error(struct Curl_easy *data, z_stream *z)
{
- struct Curl_easy *data = conn->data;
if(z->msg)
failf(data, "Error while processing content unencoding: %s",
z->msg);
@@ -122,7 +117,7 @@ process_zlib_error(struct connectdata *conn, z_stream *z)
}
static CURLcode
-exit_zlib(struct connectdata *conn,
+exit_zlib(struct Curl_easy *data,
z_stream *z, zlibInitState *zlib_init, CURLcode result)
{
if(*zlib_init == ZLIB_GZIP_HEADER)
@@ -130,14 +125,14 @@ exit_zlib(struct connectdata *conn,
if(*zlib_init != ZLIB_UNINIT) {
if(inflateEnd(z) != Z_OK && result == CURLE_OK)
- result = process_zlib_error(conn, z);
+ result = process_zlib_error(data, z);
*zlib_init = ZLIB_UNINIT;
}
return result;
}
-static CURLcode process_trailer(struct connectdata *conn,
+static CURLcode process_trailer(struct Curl_easy *data,
struct zlib_params *zp)
{
z_stream *z = &zp->z;
@@ -153,7 +148,7 @@ static CURLcode process_trailer(struct connectdata *conn,
if(z->avail_in)
result = CURLE_WRITE_ERROR;
if(result || !zp->trailerlen)
- result = exit_zlib(conn, z, &zp->zlib_init, result);
+ result = exit_zlib(data, z, &zp->zlib_init, result);
else {
/* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
@@ -161,7 +156,7 @@ static CURLcode process_trailer(struct connectdata *conn,
return result;
}
-static CURLcode inflate_stream(struct connectdata *conn,
+static CURLcode inflate_stream(struct Curl_easy *data,
struct contenc_writer *writer,
zlibInitState started)
{
@@ -178,13 +173,13 @@ static CURLcode inflate_stream(struct connectdata *conn,
zp->zlib_init != ZLIB_INFLATING &&
zp->zlib_init != ZLIB_INIT_GZIP &&
zp->zlib_init != ZLIB_GZIP_INFLATING)
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
/* Dynamically allocate a buffer for decompression because it's uncommonly
large to hold on the stack */
decomp = malloc(DSIZ);
if(decomp == NULL)
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via downstream_write function. */
@@ -208,10 +203,10 @@ static CURLcode inflate_stream(struct connectdata *conn,
if(z->avail_out != DSIZ) {
if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */
- result = Curl_unencode_write(conn, writer->downstream, decomp,
+ result = Curl_unencode_write(data, writer->downstream, decomp,
DSIZ - z->avail_out);
if(result) {
- exit_zlib(conn, z, &zp->zlib_init, result);
+ exit_zlib(data, z, &zp->zlib_init, result);
break;
}
}
@@ -227,7 +222,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* No more data to flush: just exit loop. */
break;
case Z_STREAM_END:
- result = process_trailer(conn, zp);
+ result = process_trailer(data, zp);
break;
case Z_DATA_ERROR:
/* some servers seem to not generate zlib headers, so this is an attempt
@@ -247,7 +242,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
}
/* FALLTHROUGH */
default:
- result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
+ result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
break;
}
}
@@ -264,7 +259,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* Deflate handler. */
-static CURLcode deflate_init_writer(struct connectdata *conn,
+static CURLcode deflate_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
@@ -278,12 +273,12 @@ static CURLcode deflate_init_writer(struct connectdata *conn,
z->zfree = (free_func) zfree_cb;
if(inflateInit(z) != Z_OK)
- return process_zlib_error(conn, z);
+ return process_zlib_error(data, z);
zp->zlib_init = ZLIB_INIT;
return CURLE_OK;
}
-static CURLcode deflate_unencode_write(struct connectdata *conn,
+static CURLcode deflate_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -295,19 +290,19 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
z->avail_in = (uInt) nbytes;
if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
- return process_trailer(conn, zp);
+ return process_trailer(data, zp);
/* Now uncompress the data */
- return inflate_stream(conn, writer, ZLIB_INFLATING);
+ return inflate_stream(data, writer, ZLIB_INFLATING);
}
-static void deflate_close_writer(struct connectdata *conn,
+static void deflate_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
- exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
+ exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
static const struct content_encoding deflate_encoding = {
@@ -321,7 +316,7 @@ static const struct content_encoding deflate_encoding = {
/* Gzip handler. */
-static CURLcode gzip_init_writer(struct connectdata *conn,
+static CURLcode gzip_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
@@ -337,14 +332,14 @@ static CURLcode gzip_init_writer(struct connectdata *conn,
if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
- return process_zlib_error(conn, z);
+ return process_zlib_error(data, z);
}
zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
}
else {
/* we must parse the gzip header and trailer ourselves */
if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
- return process_zlib_error(conn, z);
+ return process_zlib_error(data, z);
}
zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
zp->zlib_init = ZLIB_INIT; /* Initial call state */
@@ -437,7 +432,7 @@ static enum {
}
#endif
-static CURLcode gzip_unencode_write(struct connectdata *conn,
+static CURLcode gzip_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -449,13 +444,13 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
/* Now uncompress the data */
- return inflate_stream(conn, writer, ZLIB_INIT_GZIP);
+ return inflate_stream(data, writer, ZLIB_INIT_GZIP);
}
#ifndef OLD_ZLIB_SUPPORT
/* Support for old zlib versions is compiled away and we are running with
an old version, so return an error. */
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
#else
/* This next mess is to get around the potential case where there isn't
@@ -493,7 +488,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
z->avail_in = (uInt) nbytes;
z->next_in = malloc(z->avail_in);
if(z->next_in == NULL) {
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
memcpy(z->next_in, buf, z->avail_in);
zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
@@ -502,7 +497,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case GZIP_BAD:
default:
- return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
+ return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
}
}
@@ -515,7 +510,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
z->avail_in += (uInt) nbytes;
z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
if(z->next_in == NULL) {
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);
@@ -536,7 +531,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case GZIP_BAD:
default:
- return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
+ return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
}
}
@@ -545,7 +540,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case ZLIB_EXTERNAL_TRAILER:
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
- return process_trailer(conn, zp);
+ return process_trailer(data, zp);
case ZLIB_GZIP_INFLATING:
default:
@@ -561,17 +556,17 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
}
/* We've parsed the header, now uncompress the data */
- return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING);
+ return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
#endif
}
-static void gzip_close_writer(struct connectdata *conn,
+static void gzip_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
- exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
+ exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
static const struct content_encoding gzip_encoding = {
@@ -630,11 +625,11 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
return CURLE_WRITE_ERROR;
}
-static CURLcode brotli_init_writer(struct connectdata *conn,
+static CURLcode brotli_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct brotli_params *bp = (struct brotli_params *) &writer->params;
- (void) conn;
+ (void) data;
if(!writer->downstream)
return CURLE_WRITE_ERROR;
@@ -643,7 +638,7 @@ static CURLcode brotli_init_writer(struct connectdata *conn,
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}
-static CURLcode brotli_unencode_write(struct connectdata *conn,
+static CURLcode brotli_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -668,7 +663,7 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
dstleft = DSIZ;
r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL);
- result = Curl_unencode_write(conn, writer->downstream,
+ result = Curl_unencode_write(data, writer->downstream,
decomp, DSIZ - dstleft);
if(result)
break;
@@ -691,11 +686,11 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
return result;
}
-static void brotli_close_writer(struct connectdata *conn,
+static void brotli_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct brotli_params *bp = (struct brotli_params *) &writer->params;
- (void) conn;
+ (void) data;
if(bp->br) {
BrotliDecoderDestroyInstance(bp->br);
@@ -721,11 +716,11 @@ struct zstd_params {
void *decomp;
};
-static CURLcode zstd_init_writer(struct connectdata *conn,
+static CURLcode zstd_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zstd_params *zp = (struct zstd_params *)&writer->params;
- (void)conn;
+ (void)data;
if(!writer->downstream)
return CURLE_WRITE_ERROR;
@@ -735,9 +730,9 @@ static CURLcode zstd_init_writer(struct connectdata *conn,
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
-static CURLcode zstd_unencode_write(struct connectdata *conn,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
+static CURLcode zstd_unencode_write(struct Curl_easy *data,
+ struct contenc_writer *writer,
+ const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
struct zstd_params *zp = (struct zstd_params *)&writer->params;
@@ -764,7 +759,7 @@ static CURLcode zstd_unencode_write(struct connectdata *conn,
return CURLE_BAD_CONTENT_ENCODING;
}
if(out.pos > 0) {
- result = Curl_unencode_write(conn, writer->downstream,
+ result = Curl_unencode_write(data, writer->downstream,
zp->decomp, out.pos);
if(result)
break;
@@ -776,11 +771,11 @@ static CURLcode zstd_unencode_write(struct connectdata *conn,
return result;
}
-static void zstd_close_writer(struct connectdata *conn,
- struct contenc_writer *writer)
+static void zstd_close_writer(struct Curl_easy *data,
+ struct contenc_writer *writer)
{
struct zstd_params *zp = (struct zstd_params *)&writer->params;
- (void)conn;
+ (void)data;
if(zp->decomp) {
free(zp->decomp);
@@ -804,24 +799,24 @@ static const struct content_encoding zstd_encoding = {
/* Identity handler. */
-static CURLcode identity_init_writer(struct connectdata *conn,
+static CURLcode identity_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}
-static CURLcode identity_unencode_write(struct connectdata *conn,
+static CURLcode identity_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- return Curl_unencode_write(conn, writer->downstream, buf, nbytes);
+ return Curl_unencode_write(data, writer->downstream, buf, nbytes);
}
-static void identity_close_writer(struct connectdata *conn,
+static void identity_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
(void) writer;
}
@@ -889,18 +884,17 @@ char *Curl_all_content_encodings(void)
/* Real client writer: no downstream. */
-static CURLcode client_init_writer(struct connectdata *conn,
+static CURLcode client_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
}
-static CURLcode client_unencode_write(struct connectdata *conn,
+static CURLcode client_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
(void) writer;
@@ -908,13 +902,13 @@ static CURLcode client_unencode_write(struct connectdata *conn,
if(!nbytes || k->ignorebody)
return CURLE_OK;
- return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes);
+ return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
}
-static void client_close_writer(struct connectdata *conn,
+static void client_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
(void) writer;
}
@@ -929,14 +923,14 @@ static const struct content_encoding client_encoding = {
/* Deferred error dummy writer. */
-static CURLcode error_init_writer(struct connectdata *conn,
+static CURLcode error_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}
-static CURLcode error_unencode_write(struct connectdata *conn,
+static CURLcode error_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -948,16 +942,16 @@ static CURLcode error_unencode_write(struct connectdata *conn,
if(!all)
return CURLE_OUT_OF_MEMORY;
- failf(conn->data, "Unrecognized content encoding type. "
- "libcurl understands %s content encodings.", all);
+ failf(data, "Unrecognized content encoding type. "
+ "libcurl understands %s content encodings.", all);
free(all);
return CURLE_BAD_CONTENT_ENCODING;
}
-static void error_close_writer(struct connectdata *conn,
+static void error_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
(void) writer;
}
@@ -972,7 +966,7 @@ static const struct content_encoding error_encoding = {
/* Create an unencoding writer stage using the given handler. */
static struct contenc_writer *
-new_unencoding_writer(struct connectdata *conn,
+new_unencoding_writer(struct Curl_easy *data,
const struct content_encoding *handler,
struct contenc_writer *downstream)
{
@@ -982,7 +976,7 @@ new_unencoding_writer(struct connectdata *conn,
if(writer) {
writer->handler = handler;
writer->downstream = downstream;
- if(handler->init_writer(conn, writer)) {
+ if(handler->init_writer(data, writer)) {
free(writer);
writer = NULL;
}
@@ -992,25 +986,24 @@ new_unencoding_writer(struct connectdata *conn,
}
/* Write data using an unencoding writer stack. */
-CURLcode Curl_unencode_write(struct connectdata *conn,
+CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
if(!nbytes)
return CURLE_OK;
- return writer->handler->unencode_write(conn, writer, buf, nbytes);
+ return writer->handler->unencode_write(data, writer, buf, nbytes);
}
/* Close and clean-up the connection's writer stack. */
-void Curl_unencode_cleanup(struct connectdata *conn)
+void Curl_unencode_cleanup(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
struct contenc_writer *writer = k->writer_stack;
while(writer) {
k->writer_stack = writer->downstream;
- writer->handler->close_writer(conn, writer);
+ writer->handler->close_writer(data, writer);
free(writer);
writer = k->writer_stack;
}
@@ -1033,10 +1026,9 @@ static const struct content_encoding *find_encoding(const char *name,
/* Set-up the unencoding stack from the Content-Encoding header value.
* See RFC 7231 section 3.1.2.2. */
-CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked)
{
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
do {
@@ -1056,14 +1048,14 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
/* Special case: chunked encoding is handled at the reader level. */
if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) {
k->chunk = TRUE; /* chunks coming our way. */
- Curl_httpchunk_init(conn); /* init our chunky engine. */
+ Curl_httpchunk_init(data); /* init our chunky engine. */
}
else if(namelen) {
const struct content_encoding *encoding = find_encoding(name, namelen);
struct contenc_writer *writer;
if(!k->writer_stack) {
- k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL);
+ k->writer_stack = new_unencoding_writer(data, &client_encoding, NULL);
if(!k->writer_stack)
return CURLE_OUT_OF_MEMORY;
@@ -1073,7 +1065,7 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
encoding = &error_encoding; /* Defer error at stack use. */
/* Stack the unencoding stage. */
- writer = new_unencoding_writer(conn, encoding, k->writer_stack);
+ writer = new_unencoding_writer(data, encoding, k->writer_stack);
if(!writer)
return CURLE_OUT_OF_MEMORY;
k->writer_stack = writer;
@@ -1085,29 +1077,29 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
#else
/* Stubs for builds without HTTP. */
-CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked)
{
- (void) conn;
+ (void) data;
(void) enclist;
(void) maybechunked;
return CURLE_NOT_BUILT_IN;
}
-CURLcode Curl_unencode_write(struct connectdata *conn,
+CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- (void) conn;
+ (void) data;
(void) writer;
(void) buf;
(void) nbytes;
return CURLE_NOT_BUILT_IN;
}
-void Curl_unencode_cleanup(struct connectdata *conn)
+void Curl_unencode_cleanup(struct Curl_easy *data)
{
- (void) conn;
+ (void) data;
}
char *Curl_all_content_encodings(void)
diff --git a/Utilities/cmcurl/lib/content_encoding.h b/Utilities/cmcurl/lib/content_encoding.h
index bdd3f1c8c..acfd0c27b 100644
--- a/Utilities/cmcurl/lib/content_encoding.h
+++ b/Utilities/cmcurl/lib/content_encoding.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,23 +33,23 @@ struct contenc_writer {
struct content_encoding {
const char *name; /* Encoding name. */
const char *alias; /* Encoding name alias. */
- CURLcode (*init_writer)(struct connectdata *conn,
+ CURLcode (*init_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
- CURLcode (*unencode_write)(struct connectdata *conn,
+ CURLcode (*unencode_write)(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
- void (*close_writer)(struct connectdata *conn,
+ void (*close_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
size_t paramsize;
};
-CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked);
-CURLcode Curl_unencode_write(struct connectdata *conn,
+CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
-void Curl_unencode_cleanup(struct connectdata *conn);
+void Curl_unencode_cleanup(struct Curl_easy *data);
char *Curl_all_content_encodings(void);
#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index cb7d94b10..09fd092ac 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -264,6 +264,11 @@ static const char *get_top_domain(const char * const domain, size_t *outlen)
return first? first: domain;
}
+/* Avoid C1001, an "internal error" with MSVC14 */
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+#pragma optimize("", off)
+#endif
+
/*
* A case-insensitive hash for the cookie domains.
*/
@@ -280,6 +285,10 @@ static size_t cookie_hash_domain(const char *domain, const size_t len)
return (h % COOKIE_HASH_SIZE);
}
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+#pragma optimize("", on)
+#endif
+
/*
* Hash this domain.
*/
@@ -1539,7 +1548,7 @@ static int cookie_output(struct Curl_easy *data,
}
fputs("# Netscape HTTP Cookie File\n"
- "# https://curl.haxx.se/docs/http-cookies.html\n"
+ "# https://curl.se/docs/http-cookies.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index b3865e601..e0aa383be 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -34,12 +34,12 @@ struct Cookie {
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */
- bool tailmatch; /* whether we do tail-matching of the domain name */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */
+ bool tailmatch; /* whether we do tail-matching of the domain name */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
bool httponly; /* true if the httponly directive is present */
@@ -61,8 +61,8 @@ struct CookieInfo {
struct Cookie *cookies[COOKIE_HASH_SIZE];
char *filename; /* file we read from/write to */
- bool running; /* state info, for cookie adding information */
long numcookies; /* number of cookies in the "jar" */
+ bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */
int lastct; /* last creation-time used in the jar */
};
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 947d0d375..06537b275 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -285,7 +285,7 @@ Curl_he2ai(const struct hostent *he, int port)
#endif
ss_size = sizeof(struct sockaddr_in);
- /* allocate memory to told the struct, the address and the name */
+ /* allocate memory to hold the struct, the address and the name */
ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.h b/Utilities/cmcurl/lib/curl_addrinfo.h
index a0cade614..73a8c1b33 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.h
+++ b/Utilities/cmcurl/lib/curl_addrinfo.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_base64.h b/Utilities/cmcurl/lib/curl_base64.h
index cfb6ee75b..d48edc424 100644
--- a/Utilities/cmcurl/lib/curl_base64.h
+++ b/Utilities/cmcurl/lib/curl_base64.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index d5bf4feff..8dfe3285c 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -56,8 +56,8 @@
/* to disable LDAPS */
#cmakedefine CURL_DISABLE_LDAPS 1
-/* to enable MQTT */
-#undef CURL_ENABLE_MQTT
+/* to disable MQTT */
+#cmakedefine CURL_DISABLE_MQTT 1
/* to disable POP3 */
#cmakedefine CURL_DISABLE_POP3 1
@@ -388,8 +388,11 @@
/* Define to 1 if you have the <libgen.h> header file. */
#cmakedefine HAVE_LIBGEN_H 1
-/* Define to 1 if you have the `idn' library (-lidn). */
-#cmakedefine HAVE_LIBIDN 1
+/* Define to 1 if you have the `idn2' library (-lidn2). */
+#cmakedefine HAVE_LIBIDN2 1
+
+/* Define to 1 if you have the idn2.h header file. */
+#cmakedefine HAVE_IDN2_H 1
/* Define to 1 if you have the `resolv' library (-lresolv). */
#cmakedefine HAVE_LIBRESOLV 1
@@ -462,6 +465,9 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#cmakedefine HAVE_NETINET_TCP_H 1
+/* Define to 1 if you have the <linux/tcp.h> header file. */
+#cmakedefine HAVE_LINUX_TCP_H 1
+
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1
@@ -999,6 +1005,10 @@ ${SIZEOF_TIME_T_CODE}
/* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1
+/* Define to 1 if you don't want the OpenSSL configuration to be loaded
+ automatically */
+#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1
+
/* to enable NGHTTP2 */
#cmakedefine USE_NGHTTP2 1
@@ -1017,8 +1027,8 @@ ${SIZEOF_TIME_T_CODE}
/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS
-/* to enable alt-svc */
-#cmakedefine USE_ALTSVC 1
+/* to disable alt-svc */
+#cmakedefine CURL_DISABLE_ALTSVC 1
/* to enable SSPI support */
#cmakedefine USE_WINDOWS_SSPI 1
diff --git a/Utilities/cmcurl/lib/curl_ctype.c b/Utilities/cmcurl/lib/curl_ctype.c
index 1a47fb5e6..d6cd08a07 100644
--- a/Utilities/cmcurl/lib/curl_ctype.c
+++ b/Utilities/cmcurl/lib/curl_ctype.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_ctype.h b/Utilities/cmcurl/lib/curl_ctype.h
index 6e94bb1b4..17dfaa094 100644
--- a/Utilities/cmcurl/lib/curl_ctype.h
+++ b/Utilities/cmcurl/lib/curl_ctype.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_des.c b/Utilities/cmcurl/lib/curl_des.c
index 39c0f35ee..8c5af19cd 100644
--- a/Utilities/cmcurl/lib/curl_des.c
+++ b/Utilities/cmcurl/lib/curl_des.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2015 - 2020, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_des.h b/Utilities/cmcurl/lib/curl_des.h
index a42eeb53f..438706a0d 100644
--- a/Utilities/cmcurl/lib/curl_des.h
+++ b/Utilities/cmcurl/lib/curl_des.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2015 - 2020, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index a774d136e..2fc25bc17 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/lib/curl_endian.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index 9830e58fd..341dfaf3c 100644
--- a/Utilities/cmcurl/lib/curl_endian.h
+++ b/Utilities/cmcurl/lib/curl_endian.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index ab3e7428d..4bfa58598 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.h b/Utilities/cmcurl/lib/curl_fnmatch.h
index 34fccae48..1c80ea779 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.h
+++ b/Utilities/cmcurl/lib/curl_fnmatch.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_get_line.c b/Utilities/cmcurl/lib/curl_get_line.c
index c4194851a..438ede704 100644
--- a/Utilities/cmcurl/lib/curl_get_line.c
+++ b/Utilities/cmcurl/lib/curl_get_line.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -22,6 +22,9 @@
#include "curl_setup.h"
+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
+ defined(USE_HSTS)
+
#include "curl_get_line.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -53,3 +56,5 @@ char *Curl_get_line(char *buf, int len, FILE *input)
}
return NULL;
}
+
+#endif /* if not disabled */
diff --git a/Utilities/cmcurl/lib/curl_get_line.h b/Utilities/cmcurl/lib/curl_get_line.h
index 532ab080a..597aa09a9 100644
--- a/Utilities/cmcurl/lib/curl_get_line.h
+++ b/Utilities/cmcurl/lib/curl_get_line.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_gethostname.c b/Utilities/cmcurl/lib/curl_gethostname.c
index 8337c72e8..2d5ff61cf 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.c
+++ b/Utilities/cmcurl/lib/curl_gethostname.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -48,7 +48,7 @@
* For libcurl static library release builds no overriding takes place.
*/
-int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen)
+int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
{
#ifndef HAVE_GETHOSTNAME
diff --git a/Utilities/cmcurl/lib/curl_gethostname.h b/Utilities/cmcurl/lib/curl_gethostname.h
index 8ae15e6c1..2161c40ac 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.h
+++ b/Utilities/cmcurl/lib/curl_gethostname.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -26,6 +26,6 @@
#define HOSTNAME_MAX 1024
/* This returns the local machine's un-qualified hostname */
-int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen);
+int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen);
#endif /* HEADER_CURL_GETHOSTNAME_H */
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index d854ab0c7..6445fbad0 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -131,6 +131,10 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
infof(data, "%s%s\n", prefix, buf);
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+ (void)prefix;
+#endif
}
#endif /* HAVE_GSSAPI */
diff --git a/Utilities/cmcurl/lib/curl_gssapi.h b/Utilities/cmcurl/lib/curl_gssapi.h
index 88f68dbbb..466d09ed0 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.h
+++ b/Utilities/cmcurl/lib/curl_gssapi.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_hmac.h b/Utilities/cmcurl/lib/curl_hmac.h
index 9b70c8468..84c73121b 100644
--- a/Utilities/cmcurl/lib/curl_hmac.h
+++ b/Utilities/cmcurl/lib/curl_hmac.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sec.h b/Utilities/cmcurl/lib/curl_krb5.h
index 7bdde269b..3f40f9a6c 100644
--- a/Utilities/cmcurl/lib/curl_sec.h
+++ b/Utilities/cmcurl/lib/curl_krb5.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_SECURITY_H
-#define HEADER_CURL_SECURITY_H
+#ifndef HEADER_CURL_KRB5_H
+#define HEADER_CURL_KRB5_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -26,7 +26,7 @@ struct Curl_sec_client_mech {
const char *name;
size_t size;
int (*init)(void *);
- int (*auth)(void *, struct connectdata *);
+ int (*auth)(void *, struct Curl_easy *data, struct connectdata *);
void (*end)(void *);
int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
@@ -39,13 +39,13 @@ struct Curl_sec_client_mech {
#define AUTH_ERROR 2
#ifdef HAVE_GSSAPI
-int Curl_sec_read_msg(struct connectdata *conn, char *,
+int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *,
enum protection_level);
void Curl_sec_end(struct connectdata *);
-CURLcode Curl_sec_login(struct connectdata *);
+CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *);
int Curl_sec_request_prot(struct connectdata *conn, const char *level);
-
-extern struct Curl_sec_client_mech Curl_krb5_client_mech;
+#else
+#define Curl_sec_end(x)
#endif
-#endif /* HEADER_CURL_SECURITY_H */
+#endif /* HEADER_CURL_KRB5_H */
diff --git a/Utilities/cmcurl/lib/curl_ldap.h b/Utilities/cmcurl/lib/curl_ldap.h
index 912e13107..124e18b13 100644
--- a/Utilities/cmcurl/lib/curl_ldap.h
+++ b/Utilities/cmcurl/lib/curl_ldap.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_md4.h b/Utilities/cmcurl/lib/curl_md4.h
index c7bb20981..f9dafcb53 100644
--- a/Utilities/cmcurl/lib/curl_md4.h
+++ b/Utilities/cmcurl/lib/curl_md4.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_md5.h b/Utilities/cmcurl/lib/curl_md5.h
index e06c68edf..5739c89ca 100644
--- a/Utilities/cmcurl/lib/curl_md5.h
+++ b/Utilities/cmcurl/lib/curl_md5.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_memory.h b/Utilities/cmcurl/lib/curl_memory.h
index ce38a08cd..580629063 100644
--- a/Utilities/cmcurl/lib/curl_memory.h
+++ b/Utilities/cmcurl/lib/curl_memory.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_memrchr.c b/Utilities/cmcurl/lib/curl_memrchr.c
index eeb3044a9..0bd845f69 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.c
+++ b/Utilities/cmcurl/lib/curl_memrchr.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_memrchr.h b/Utilities/cmcurl/lib/curl_memrchr.h
index 90a8a07cc..c8394bb43 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.h
+++ b/Utilities/cmcurl/lib/curl_memrchr.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_multibyte.c b/Utilities/cmcurl/lib/curl_multibyte.c
index 2c8925b53..d327c8ba7 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.c
+++ b/Utilities/cmcurl/lib/curl_multibyte.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_multibyte.h b/Utilities/cmcurl/lib/curl_multibyte.h
index 5f8c05afc..8adaf4978 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.h
+++ b/Utilities/cmcurl/lib/curl_multibyte.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 0eefb1587..9a075ac90 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -22,7 +22,7 @@
#include "curl_setup.h"
-#if defined(USE_NTLM)
+#if defined(USE_CURL_NTLM_CORE)
/*
* NTLM details:
@@ -50,8 +50,6 @@
in NTLM type-3 messages.
*/
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
#ifdef USE_WOLFSSL
@@ -582,15 +580,11 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
unsigned char *identity;
CURLcode result = CURLE_OK;
- /* we do the length checks below separately to avoid integer overflow risk
- on extreme data lengths */
- if((userlen > SIZE_T_MAX/2) ||
- (domlen > SIZE_T_MAX/2) ||
- ((userlen + domlen) > SIZE_T_MAX/2))
+ if((userlen > CURL_MAX_INPUT_LENGTH) || (domlen > CURL_MAX_INPUT_LENGTH))
return CURLE_OUT_OF_MEMORY;
identity_len = (userlen + domlen) * 2;
- identity = malloc(identity_len);
+ identity = malloc(identity_len + 1);
if(!identity)
return CURLE_OUT_OF_MEMORY;
@@ -744,6 +738,4 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
#endif /* USE_NTRESPONSES */
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* USE_NTLM */
+#endif /* USE_CURL_NTLM_CORE */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.h b/Utilities/cmcurl/lib/curl_ntlm_core.h
index 7895b6470..fab628c59 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if defined(USE_NTLM)
+#if defined(USE_CURL_NTLM_CORE)
/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
then it must be initialized to be used by NTLM. */
@@ -36,8 +36,6 @@
#define NTLM_NEEDS_NSS_INIT
#endif
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
#ifdef USE_WOLFSSL
# include <wolfssl/options.h>
@@ -102,8 +100,6 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
#endif /* USE_NTRESPONSES */
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* USE_NTLM */
+#endif /* USE_CURL_NTLM_CORE */
#endif /* HEADER_CURL_NTLM_CORE_H */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index 17a92f8ca..9af79fd66 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -329,13 +329,16 @@ done:
return CURLE_REMOTE_ACCESS_DENIED;
}
-CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
+CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
+ struct connectdata *conn,
bool proxy,
const char *header)
{
struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
+ (void) data; /* In case it gets unused by nop log macros. */
+
if(!checkprefix("NTLM", header))
return CURLE_BAD_CONTENT_ENCODING;
@@ -352,17 +355,17 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
}
else {
if(*state == NTLMSTATE_LAST) {
- infof(conn->data, "NTLM auth restarted\n");
+ infof(data, "NTLM auth restarted\n");
Curl_http_auth_cleanup_ntlm_wb(conn);
}
else if(*state == NTLMSTATE_TYPE3) {
- infof(conn->data, "NTLM handshake rejected\n");
+ infof(data, "NTLM handshake rejected\n");
Curl_http_auth_cleanup_ntlm_wb(conn);
*state = NTLMSTATE_NONE;
return CURLE_REMOTE_ACCESS_DENIED;
}
else if(*state >= NTLMSTATE_TYPE1) {
- infof(conn->data, "NTLM handshake failure (internal error)\n");
+ infof(data, "NTLM handshake failure (internal error)\n");
return CURLE_REMOTE_ACCESS_DENIED;
}
@@ -376,7 +379,8 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
* This is for creating ntlm header output by delegating challenge/response
* to Samba's winbind daemon helper ntlm_auth.
*/
-CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
+CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy)
{
/* 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 */
@@ -386,12 +390,11 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
struct ntlmdata *ntlm;
curlntlm *state;
struct auth *authp;
- struct Curl_easy *data = conn->data;
CURLcode res = CURLE_OK;
DEBUGASSERT(conn);
- DEBUGASSERT(conn->data);
+ DEBUGASSERT(data);
if(proxy) {
#ifndef CURL_DISABLE_PROXY
@@ -399,7 +402,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
userp = conn->http_proxy.user;
ntlm = &conn->proxyntlm;
state = &conn->proxy_ntlm_state;
- authp = &conn->data->state.authproxy;
+ authp = &data->state.authproxy;
#else
return CURLE_NOT_BUILT_IN;
#endif
@@ -409,7 +412,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
userp = conn->user;
ntlm = &conn->ntlm;
state = &conn->http_ntlm_state;
- authp = &conn->data->state.authhost;
+ authp = &data->state.authhost;
}
authp->done = FALSE;
@@ -433,10 +436,10 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
* request handling process.
*/
/* Create communication with ntlm_auth */
- res = ntlm_wb_init(conn->data, ntlm, userp);
+ res = ntlm_wb_init(data, ntlm, userp);
if(res)
return res;
- res = ntlm_wb_response(conn->data, ntlm, "YR\n", *state);
+ res = ntlm_wb_response(data, ntlm, "YR\n", *state);
if(res)
return res;
@@ -454,7 +457,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
char *input = aprintf("TT %s\n", ntlm->challenge);
if(!input)
return CURLE_OUT_OF_MEMORY;
- res = ntlm_wb_response(conn->data, ntlm, input, *state);
+ res = ntlm_wb_response(data, ntlm, input, *state);
free(input);
if(res)
return res;
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.h b/Utilities/cmcurl/lib/curl_ntlm_wb.h
index 3cf841cf2..961b56873 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -28,11 +28,13 @@
defined(NTLM_WB_ENABLED)
/* this is for ntlm header input */
-CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy,
+CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
+ struct connectdata *conn, bool proxy,
const char *header);
/* this is for creating ntlm header output */
-CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
+CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy);
void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/curl_path.c b/Utilities/cmcurl/lib/curl_path.c
index fbd98cb39..6100d77bd 100644
--- a/Utilities/cmcurl/lib/curl_path.c
+++ b/Utilities/cmcurl/lib/curl_path.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -31,12 +31,11 @@
#include "memdebug.h"
/* figure out the path to work with in this particular request */
-CURLcode Curl_getworkingpath(struct connectdata *conn,
+CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir, /* when SFTP is used */
char **path) /* returns the allocated
real path to work with */
{
- struct Curl_easy *data = conn->data;
char *real_path = NULL;
char *working_path;
size_t working_path_len;
@@ -47,7 +46,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
return result;
/* Check for /~/, indicating relative to the user's home directory */
- if(conn->handler->protocol & CURLPROTO_SCP) {
+ if(data->conn->handler->protocol & CURLPROTO_SCP) {
real_path = malloc(working_path_len + 1);
if(real_path == NULL) {
free(working_path);
@@ -59,7 +58,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
else
memcpy(real_path, working_path, 1 + working_path_len);
}
- else if(conn->handler->protocol & CURLPROTO_SFTP) {
+ else if(data->conn->handler->protocol & CURLPROTO_SFTP) {
if((working_path_len > 1) && (working_path[1] == '~')) {
size_t homelen = strlen(homedir);
real_path = malloc(homelen + working_path_len + 1);
@@ -168,7 +167,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
*cpp = cp + i + strspn(cp + i, WHITESPACE);
}
else {
- /* Read to end of filename - either to white space or terminator */
+ /* Read to end of filename - either to whitespace or terminator */
end = strpbrk(cp, WHITESPACE);
if(end == NULL)
end = strchr(cp, '\0');
@@ -184,7 +183,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
(*path)[pathLength] = '\0';
cp += 3;
}
- /* Copy path name up until first "white space" */
+ /* Copy path name up until first "whitespace" */
memcpy(&(*path)[pathLength], cp, (int)(end - cp));
pathLength += (int)(end - cp);
(*path)[pathLength] = '\0';
diff --git a/Utilities/cmcurl/lib/curl_path.h b/Utilities/cmcurl/lib/curl_path.h
index 636c37f20..a376bd1d2 100644
--- a/Utilities/cmcurl/lib/curl_path.h
+++ b/Utilities/cmcurl/lib/curl_path.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -39,7 +39,7 @@
have their definition hidden well */
#endif
-CURLcode Curl_getworkingpath(struct connectdata *conn,
+CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir,
char **path);
diff --git a/Utilities/cmcurl/lib/curl_printf.h b/Utilities/cmcurl/lib/curl_printf.h
index 0d37b8e57..9fa625f10 100644
--- a/Utilities/cmcurl/lib/curl_printf.h
+++ b/Utilities/cmcurl/lib/curl_printf.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_range.c b/Utilities/cmcurl/lib/curl_range.c
index aa3c49332..f7fb7c082 100644
--- a/Utilities/cmcurl/lib/curl_range.c
+++ b/Utilities/cmcurl/lib/curl_range.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,12 +33,11 @@
Check if this is a range download, and if so, set the internal variables
properly.
*/
-CURLcode Curl_range(struct connectdata *conn)
+CURLcode Curl_range(struct Curl_easy *data)
{
curl_off_t from, to;
char *ptr;
char *ptr2;
- struct Curl_easy *data = conn->data;
if(data->state.use_range && data->state.range) {
CURLofft from_t;
diff --git a/Utilities/cmcurl/lib/curl_range.h b/Utilities/cmcurl/lib/curl_range.h
index 2350df992..0a07baf14 100644
--- a/Utilities/cmcurl/lib/curl_range.h
+++ b/Utilities/cmcurl/lib/curl_range.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -25,6 +25,5 @@
#include "curl_setup.h"
#include "urldata.h"
-CURLcode Curl_range(struct connectdata *conn);
-
+CURLcode Curl_range(struct Curl_easy *data);
#endif /* HEADER_CURL_RANGE_H */
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index df8f2b1d9..fabdc8848 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -48,11 +48,13 @@
#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
-static CURLcode rtmp_setup_connection(struct connectdata *conn);
-static CURLcode rtmp_do(struct connectdata *conn, bool *done);
-static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature);
-static CURLcode rtmp_connect(struct connectdata *conn, bool *done);
-static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead);
+static CURLcode rtmp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode rtmp_do(struct Curl_easy *data, bool *done);
+static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature);
+static CURLcode rtmp_connect(struct Curl_easy *data, bool *done);
+static CURLcode rtmp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
static Curl_recv rtmp_recv;
static Curl_send rtmp_send;
@@ -79,6 +81,7 @@ const struct Curl_handler Curl_handler_rtmp = {
ZERO_NULL, /* connection_check */
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
+ CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags*/
};
@@ -100,6 +103,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
ZERO_NULL, /* connection_check */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
+ CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags*/
};
@@ -121,6 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
ZERO_NULL, /* connection_check */
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
+ CURLPROTO_RTMPE, /* family */
PROTOPT_NONE /* flags*/
};
@@ -142,6 +147,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
ZERO_NULL, /* connection_check */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
+ CURLPROTO_RTMPTE, /* family */
PROTOPT_NONE /* flags*/
};
@@ -163,6 +169,7 @@ const struct Curl_handler Curl_handler_rtmps = {
ZERO_NULL, /* connection_check */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
+ CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags*/
};
@@ -184,10 +191,12 @@ const struct Curl_handler Curl_handler_rtmpts = {
ZERO_NULL, /* connection_check */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
+ CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags*/
};
-static CURLcode rtmp_setup_connection(struct connectdata *conn)
+static CURLcode rtmp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
RTMP *r = RTMP_Alloc();
if(!r)
@@ -195,7 +204,7 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn)
RTMP_Init(r);
RTMP_SetBufferMS(r, DEF_BUFTIME);
- if(!RTMP_SetupURL(r, conn->data->change.url)) {
+ if(!RTMP_SetupURL(r, data->change.url)) {
RTMP_Free(r);
return CURLE_URL_MALFORMAT;
}
@@ -203,8 +212,9 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn)
return CURLE_OK;
}
-static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
+static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
SET_RCVTIMEO(tv, 10);
@@ -213,7 +223,7 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
/* We have to know if it's a write before we send the
* connect request packet
*/
- if(conn->data->set.upload)
+ if(data->set.upload)
r->Link.protocol |= RTMP_FEATURE_WRITE;
/* For plain streams, use the buffer toggle trick to keep data flowing */
@@ -237,15 +247,15 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode rtmp_do(struct connectdata *conn, bool *done)
+static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
if(!RTMP_ConnectStream(r, 0))
return CURLE_FAILED_INIT;
- if(conn->data->set.upload) {
+ if(data->set.upload) {
Curl_pgrsSetUploadSize(data, data->state.infilesize);
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
}
@@ -255,20 +265,22 @@ static CURLcode rtmp_do(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode rtmp_done(struct connectdata *conn, CURLcode status,
+static CURLcode rtmp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
- (void)conn; /* unused */
+ (void)data; /* unused */
(void)status; /* unused */
(void)premature; /* unused */
return CURLE_OK;
}
-static CURLcode rtmp_disconnect(struct connectdata *conn,
+static CURLcode rtmp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
RTMP *r = conn->proto.rtmp;
+ (void)data;
(void)dead_connection;
if(r) {
conn->proto.rtmp = NULL;
@@ -278,9 +290,10 @@ static CURLcode rtmp_disconnect(struct connectdata *conn,
return CURLE_OK;
}
-static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
+static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *err)
{
+ struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
ssize_t nread;
@@ -289,8 +302,8 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
nread = RTMP_Read(r, buf, curlx_uztosi(len));
if(nread < 0) {
if(r->m_read.status == RTMP_READ_COMPLETE ||
- r->m_read.status == RTMP_READ_EOF) {
- conn->data->req.size = conn->data->req.bytecount;
+ r->m_read.status == RTMP_READ_EOF) {
+ data->req.size = data->req.bytecount;
nread = 0;
}
else
@@ -299,9 +312,10 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
return nread;
}
-static ssize_t rtmp_send(struct connectdata *conn, int sockindex,
+static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
+ struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
ssize_t num;
diff --git a/Utilities/cmcurl/lib/curl_rtmp.h b/Utilities/cmcurl/lib/curl_rtmp.h
index 86a01382d..f45fa71d1 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.h
+++ b/Utilities/cmcurl/lib/curl_rtmp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2019, Howard Chu, <hyc@highlandsun.com>
+ * Copyright (C) 2010 - 2020, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 83fe896e3..ffeb75164 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -194,7 +194,7 @@ void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params)
*
* This is the ONLY way to change SASL state!
*/
-static void state(struct SASL *sasl, struct connectdata *conn,
+static void state(struct SASL *sasl, struct Curl_easy *data,
saslstate newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -221,10 +221,10 @@ static void state(struct SASL *sasl, struct connectdata *conn,
};
if(sasl->state != newstate)
- infof(conn->data, "SASL %p state change from %s to %s\n",
+ infof(data, "SASL %p state change from %s to %s\n",
(void *)sasl, names[sasl->state], names[newstate]);
#else
- (void) conn;
+ (void) data;
#endif
sasl->state = newstate;
@@ -253,11 +253,11 @@ bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn)
*
* Calculate the required login details for SASL authentication.
*/
-CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
bool force_ir, saslprogress *progress)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
unsigned int enabledmechs;
const char *mech = NULL;
char *resp = NULL;
@@ -398,10 +398,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
resp = NULL;
}
- result = sasl->params->sendauth(conn, mech, resp);
+ result = sasl->params->sendauth(data, conn, mech, resp);
if(!result) {
*progress = SASL_INPROGRESS;
- state(sasl, conn, resp ? state2 : state1);
+ state(sasl, data, resp ? state2 : state1);
}
}
@@ -415,11 +415,11 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
*
* Continue the authentication.
*/
-CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
int code, saslprogress *progress)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
saslstate newstate = SASL_FINAL;
char *resp = NULL;
#ifndef CURL_DISABLE_PROXY
@@ -450,14 +450,14 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
if(code != sasl->params->finalcode)
result = CURLE_LOGIN_DENIED;
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return result;
}
if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
code != sasl->params->contcode) {
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -587,7 +587,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
if(code == sasl->params->finalcode) {
/* Final response was received so we are done */
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return result;
}
else if(code == sasl->params->contcode) {
@@ -600,7 +600,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
}
else {
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -609,7 +609,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
sasl->authmechs ^= sasl->authused;
/* Start an alternative SASL authentication */
- result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress);
+ result = Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress);
newstate = sasl->state; /* Use state from Curl_sasl_start() */
break;
default:
@@ -621,12 +621,12 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
switch(result) {
case CURLE_BAD_CONTENT_ENCODING:
/* Cancel dialog */
- result = sasl->params->sendcont(conn, "*");
+ result = sasl->params->sendcont(data, conn, "*");
newstate = SASL_CANCEL;
break;
case CURLE_OK:
if(resp)
- result = sasl->params->sendcont(conn, resp);
+ result = sasl->params->sendcont(data, conn, resp);
break;
default:
newstate = SASL_STOP; /* Stop on error */
@@ -636,7 +636,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
free(resp);
- state(sasl, conn, newstate);
+ state(sasl, data, newstate);
return result;
}
diff --git a/Utilities/cmcurl/lib/curl_sasl.h b/Utilities/cmcurl/lib/curl_sasl.h
index 7647a48be..75a957583 100644
--- a/Utilities/cmcurl/lib/curl_sasl.h
+++ b/Utilities/cmcurl/lib/curl_sasl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -88,10 +88,12 @@ struct SASLproto {
int contcode; /* Code to receive when continuation is expected */
int finalcode; /* Code to receive upon authentication success */
size_t maxirlen; /* Maximum initial response length */
- CURLcode (*sendauth)(struct connectdata *conn,
+ CURLcode (*sendauth)(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech, const char *ir);
/* Send authentication command */
- CURLcode (*sendcont)(struct connectdata *conn, const char *contauth);
+ CURLcode (*sendcont)(struct Curl_easy *data,
+ struct connectdata *conn, const char *contauth);
/* Send authentication continuation */
void (*getmessage)(char *buffer, char **outptr);
/* Get SASL response message */
@@ -133,11 +135,13 @@ void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params);
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn);
/* Calculate the required login details for SASL authentication */
-CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
bool force_ir, saslprogress *progress);
/* Continue an SASL authentication */
-CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
int code, saslprogress *progress);
#endif /* HEADER_CURL_SASL_H */
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 45a093fbb..ef43b2b49 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -38,8 +38,7 @@
* Define WIN32 when build target is Win32 API
*/
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \
- !defined(__SYMBIAN32__)
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
#define WIN32
#endif
@@ -88,10 +87,6 @@
# include "config-amigaos.h"
#endif
-#ifdef __SYMBIAN32__
-# include "config-symbian.h"
-#endif
-
#ifdef __OS400__
# include "config-os400.h"
#endif
@@ -247,7 +242,7 @@
* interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
* performing this task will result in a synthesized IPv6 address.
*/
-#ifdef __APPLE__
+#if defined(__APPLE__) && !defined(USE_ARES)
#define USE_RESOLVE_ON_IPS 1
#endif
@@ -286,10 +281,16 @@
# include <exec/execbase.h>
# include <proto/exec.h>
# include <proto/dos.h>
+# include <unistd.h>
# ifdef HAVE_PROTO_BSDSOCKET_H
# include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
# endif
+/*
+ * In clib2 arpa/inet.h warns that some prototypes may clash
+ * with bsdsocket.library. This avoids the definition of those.
+ */
+# define __NO_NET_API
#endif
#include <stdio.h>
@@ -575,14 +576,6 @@
/* ---------------------------------------------------------------- */
/*
- * When using WINSOCK, TELNET protocol requires WINSOCK2 API.
- */
-
-#if defined(USE_WINSOCK) && (USE_WINSOCK != 2)
-# define CURL_DISABLE_TELNET 1
-#endif
-
-/*
* msvc 6.0 does not have struct sockaddr_storage and
* does not define IPPROTO_ESP in winsock2.h. But both
* are available if PSDK is properly installed.
@@ -652,13 +645,12 @@ int netware_init(void);
/* Single point where USE_NTLM definition might be defined */
#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
-#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
+#if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
- defined(USE_MBEDTLS) || \
(defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
-#define USE_NTLM
+#define USE_CURL_NTLM_CORE
# if defined(USE_MBEDTLS)
/* Get definition of MBEDTLS_MD4_C */
@@ -666,6 +658,10 @@ int netware_init(void);
# endif
#endif
+
+#if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI)
+#define USE_NTLM
+#endif
#endif
#ifdef CURL_WANTS_CA_BUNDLE_ENV
@@ -717,7 +713,7 @@ int netware_init(void);
defined(HAVE_WINSOCK_H) || \
defined(HAVE_WINSOCK2_H) || \
defined(HAVE_WS2TCPIP_H)
-# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
+# error "WinSock and lwIP TCP/IP stack definitions shall not coexist!"
# endif
#endif
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index e7c00deab..ef60bc7ae 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sha256.h b/Utilities/cmcurl/lib/curl_sha256.h
index 35d286ceb..b4579d769 100644
--- a/Utilities/cmcurl/lib/curl_sha256.h
+++ b/Utilities/cmcurl/lib/curl_sha256.h
@@ -12,7 +12,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -24,6 +24,9 @@
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include "curl_hmac.h"
+
+extern const struct HMAC_params Curl_HMAC_SHA256[1];
#define SHA256_DIGEST_LENGTH 32
diff --git a/Utilities/cmcurl/lib/curl_sspi.c b/Utilities/cmcurl/lib/curl_sspi.c
index 512ce2411..06841ddec 100644
--- a/Utilities/cmcurl/lib/curl_sspi.c
+++ b/Utilities/cmcurl/lib/curl_sspi.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sspi.h b/Utilities/cmcurl/lib/curl_sspi.h
index c09026ebb..881384d4e 100644
--- a/Utilities/cmcurl/lib/curl_sspi.h
+++ b/Utilities/cmcurl/lib/curl_sspi.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_threads.c b/Utilities/cmcurl/lib/curl_threads.c
index b5f10a20e..414614401 100644
--- a/Utilities/cmcurl/lib/curl_threads.c
+++ b/Utilities/cmcurl/lib/curl_threads.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -41,14 +41,14 @@
#if defined(USE_THREADS_POSIX)
-struct curl_actual_call {
+struct Curl_actual_call {
unsigned int (*func)(void *);
void *arg;
};
static void *curl_thread_create_thunk(void *arg)
{
- struct curl_actual_call *ac = arg;
+ struct Curl_actual_call *ac = arg;
unsigned int (*func)(void *) = ac->func;
void *real_arg = ac->arg;
@@ -62,7 +62,7 @@ static void *curl_thread_create_thunk(void *arg)
curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg)
{
curl_thread_t t = malloc(sizeof(pthread_t));
- struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
+ struct Curl_actual_call *ac = malloc(sizeof(struct Curl_actual_call));
if(!(ac && t))
goto err;
diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h
index 65d1a790c..e10b7a1b0 100644
--- a/Utilities/cmcurl/lib/curl_threads.h
+++ b/Utilities/cmcurl/lib/curl_threads.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curlx.h b/Utilities/cmcurl/lib/curlx.h
index 98e51bf56..9f21f60d5 100644
--- a/Utilities/cmcurl/lib/curlx.h
+++ b/Utilities/cmcurl/lib/curlx.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index f529b48f7..4319dadba 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -57,6 +57,7 @@
#include "escape.h"
#include "progress.h"
#include "dict.h"
+#include "curl_printf.h"
#include "strcase.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -66,7 +67,7 @@
* Forward declarations.
*/
-static CURLcode dict_do(struct connectdata *conn, bool *done);
+static CURLcode dict_do(struct Curl_easy *data, bool *done);
/*
* DICT protocol handler.
@@ -90,7 +91,8 @@ const struct Curl_handler Curl_handler_dict = {
ZERO_NULL, /* connection_check */
PORT_DICT, /* defport */
CURLPROTO_DICT, /* protocol */
- PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+ CURLPROTO_DICT, /* family */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
@@ -126,7 +128,51 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
return dictp;
}
-static CURLcode dict_do(struct connectdata *conn, bool *done)
+/* sendf() sends formatted data to the server */
+static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
+ const char *fmt, ...)
+{
+ ssize_t bytes_written;
+ size_t write_len;
+ CURLcode result = CURLE_OK;
+ char *s;
+ char *sptr;
+ va_list ap;
+ va_start(ap, fmt);
+ s = vaprintf(fmt, ap); /* returns an allocated string */
+ va_end(ap);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY; /* failure */
+
+ bytes_written = 0;
+ write_len = strlen(s);
+ sptr = s;
+
+ for(;;) {
+ /* Write the buffer to the socket */
+ result = Curl_write(data, sockfd, sptr, write_len, &bytes_written);
+
+ if(result)
+ break;
+
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
+
+ if((size_t)bytes_written != write_len) {
+ /* if not all was written at once, we must advance the pointer, decrease
+ the size left and try again! */
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ free(s); /* free the output string */
+
+ return result;
+}
+
+static CURLcode dict_do(struct Curl_easy *data, bool *done)
{
char *word;
char *eword;
@@ -136,7 +182,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = data->state.up.path;
@@ -183,18 +229,16 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(!eword)
return CURLE_OUT_OF_MEMORY;
- result = Curl_sendf(sockfd, conn,
- "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
- "MATCH "
- "%s " /* database */
- "%s " /* strategy */
- "%s\r\n" /* word */
- "QUIT\r\n",
-
- database,
- strategy,
- eword
- );
+ result = sendf(sockfd, data,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "MATCH "
+ "%s " /* database */
+ "%s " /* strategy */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+ database,
+ strategy,
+ eword);
free(eword);
@@ -233,14 +277,14 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(!eword)
return CURLE_OUT_OF_MEMORY;
- result = Curl_sendf(sockfd, conn,
- "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
- "DEFINE "
- "%s " /* database */
- "%s\r\n" /* word */
- "QUIT\r\n",
- database,
- eword);
+ result = sendf(sockfd, data,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "DEFINE "
+ "%s " /* database */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+ database,
+ eword);
free(eword);
@@ -261,10 +305,10 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(ppath[i] == ':')
ppath[i] = ' ';
}
- result = Curl_sendf(sockfd, conn,
- "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
- "%s\r\n"
- "QUIT\r\n", ppath);
+ result = sendf(sockfd, data,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "%s\r\n"
+ "QUIT\r\n", ppath);
if(result) {
failf(data, "Failed sending DICT request");
return result;
diff --git a/Utilities/cmcurl/lib/dict.h b/Utilities/cmcurl/lib/dict.h
index 38a55ac0d..6a6c772d1 100644
--- a/Utilities/cmcurl/lib/dict.h
+++ b/Utilities/cmcurl/lib/dict.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
index 8bc3428ff..004244c8d 100644
--- a/Utilities/cmcurl/lib/doh.c
+++ b/Utilities/cmcurl/lib/doh.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -57,12 +57,13 @@ static const char * const errors[]={
"Unexpected TYPE",
"Unexpected CLASS",
"No content",
- "Bad ID"
+ "Bad ID",
+ "Name too long"
};
static const char *doh_strerror(DOHcode code)
{
- if((code >= DOH_OK) && (code <= DOH_DNS_BAD_ID))
+ if((code >= DOH_OK) && (code <= DOH_DNS_NAME_TOO_LONG))
return errors[code];
return "bad error code";
}
@@ -186,19 +187,20 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
}
/* called from multi.c when this DOH transfer is complete */
-static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
+static int doh_done(struct Curl_easy *doh, CURLcode result)
{
struct Curl_easy *data = doh->set.dohfor;
+ struct dohdata *dohp = data->req.doh;
/* so one of the DOH request done for the 'data' transfer is now complete! */
- data->req.doh.pending--;
- infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending);
+ dohp->pending--;
+ infof(data, "a DOH request is completed, %u to go\n", dohp->pending);
if(result)
infof(data, "DOH request %s\n", curl_easy_strerror(result));
- if(!data->req.doh.pending) {
+ if(!dohp->pending) {
/* DOH completed */
- curl_slist_free_all(data->req.doh.headers);
- data->req.doh.headers = NULL;
+ curl_slist_free_all(dohp->headers);
+ dohp->headers = NULL;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
return 0;
@@ -224,7 +226,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
&p->dohlen);
if(d) {
- failf(data, "Failed to encode DOH packet [%d]\n", d);
+ failf(data, "Failed to encode DOH packet [%d]", d);
return CURLE_OUT_OF_MEMORY;
}
@@ -348,8 +350,12 @@ static CURLcode dohprobe(struct Curl_easy *data,
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]);
+ }
- doh->set.fmultidone = Curl_doh_done;
+ doh->set.fmultidone = doh_done;
doh->set.dohfor = data; /* identify for which transfer this is done */
p->easy = doh;
@@ -373,58 +379,64 @@ static CURLcode dohprobe(struct Curl_easy *data,
* 'Curl_addrinfo *' with the address information.
*/
-struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
int slot;
+ struct dohdata *dohp;
+ struct connectdata *conn = data->conn;
*waitp = TRUE; /* this never returns synchronously */
- (void)conn;
(void)hostname;
(void)port;
+ DEBUGASSERT(!data->req.doh);
+ DEBUGASSERT(conn);
+
/* start clean, consider allocating this struct on demand */
- memset(&data->req.doh, 0, sizeof(struct dohdata));
+ dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
+ if(!dohp)
+ return NULL;
conn->bits.doh = TRUE;
- data->req.doh.host = hostname;
- data->req.doh.port = port;
- data->req.doh.headers =
+ dohp->host = hostname;
+ dohp->port = port;
+ dohp->headers =
curl_slist_append(NULL,
"Content-Type: application/dns-message");
- if(!data->req.doh.headers)
+ if(!dohp->headers)
goto error;
if(conn->ip_version != CURL_IPRESOLVE_V6) {
/* create IPv4 DOH request */
- result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4],
+ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
- data->multi, data->req.doh.headers);
+ data->multi, dohp->headers);
if(result)
goto error;
- data->req.doh.pending++;
+ dohp->pending++;
}
if(conn->ip_version != CURL_IPRESOLVE_V4) {
/* create IPv6 DOH request */
- result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6],
+ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
- data->multi, data->req.doh.headers);
+ data->multi, dohp->headers);
if(result)
goto error;
- data->req.doh.pending++;
+ dohp->pending++;
}
return NULL;
error:
- curl_slist_free_all(data->req.doh.headers);
- data->req.doh.headers = NULL;
+ curl_slist_free_all(dohp->headers);
+ data->req.doh->headers = NULL;
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- Curl_close(&data->req.doh.probe[slot].easy);
+ Curl_close(&dohp->probe[slot].easy);
}
+ Curl_safefree(data->req.doh);
return NULL;
}
@@ -463,7 +475,7 @@ static unsigned int get32bit(const unsigned char *doh, int index)
the pointer first. */
doh += index;
- /* avoid undefined behaviour by casting to unsigned before shifting
+ /* avoid undefined behavior by casting to unsigned before shifting
24 bits, possibly into the sign bit. codegen is same, but
ub sanitizer won't be upset */
return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
@@ -899,20 +911,22 @@ UNITTEST void de_cleanup(struct dohentry *d)
}
}
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dnsp)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
+ struct dohdata *dohp = data->req.doh;
*dnsp = NULL; /* defaults to no response */
+ if(!dohp)
+ return CURLE_OUT_OF_MEMORY;
- if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
- !data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
- failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
- return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
+ !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
+ failf(data, "Could not DOH-resolve: %s", data->state.async.hostname);
+ return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
- else if(!data->req.doh.pending) {
+ else if(!dohp->pending) {
DOHcode rc[DOH_PROBE_SLOTS] = {
DOH_OK, DOH_OK
};
@@ -920,13 +934,13 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
int slot;
/* remove DOH handles from multi handle and close them */
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy);
- Curl_close(&data->req.doh.probe[slot].easy);
+ curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
+ Curl_close(&dohp->probe[slot].easy);
}
/* parse the responses, create the struct and return it! */
de_init(&de);
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- struct dnsprobe *p = &data->req.doh.probe[slot];
+ struct dnsprobe *p = &dohp->probe[slot];
if(!p->dnstype)
continue;
rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
@@ -936,7 +950,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_dyn_free(&p->serverdoh);
if(rc[slot]) {
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
- type2name(p->dnstype), data->req.doh.host);
+ type2name(p->dnstype), dohp->host);
}
} /* next slot */
@@ -946,10 +960,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
struct Curl_dns_entry *dns;
struct Curl_addrinfo *ai;
- infof(data, "DOH Host name: %s\n", data->req.doh.host);
+ infof(data, "DOH Host name: %s\n", dohp->host);
showdoh(data, &de);
- ai = doh2ai(&de, data->req.doh.host, data->req.doh.port);
+ ai = doh2ai(&de, dohp->host, dohp->port);
if(!ai) {
de_cleanup(&de);
return CURLE_OUT_OF_MEMORY;
@@ -959,7 +973,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* we got a response, store it in the cache */
- dns = Curl_cache_addr(data, ai, data->req.doh.host, data->req.doh.port);
+ dns = Curl_cache_addr(data, ai, dohp->host, dohp->port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -969,7 +983,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_freeaddrinfo(ai);
}
else {
- conn->async.dns = dns;
+ data->state.async.dns = dns;
*dnsp = dns;
result = CURLE_OK; /* address resolution OK */
}
@@ -979,9 +993,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
/* All done */
de_cleanup(&de);
+ Curl_safefree(data->req.doh);
return result;
- } /* !data->req.doh.pending */
+ } /* !dohp->pending */
/* else wait for pending DOH transactions to complete */
return CURLE_OK;
diff --git a/Utilities/cmcurl/lib/doh.h b/Utilities/cmcurl/lib/doh.h
index bbd4c1a65..b3584d1b2 100644
--- a/Utilities/cmcurl/lib/doh.h
+++ b/Utilities/cmcurl/lib/doh.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -32,12 +32,12 @@
* and returns a 'Curl_addrinfo *' with the address information.
*/
-struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns);
int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
diff --git a/Utilities/cmcurl/lib/dotdot.c b/Utilities/cmcurl/lib/dotdot.c
index ce9a05214..3a1435f8e 100644
--- a/Utilities/cmcurl/lib/dotdot.c
+++ b/Utilities/cmcurl/lib/dotdot.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/dotdot.h b/Utilities/cmcurl/lib/dotdot.h
index f70b1db3f..ac1ea363e 100644
--- a/Utilities/cmcurl/lib/dotdot.h
+++ b/Utilities/cmcurl/lib/dotdot.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/dynbuf.c b/Utilities/cmcurl/lib/dynbuf.c
index 38d370b07..ada7e0ccf 100644
--- a/Utilities/cmcurl/lib/dynbuf.c
+++ b/Utilities/cmcurl/lib/dynbuf.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -21,12 +21,11 @@
***************************************************************************/
#include "curl_setup.h"
-#include "strdup.h"
#include "dynbuf.h"
-
-/* The last 3 #include files should be in this order */
#include "curl_printf.h"
+#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
+#endif
#include "memdebug.h"
#define MIN_FIRST_ALLOC 32
@@ -94,11 +93,15 @@ static CURLcode dyn_nappend(struct dynbuf *s,
}
if(a != s->allc) {
- s->bufr = Curl_saferealloc(s->bufr, a);
- if(!s->bufr) {
+ /* this logic is not using Curl_saferealloc() to make the tool not have to
+ include that as well when it uses this code */
+ void *p = realloc(s->bufr, a);
+ if(!p) {
+ Curl_safefree(s->bufr);
s->leng = s->allc = 0;
return CURLE_OUT_OF_MEMORY;
}
+ s->bufr = p;
s->allc = a;
}
@@ -143,6 +146,7 @@ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
else {
memmove(&s->bufr[0], &s->bufr[s->leng - trail], trail);
s->leng = trail;
+ s->bufr[s->leng] = 0;
}
return CURLE_OK;
@@ -173,15 +177,22 @@ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
}
/*
- * Append a string printf()-style
+ * Append a string vprintf()-style
*/
-CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
{
+#ifdef BUILDING_LIBCURL
+ int rc;
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ rc = Curl_dyn_vprintf(s, fmt, ap);
+
+ if(!rc)
+ return CURLE_OK;
+#else
char *str;
- va_list ap;
- va_start(ap, fmt);
str = vaprintf(fmt, ap); /* this allocs a new string to append */
- va_end(ap);
if(str) {
CURLcode result = dyn_nappend(s, (unsigned char *)str, strlen(str));
@@ -190,10 +201,27 @@ CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
}
/* If we failed, we cleanup the whole buffer and return error */
Curl_dyn_free(s);
+#endif
return CURLE_OUT_OF_MEMORY;
}
/*
+ * Append a string printf()-style
+ */
+CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+{
+ CURLcode result;
+ va_list ap;
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ va_start(ap, fmt);
+ result = Curl_dyn_vaddf(s, fmt, ap);
+ va_end(ap);
+ return result;
+}
+
+/*
* Returns a pointer to the buffer.
*/
char *Curl_dyn_ptr(const struct dynbuf *s)
diff --git a/Utilities/cmcurl/lib/dynbuf.h b/Utilities/cmcurl/lib/dynbuf.h
index ecc995755..484e40c64 100644
--- a/Utilities/cmcurl/lib/dynbuf.h
+++ b/Utilities/cmcurl/lib/dynbuf.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -22,6 +22,23 @@
*
***************************************************************************/
+#ifndef BUILDING_LIBCURL
+/* this renames the functions so that the tool code can use the same code
+ without getting symbol collisions */
+#define Curl_dyn_init(a,b) curlx_dyn_init(a,b)
+#define Curl_dyn_add(a,b) curlx_dyn_add(a,b)
+#define Curl_dyn_addn(a,b,c) curlx_dyn_addn(a,b,c)
+#define Curl_dyn_addf curlx_dyn_addf
+#define Curl_dyn_vaddf curlx_dyn_vaddf
+#define Curl_dyn_free(a) curlx_dyn_free(a)
+#define Curl_dyn_ptr(a) curlx_dyn_ptr(a)
+#define Curl_dyn_uptr(a) curlx_dyn_uptr(a)
+#define Curl_dyn_len(a) curlx_dyn_len(a)
+#define Curl_dyn_reset(a) curlx_dyn_reset(a)
+#define Curl_dyn_tail(a,b) curlx_dyn_tail(a,b)
+#define curlx_dynbuf dynbuf /* for the struct name */
+#endif
+
struct dynbuf {
char *bufr; /* point to a null-terminated allocated buffer */
size_t leng; /* number of bytes *EXCLUDING* the zero terminator */
@@ -40,12 +57,18 @@ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
WARN_UNUSED_RESULT;
CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
WARN_UNUSED_RESULT;
+CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
+ WARN_UNUSED_RESULT;
void Curl_dyn_reset(struct dynbuf *s);
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
char *Curl_dyn_ptr(const struct dynbuf *s);
unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
size_t Curl_dyn_len(const struct dynbuf *s);
+/* returns 0 on success, -1 on error */
+/* The implementation of this function exists in mprintf.c */
+int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
+
/* Dynamic buffer max sizes */
#define DYN_DOH_RESPONSE 3000
#define DYN_DOH_CNAME 256
@@ -60,4 +83,6 @@ size_t Curl_dyn_len(const struct dynbuf *s);
#define DYN_PROXY_CONNECT_HEADERS 16384
#define DYN_QLOG_NAME 1024
#define DYN_H1_TRAILER 4096
+#define DYN_PINGPPONG_CMD (64*1024)
+#define DYN_IMAP_CMD (64*1024)
#endif
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index a69eb9e56..0fb255af4 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -78,6 +78,8 @@
#include "system_win32.h"
#include "http2.h"
#include "dynbuf.h"
+#include "altsvc.h"
+#include "hsts.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -105,7 +107,6 @@ static long init_flags;
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
#endif
-#ifndef __SYMBIAN32__
/*
* If a memory-using function (like curl_getenv) is used before
* curl_global_init() is called, we need to have these pointers set already.
@@ -118,22 +119,15 @@ curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
#if defined(WIN32) && defined(UNICODE)
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif
-#else
-/*
- * Symbian OS doesn't support initialization to code in writable static data.
- * Initialization will occur in the curl_global_init() call.
- */
-curl_malloc_callback Curl_cmalloc;
-curl_free_callback Curl_cfree;
-curl_realloc_callback Curl_crealloc;
-curl_strdup_callback Curl_cstrdup;
-curl_calloc_callback Curl_ccalloc;
-#endif
#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
# pragma warning(default:4232) /* MSVC extension, dllimport identity */
#endif
+#ifdef DEBUGBUILD
+static char *leakpointer;
+#endif
+
/**
* curl_global_init() globally initializes curl given a bitwise set of the
* different features of what to initialize.
@@ -200,6 +194,12 @@ static CURLcode global_init(long flags, bool memoryfuncs)
init_flags = flags;
+#ifdef DEBUGBUILD
+ if(getenv("CURL_GLOBAL_INIT"))
+ /* alloc data that will leak if *cleanup() is not called! */
+ leakpointer = malloc(1);
+#endif
+
return CURLE_OK;
fail:
@@ -275,6 +275,9 @@ void curl_global_cleanup(void)
#ifdef USE_WOLFSSH
(void)wolfSSH_Cleanup();
#endif
+#ifdef DEBUGBUILD
+ free(leakpointer);
+#endif
init_flags = 0;
}
@@ -883,10 +886,30 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
goto fail;
}
+#ifdef USE_ALTSVC
+ if(data->asi) {
+ outcurl->asi = Curl_altsvc_init();
+ if(!outcurl->asi)
+ goto fail;
+ if(outcurl->set.str[STRING_ALTSVC])
+ (void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]);
+ }
+#endif
+#ifdef USE_HSTS
+ if(data->hsts) {
+ outcurl->hsts = Curl_hsts_init();
+ if(!outcurl->hsts)
+ goto fail;
+ if(outcurl->set.str[STRING_HSTS])
+ (void)Curl_hsts_loadfile(outcurl,
+ outcurl->hsts, outcurl->set.str[STRING_HSTS]);
+ (void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
+ }
+#endif
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(outcurl,
- &outcurl->state.resolver,
- data->state.resolver))
+ &outcurl->state.async.resolver,
+ data->state.async.resolver))
goto fail;
#ifdef USE_ARES
@@ -930,6 +953,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
Curl_dyn_free(&outcurl->state.headerb);
Curl_safefree(outcurl->change.url);
Curl_safefree(outcurl->change.referer);
+ Curl_altsvc_cleanup(&outcurl->asi);
+ Curl_hsts_cleanup(&outcurl->hsts);
Curl_freeset(outcurl);
free(outcurl);
}
@@ -958,6 +983,7 @@ void curl_easy_reset(struct Curl_easy *data)
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
+ data->state.retrycount = 0; /* reset the retry counter */
/* zero out authentication data: */
memset(&data->state.authhost, 0, sizeof(struct auth));
@@ -1046,7 +1072,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* even if one function returns error, this loops through and frees
all buffers */
if(!result)
- result = Curl_client_write(conn, writebuf[i].type,
+ result = Curl_client_write(data, writebuf[i].type,
Curl_dyn_ptr(&writebuf[i].b),
Curl_dyn_len(&writebuf[i].b));
Curl_dyn_free(&writebuf[i].b);
@@ -1067,9 +1093,13 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
- /* force a recv/send check of this connection, as the data might've been
- read off the socket already */
- data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
+ /* reset the too-slow time keeper */
+ data->state.keeps_speed.tv_sec = 0;
+
+ if(!data->state.tempcount)
+ /* if not pausing again, force a recv/send check of this connection as
+ the data might've been read off the socket already */
+ data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
if(data->multi)
Curl_update_timer(data->multi);
}
@@ -1126,8 +1156,13 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
if(result)
return result;
+ if(!data->conn)
+ /* on first invoke, the transfer has been detached from the connection and
+ needs to be reattached */
+ Curl_attach_connnection(data, c);
+
*n = 0;
- result = Curl_read(c, sfd, buffer, buflen, &n1);
+ result = Curl_read(data, sfd, buffer, buflen, &n1);
if(result)
return result;
@@ -1156,8 +1191,13 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
if(result)
return result;
+ if(!data->conn)
+ /* on first invoke, the transfer has been detached from the connection and
+ needs to be reattached */
+ Curl_attach_connnection(data, c);
+
*n = 0;
- result = Curl_write(c, sfd, buffer, buflen, &n1);
+ result = Curl_write(data, sfd, buffer, buflen, &n1);
if(n1 == -1)
return CURLE_SEND_ERROR;
@@ -1176,16 +1216,16 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
*
* Returns always 0.
*/
-static int conn_upkeep(struct connectdata *conn,
+static int conn_upkeep(struct Curl_easy *data,
+ struct connectdata *conn,
void *param)
{
/* Param is unused. */
(void)param;
- if(conn->handler->connection_check) {
+ if(conn->handler->connection_check)
/* Do a protocol-specific keepalive check on the connection. */
- conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
- }
+ conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
return 0; /* continue iteration */
}
diff --git a/Utilities/cmcurl/lib/easygetopt.c b/Utilities/cmcurl/lib/easygetopt.c
new file mode 100644
index 000000000..7b2213fb2
--- /dev/null
+++ b/Utilities/cmcurl/lib/easygetopt.c
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ | |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * ___|___/|_| ______|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * 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 "strcase.h"
+#include "easyoptions.h"
+
+#ifndef CURL_DISABLE_GETOPTIONS
+
+/* Lookups easy options at runtime */
+static struct curl_easyoption *lookup(const char *name, CURLoption id)
+{
+ DEBUGASSERT(name || id);
+ DEBUGASSERT(!Curl_easyopts_check());
+ if(name || id) {
+ struct curl_easyoption *o = &Curl_easyopts[0];
+ do {
+ if(name) {
+ if(strcasecompare(o->name, name))
+ return o;
+ }
+ else {
+ if((o->id == id) && !(o->flags & CURLOT_FLAG_ALIAS))
+ /* don't match alias options */
+ return o;
+ }
+ o++;
+ } while(o->name);
+ }
+ return NULL;
+}
+
+const struct curl_easyoption *curl_easy_option_by_name(const char *name)
+{
+ /* when name is used, the id argument is ignored */
+ return lookup(name, CURLOPT_LASTENTRY);
+}
+
+const struct curl_easyoption *curl_easy_option_by_id(CURLoption id)
+{
+ return lookup(NULL, id);
+}
+
+/* Iterates over available options */
+const struct curl_easyoption *
+curl_easy_option_next(const struct curl_easyoption *prev)
+{
+ if(prev && prev->name) {
+ prev++;
+ if(prev->name)
+ return prev;
+ }
+ else if(!prev)
+ return &Curl_easyopts[0];
+ return NULL;
+}
+
+#else
+const struct curl_easyoption *curl_easy_option_by_name(const char *name)
+{
+ (void)name;
+ return NULL;
+}
+
+const struct curl_easyoption *curl_easy_option_by_id (CURLoption id)
+{
+ (void)id;
+ return NULL;
+}
+
+const struct curl_easyoption *
+curl_easy_option_next(const struct curl_easyoption *prev)
+{
+ (void)prev;
+ return NULL;
+}
+#endif
diff --git a/Utilities/cmcurl/lib/easyif.h b/Utilities/cmcurl/lib/easyif.h
index eda0d62e5..336441828 100644
--- a/Utilities/cmcurl/lib/easyif.h
+++ b/Utilities/cmcurl/lib/easyif.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/easyoptions.c b/Utilities/cmcurl/lib/easyoptions.c
new file mode 100644
index 000000000..b54829ba3
--- /dev/null
+++ b/Utilities/cmcurl/lib/easyoptions.c
@@ -0,0 +1,354 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ | |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * ___|___/|_| ______|
+ *
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * 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.
+ *
+ ***************************************************************************/
+
+/* This source code is generated by optiontable.pl - DO NOT EDIT BY HAND */
+
+#include "curl_setup.h"
+#include "easyoptions.h"
+
+/* all easy setopt options listed in alphabetical order */
+struct curl_easyoption Curl_easyopts[] = {
+ {"ABSTRACT_UNIX_SOCKET", CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOT_STRING, 0},
+ {"ACCEPTTIMEOUT_MS", CURLOPT_ACCEPTTIMEOUT_MS, CURLOT_LONG, 0},
+ {"ACCEPT_ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, 0},
+ {"ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE, CURLOT_LONG, 0},
+ {"ALTSVC", CURLOPT_ALTSVC, CURLOT_STRING, 0},
+ {"ALTSVC_CTRL", CURLOPT_ALTSVC_CTRL, CURLOT_LONG, 0},
+ {"APPEND", CURLOPT_APPEND, CURLOT_LONG, 0},
+ {"AUTOREFERER", CURLOPT_AUTOREFERER, CURLOT_LONG, 0},
+ {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0},
+ {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0},
+ {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0},
+ {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0},
+ {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0},
+ {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0},
+ {"CHUNK_DATA", CURLOPT_CHUNK_DATA, CURLOT_CBPTR, 0},
+ {"CHUNK_END_FUNCTION", CURLOPT_CHUNK_END_FUNCTION, CURLOT_FUNCTION, 0},
+ {"CLOSESOCKETDATA", CURLOPT_CLOSESOCKETDATA, CURLOT_CBPTR, 0},
+ {"CLOSESOCKETFUNCTION", CURLOPT_CLOSESOCKETFUNCTION, CURLOT_FUNCTION, 0},
+ {"CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT, CURLOT_LONG, 0},
+ {"CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS, CURLOT_LONG, 0},
+ {"CONNECT_ONLY", CURLOPT_CONNECT_ONLY, CURLOT_LONG, 0},
+ {"CONNECT_TO", CURLOPT_CONNECT_TO, CURLOT_SLIST, 0},
+ {"CONV_FROM_NETWORK_FUNCTION", CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"CONV_FROM_UTF8_FUNCTION", CURLOPT_CONV_FROM_UTF8_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"CONV_TO_NETWORK_FUNCTION", CURLOPT_CONV_TO_NETWORK_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"COOKIE", CURLOPT_COOKIE, CURLOT_STRING, 0},
+ {"COOKIEFILE", CURLOPT_COOKIEFILE, CURLOT_STRING, 0},
+ {"COOKIEJAR", CURLOPT_COOKIEJAR, CURLOT_STRING, 0},
+ {"COOKIELIST", CURLOPT_COOKIELIST, CURLOT_STRING, 0},
+ {"COOKIESESSION", CURLOPT_COOKIESESSION, CURLOT_LONG, 0},
+ {"COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS, CURLOT_OBJECT, 0},
+ {"CRLF", CURLOPT_CRLF, CURLOT_LONG, 0},
+ {"CRLFILE", CURLOPT_CRLFILE, CURLOT_STRING, 0},
+ {"CURLU", CURLOPT_CURLU, CURLOT_OBJECT, 0},
+ {"CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST, CURLOT_STRING, 0},
+ {"DEBUGDATA", CURLOPT_DEBUGDATA, CURLOT_CBPTR, 0},
+ {"DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION, CURLOT_FUNCTION, 0},
+ {"DEFAULT_PROTOCOL", CURLOPT_DEFAULT_PROTOCOL, CURLOT_STRING, 0},
+ {"DIRLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, 0},
+ {"DISALLOW_USERNAME_IN_URL", CURLOPT_DISALLOW_USERNAME_IN_URL,
+ CURLOT_LONG, 0},
+ {"DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT, CURLOT_LONG, 0},
+ {"DNS_INTERFACE", CURLOPT_DNS_INTERFACE, CURLOT_STRING, 0},
+ {"DNS_LOCAL_IP4", CURLOPT_DNS_LOCAL_IP4, CURLOT_STRING, 0},
+ {"DNS_LOCAL_IP6", CURLOPT_DNS_LOCAL_IP6, CURLOT_STRING, 0},
+ {"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_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0},
+ {"EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0},
+ {"ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"ERRORBUFFER", CURLOPT_ERRORBUFFER, CURLOT_OBJECT, 0},
+ {"EXPECT_100_TIMEOUT_MS", CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOT_LONG, 0},
+ {"FAILONERROR", CURLOPT_FAILONERROR, CURLOT_LONG, 0},
+ {"FILE", CURLOPT_WRITEDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"FILETIME", CURLOPT_FILETIME, CURLOT_LONG, 0},
+ {"FNMATCH_DATA", CURLOPT_FNMATCH_DATA, CURLOT_CBPTR, 0},
+ {"FNMATCH_FUNCTION", CURLOPT_FNMATCH_FUNCTION, CURLOT_FUNCTION, 0},
+ {"FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION, CURLOT_LONG, 0},
+ {"FORBID_REUSE", CURLOPT_FORBID_REUSE, CURLOT_LONG, 0},
+ {"FRESH_CONNECT", CURLOPT_FRESH_CONNECT, CURLOT_LONG, 0},
+ {"FTPAPPEND", CURLOPT_APPEND, CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"FTPLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"FTPPORT", CURLOPT_FTPPORT, CURLOT_STRING, 0},
+ {"FTPSSLAUTH", CURLOPT_FTPSSLAUTH, CURLOT_VALUES, 0},
+ {"FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT, CURLOT_STRING, 0},
+ {"FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER,
+ CURLOT_STRING, 0},
+ {"FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS,
+ CURLOT_LONG, 0},
+ {"FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD, CURLOT_VALUES, 0},
+ {"FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOT_LONG, 0},
+ {"FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP, CURLOT_LONG, 0},
+ {"FTP_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, CURLOT_FLAG_ALIAS},
+ {"FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC, CURLOT_LONG, 0},
+ {"FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT, CURLOT_LONG, 0},
+ {"FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV, CURLOT_LONG, 0},
+ {"FTP_USE_PRET", CURLOPT_FTP_USE_PRET, CURLOT_LONG, 0},
+ {"GSSAPI_DELEGATION", CURLOPT_GSSAPI_DELEGATION, CURLOT_VALUES, 0},
+ {"HAPPY_EYEBALLS_TIMEOUT_MS", CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
+ CURLOT_LONG, 0},
+ {"HAPROXYPROTOCOL", CURLOPT_HAPROXYPROTOCOL, CURLOT_LONG, 0},
+ {"HEADER", CURLOPT_HEADER, CURLOT_LONG, 0},
+ {"HEADERDATA", CURLOPT_HEADERDATA, CURLOT_CBPTR, 0},
+ {"HEADERFUNCTION", CURLOPT_HEADERFUNCTION, CURLOT_FUNCTION, 0},
+ {"HEADEROPT", CURLOPT_HEADEROPT, CURLOT_VALUES, 0},
+ {"HSTS", CURLOPT_HSTS, CURLOT_STRING, 0},
+ {"HSTSREADDATA", CURLOPT_HSTSREADDATA, CURLOT_CBPTR, 0},
+ {"HSTSREADFUNCTION", CURLOPT_HSTSREADFUNCTION, CURLOT_FUNCTION, 0},
+ {"HSTSWRITEDATA", CURLOPT_HSTSWRITEDATA, CURLOT_CBPTR, 0},
+ {"HSTSWRITEFUNCTION", CURLOPT_HSTSWRITEFUNCTION, CURLOT_FUNCTION, 0},
+ {"HSTS_CTRL", CURLOPT_HSTS_CTRL, CURLOT_LONG, 0},
+ {"HTTP09_ALLOWED", CURLOPT_HTTP09_ALLOWED, CURLOT_LONG, 0},
+ {"HTTP200ALIASES", CURLOPT_HTTP200ALIASES, CURLOT_SLIST, 0},
+ {"HTTPAUTH", CURLOPT_HTTPAUTH, CURLOT_VALUES, 0},
+ {"HTTPGET", CURLOPT_HTTPGET, CURLOT_LONG, 0},
+ {"HTTPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, 0},
+ {"HTTPPOST", CURLOPT_HTTPPOST, CURLOT_OBJECT, 0},
+ {"HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL, CURLOT_LONG, 0},
+ {"HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING, CURLOT_LONG, 0},
+ {"HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING, CURLOT_LONG, 0},
+ {"HTTP_VERSION", CURLOPT_HTTP_VERSION, CURLOT_VALUES, 0},
+ {"IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH, CURLOT_LONG, 0},
+ {"INFILE", CURLOPT_READDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"INFILESIZE", CURLOPT_INFILESIZE, CURLOT_LONG, 0},
+ {"INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE, CURLOT_OFF_T, 0},
+ {"INTERFACE", CURLOPT_INTERFACE, CURLOT_STRING, 0},
+ {"INTERLEAVEDATA", CURLOPT_INTERLEAVEDATA, CURLOT_CBPTR, 0},
+ {"INTERLEAVEFUNCTION", CURLOPT_INTERLEAVEFUNCTION, CURLOT_FUNCTION, 0},
+ {"IOCTLDATA", CURLOPT_IOCTLDATA, CURLOT_CBPTR, 0},
+ {"IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION, CURLOT_FUNCTION, 0},
+ {"IPRESOLVE", CURLOPT_IPRESOLVE, CURLOT_VALUES, 0},
+ {"ISSUERCERT", CURLOPT_ISSUERCERT, CURLOT_STRING, 0},
+ {"ISSUERCERT_BLOB", CURLOPT_ISSUERCERT_BLOB, CURLOT_BLOB, 0},
+ {"KEEP_SENDING_ON_ERROR", CURLOPT_KEEP_SENDING_ON_ERROR, CURLOT_LONG, 0},
+ {"KEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, 0},
+ {"KRB4LEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"KRBLEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, 0},
+ {"LOCALPORT", CURLOPT_LOCALPORT, CURLOT_LONG, 0},
+ {"LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE, CURLOT_LONG, 0},
+ {"LOGIN_OPTIONS", CURLOPT_LOGIN_OPTIONS, CURLOT_STRING, 0},
+ {"LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT, CURLOT_LONG, 0},
+ {"LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME, CURLOT_LONG, 0},
+ {"MAIL_AUTH", CURLOPT_MAIL_AUTH, CURLOT_STRING, 0},
+ {"MAIL_FROM", CURLOPT_MAIL_FROM, CURLOT_STRING, 0},
+ {"MAIL_RCPT", CURLOPT_MAIL_RCPT, CURLOT_SLIST, 0},
+ {"MAIL_RCPT_ALLLOWFAILS", CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOT_LONG, 0},
+ {"MAXAGE_CONN", CURLOPT_MAXAGE_CONN, CURLOT_LONG, 0},
+ {"MAXCONNECTS", CURLOPT_MAXCONNECTS, CURLOT_LONG, 0},
+ {"MAXFILESIZE", CURLOPT_MAXFILESIZE, CURLOT_LONG, 0},
+ {"MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE, CURLOT_OFF_T, 0},
+ {"MAXREDIRS", CURLOPT_MAXREDIRS, CURLOT_LONG, 0},
+ {"MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE, CURLOT_OFF_T, 0},
+ {"MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE, CURLOT_OFF_T, 0},
+ {"MIMEPOST", CURLOPT_MIMEPOST, CURLOT_OBJECT, 0},
+ {"NETRC", CURLOPT_NETRC, CURLOT_VALUES, 0},
+ {"NETRC_FILE", CURLOPT_NETRC_FILE, CURLOT_STRING, 0},
+ {"NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS, CURLOT_LONG, 0},
+ {"NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS, CURLOT_LONG, 0},
+ {"NOBODY", CURLOPT_NOBODY, CURLOT_LONG, 0},
+ {"NOPROGRESS", CURLOPT_NOPROGRESS, CURLOT_LONG, 0},
+ {"NOPROXY", CURLOPT_NOPROXY, CURLOT_STRING, 0},
+ {"NOSIGNAL", CURLOPT_NOSIGNAL, CURLOT_LONG, 0},
+ {"OPENSOCKETDATA", CURLOPT_OPENSOCKETDATA, CURLOT_CBPTR, 0},
+ {"OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION, CURLOT_FUNCTION, 0},
+ {"PASSWORD", CURLOPT_PASSWORD, CURLOT_STRING, 0},
+ {"PATH_AS_IS", CURLOPT_PATH_AS_IS, CURLOT_LONG, 0},
+ {"PINNEDPUBLICKEY", CURLOPT_PINNEDPUBLICKEY, CURLOT_STRING, 0},
+ {"PIPEWAIT", CURLOPT_PIPEWAIT, CURLOT_LONG, 0},
+ {"PORT", CURLOPT_PORT, CURLOT_LONG, 0},
+ {"POST", CURLOPT_POST, CURLOT_LONG, 0},
+ {"POST301", CURLOPT_POSTREDIR, CURLOT_VALUES, CURLOT_FLAG_ALIAS},
+ {"POSTFIELDS", CURLOPT_POSTFIELDS, CURLOT_OBJECT, 0},
+ {"POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE, CURLOT_LONG, 0},
+ {"POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE, CURLOT_OFF_T, 0},
+ {"POSTQUOTE", CURLOPT_POSTQUOTE, CURLOT_SLIST, 0},
+ {"POSTREDIR", CURLOPT_POSTREDIR, CURLOT_VALUES, 0},
+ {"PREQUOTE", CURLOPT_PREQUOTE, CURLOT_SLIST, 0},
+ {"PRE_PROXY", CURLOPT_PRE_PROXY, CURLOT_STRING, 0},
+ {"PRIVATE", CURLOPT_PRIVATE, CURLOT_OBJECT, 0},
+ {"PROGRESSDATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION, CURLOT_FUNCTION, 0},
+ {"PROTOCOLS", CURLOPT_PROTOCOLS, CURLOT_LONG, 0},
+ {"PROXY", CURLOPT_PROXY, CURLOT_STRING, 0},
+ {"PROXYAUTH", CURLOPT_PROXYAUTH, CURLOT_VALUES, 0},
+ {"PROXYHEADER", CURLOPT_PROXYHEADER, CURLOT_SLIST, 0},
+ {"PROXYPASSWORD", CURLOPT_PROXYPASSWORD, CURLOT_STRING, 0},
+ {"PROXYPORT", CURLOPT_PROXYPORT, CURLOT_LONG, 0},
+ {"PROXYTYPE", CURLOPT_PROXYTYPE, CURLOT_VALUES, 0},
+ {"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0},
+ {"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0},
+ {"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 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},
+ {"PROXY_ISSUERCERT_BLOB", CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOT_BLOB, 0},
+ {"PROXY_KEYPASSWD", CURLOPT_PROXY_KEYPASSWD, CURLOT_STRING, 0},
+ {"PROXY_PINNEDPUBLICKEY", CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOT_STRING, 0},
+ {"PROXY_SERVICE_NAME", CURLOPT_PROXY_SERVICE_NAME, CURLOT_STRING, 0},
+ {"PROXY_SSLCERT", CURLOPT_PROXY_SSLCERT, CURLOT_STRING, 0},
+ {"PROXY_SSLCERTTYPE", CURLOPT_PROXY_SSLCERTTYPE, CURLOT_STRING, 0},
+ {"PROXY_SSLCERT_BLOB", CURLOPT_PROXY_SSLCERT_BLOB, CURLOT_BLOB, 0},
+ {"PROXY_SSLKEY", CURLOPT_PROXY_SSLKEY, CURLOT_STRING, 0},
+ {"PROXY_SSLKEYTYPE", CURLOPT_PROXY_SSLKEYTYPE, CURLOT_STRING, 0},
+ {"PROXY_SSLKEY_BLOB", CURLOPT_PROXY_SSLKEY_BLOB, CURLOT_BLOB, 0},
+ {"PROXY_SSLVERSION", CURLOPT_PROXY_SSLVERSION, CURLOT_VALUES, 0},
+ {"PROXY_SSL_CIPHER_LIST", CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOT_STRING, 0},
+ {"PROXY_SSL_OPTIONS", CURLOPT_PROXY_SSL_OPTIONS, CURLOT_LONG, 0},
+ {"PROXY_SSL_VERIFYHOST", CURLOPT_PROXY_SSL_VERIFYHOST, CURLOT_LONG, 0},
+ {"PROXY_SSL_VERIFYPEER", CURLOPT_PROXY_SSL_VERIFYPEER, CURLOT_LONG, 0},
+ {"PROXY_TLS13_CIPHERS", CURLOPT_PROXY_TLS13_CIPHERS, CURLOT_STRING, 0},
+ {"PROXY_TLSAUTH_PASSWORD", CURLOPT_PROXY_TLSAUTH_PASSWORD,
+ CURLOT_STRING, 0},
+ {"PROXY_TLSAUTH_TYPE", CURLOPT_PROXY_TLSAUTH_TYPE, CURLOT_STRING, 0},
+ {"PROXY_TLSAUTH_USERNAME", CURLOPT_PROXY_TLSAUTH_USERNAME,
+ CURLOT_STRING, 0},
+ {"PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE, CURLOT_LONG, 0},
+ {"PUT", CURLOPT_PUT, CURLOT_LONG, 0},
+ {"QUOTE", CURLOPT_QUOTE, CURLOT_SLIST, 0},
+ {"RANDOM_FILE", CURLOPT_RANDOM_FILE, CURLOT_STRING, 0},
+ {"RANGE", CURLOPT_RANGE, CURLOT_STRING, 0},
+ {"READDATA", CURLOPT_READDATA, CURLOT_CBPTR, 0},
+ {"READFUNCTION", CURLOPT_READFUNCTION, CURLOT_FUNCTION, 0},
+ {"REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS, CURLOT_LONG, 0},
+ {"REFERER", CURLOPT_REFERER, CURLOT_STRING, 0},
+ {"REQUEST_TARGET", CURLOPT_REQUEST_TARGET, CURLOT_STRING, 0},
+ {"RESOLVE", CURLOPT_RESOLVE, CURLOT_SLIST, 0},
+ {"RESOLVER_START_DATA", CURLOPT_RESOLVER_START_DATA, CURLOT_CBPTR, 0},
+ {"RESOLVER_START_FUNCTION", CURLOPT_RESOLVER_START_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"RESUME_FROM", CURLOPT_RESUME_FROM, CURLOT_LONG, 0},
+ {"RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE, CURLOT_OFF_T, 0},
+ {"RTSPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, CURLOT_FLAG_ALIAS},
+ {"RTSP_CLIENT_CSEQ", CURLOPT_RTSP_CLIENT_CSEQ, CURLOT_LONG, 0},
+ {"RTSP_REQUEST", CURLOPT_RTSP_REQUEST, CURLOT_VALUES, 0},
+ {"RTSP_SERVER_CSEQ", CURLOPT_RTSP_SERVER_CSEQ, CURLOT_LONG, 0},
+ {"RTSP_SESSION_ID", CURLOPT_RTSP_SESSION_ID, CURLOT_STRING, 0},
+ {"RTSP_STREAM_URI", CURLOPT_RTSP_STREAM_URI, CURLOT_STRING, 0},
+ {"RTSP_TRANSPORT", CURLOPT_RTSP_TRANSPORT, CURLOT_STRING, 0},
+ {"SASL_AUTHZID", CURLOPT_SASL_AUTHZID, CURLOT_STRING, 0},
+ {"SASL_IR", CURLOPT_SASL_IR, CURLOT_LONG, 0},
+ {"SEEKDATA", CURLOPT_SEEKDATA, CURLOT_CBPTR, 0},
+ {"SEEKFUNCTION", CURLOPT_SEEKFUNCTION, CURLOT_FUNCTION, 0},
+ {"SERVER_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT,
+ CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"SERVICE_NAME", CURLOPT_SERVICE_NAME, CURLOT_STRING, 0},
+ {"SHARE", CURLOPT_SHARE, CURLOT_OBJECT, 0},
+ {"SOCKOPTDATA", CURLOPT_SOCKOPTDATA, CURLOT_CBPTR, 0},
+ {"SOCKOPTFUNCTION", CURLOPT_SOCKOPTFUNCTION, CURLOT_FUNCTION, 0},
+ {"SOCKS5_AUTH", CURLOPT_SOCKS5_AUTH, CURLOT_LONG, 0},
+ {"SOCKS5_GSSAPI_NEC", CURLOPT_SOCKS5_GSSAPI_NEC, CURLOT_LONG, 0},
+ {"SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOT_STRING, 0},
+ {"SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES, CURLOT_VALUES, 0},
+ {"SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0},
+ {"SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
+ CURLOT_STRING, 0},
+ {"SSH_KEYDATA", CURLOPT_SSH_KEYDATA, CURLOT_CBPTR, 0},
+ {"SSH_KEYFUNCTION", CURLOPT_SSH_KEYFUNCTION, CURLOT_FUNCTION, 0},
+ {"SSH_KNOWNHOSTS", CURLOPT_SSH_KNOWNHOSTS, CURLOT_STRING, 0},
+ {"SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE, CURLOT_STRING, 0},
+ {"SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE, CURLOT_STRING, 0},
+ {"SSLCERT", CURLOPT_SSLCERT, CURLOT_STRING, 0},
+ {"SSLCERTPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"SSLCERTTYPE", CURLOPT_SSLCERTTYPE, CURLOT_STRING, 0},
+ {"SSLCERT_BLOB", CURLOPT_SSLCERT_BLOB, CURLOT_BLOB, 0},
+ {"SSLENGINE", CURLOPT_SSLENGINE, CURLOT_STRING, 0},
+ {"SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT, CURLOT_LONG, 0},
+ {"SSLKEY", CURLOPT_SSLKEY, CURLOT_STRING, 0},
+ {"SSLKEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"SSLKEYTYPE", CURLOPT_SSLKEYTYPE, CURLOT_STRING, 0},
+ {"SSLKEY_BLOB", CURLOPT_SSLKEY_BLOB, CURLOT_BLOB, 0},
+ {"SSLVERSION", CURLOPT_SSLVERSION, CURLOT_VALUES, 0},
+ {"SSL_CIPHER_LIST", CURLOPT_SSL_CIPHER_LIST, CURLOT_STRING, 0},
+ {"SSL_CTX_DATA", CURLOPT_SSL_CTX_DATA, CURLOT_CBPTR, 0},
+ {"SSL_CTX_FUNCTION", CURLOPT_SSL_CTX_FUNCTION, CURLOT_FUNCTION, 0},
+ {"SSL_EC_CURVES", CURLOPT_SSL_EC_CURVES, CURLOT_STRING, 0},
+ {"SSL_ENABLE_ALPN", CURLOPT_SSL_ENABLE_ALPN, CURLOT_LONG, 0},
+ {"SSL_ENABLE_NPN", CURLOPT_SSL_ENABLE_NPN, CURLOT_LONG, 0},
+ {"SSL_FALSESTART", CURLOPT_SSL_FALSESTART, CURLOT_LONG, 0},
+ {"SSL_OPTIONS", CURLOPT_SSL_OPTIONS, CURLOT_VALUES, 0},
+ {"SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE, CURLOT_LONG, 0},
+ {"SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST, CURLOT_LONG, 0},
+ {"SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER, CURLOT_LONG, 0},
+ {"SSL_VERIFYSTATUS", CURLOPT_SSL_VERIFYSTATUS, CURLOT_LONG, 0},
+ {"STDERR", CURLOPT_STDERR, CURLOT_OBJECT, 0},
+ {"STREAM_DEPENDS", CURLOPT_STREAM_DEPENDS, CURLOT_OBJECT, 0},
+ {"STREAM_DEPENDS_E", CURLOPT_STREAM_DEPENDS_E, CURLOT_OBJECT, 0},
+ {"STREAM_WEIGHT", CURLOPT_STREAM_WEIGHT, CURLOT_LONG, 0},
+ {"SUPPRESS_CONNECT_HEADERS", CURLOPT_SUPPRESS_CONNECT_HEADERS,
+ CURLOT_LONG, 0},
+ {"TCP_FASTOPEN", CURLOPT_TCP_FASTOPEN, CURLOT_LONG, 0},
+ {"TCP_KEEPALIVE", CURLOPT_TCP_KEEPALIVE, CURLOT_LONG, 0},
+ {"TCP_KEEPIDLE", CURLOPT_TCP_KEEPIDLE, CURLOT_LONG, 0},
+ {"TCP_KEEPINTVL", CURLOPT_TCP_KEEPINTVL, CURLOT_LONG, 0},
+ {"TCP_NODELAY", CURLOPT_TCP_NODELAY, CURLOT_LONG, 0},
+ {"TELNETOPTIONS", CURLOPT_TELNETOPTIONS, CURLOT_SLIST, 0},
+ {"TFTP_BLKSIZE", CURLOPT_TFTP_BLKSIZE, CURLOT_LONG, 0},
+ {"TFTP_NO_OPTIONS", CURLOPT_TFTP_NO_OPTIONS, CURLOT_LONG, 0},
+ {"TIMECONDITION", CURLOPT_TIMECONDITION, CURLOT_VALUES, 0},
+ {"TIMEOUT", CURLOPT_TIMEOUT, CURLOT_LONG, 0},
+ {"TIMEOUT_MS", CURLOPT_TIMEOUT_MS, CURLOT_LONG, 0},
+ {"TIMEVALUE", CURLOPT_TIMEVALUE, CURLOT_LONG, 0},
+ {"TIMEVALUE_LARGE", CURLOPT_TIMEVALUE_LARGE, CURLOT_OFF_T, 0},
+ {"TLS13_CIPHERS", CURLOPT_TLS13_CIPHERS, CURLOT_STRING, 0},
+ {"TLSAUTH_PASSWORD", CURLOPT_TLSAUTH_PASSWORD, CURLOT_STRING, 0},
+ {"TLSAUTH_TYPE", CURLOPT_TLSAUTH_TYPE, CURLOT_STRING, 0},
+ {"TLSAUTH_USERNAME", CURLOPT_TLSAUTH_USERNAME, CURLOT_STRING, 0},
+ {"TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0},
+ {"TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0},
+ {"TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0},
+ {"TRANSFER_ENCODING", CURLOPT_TRANSFER_ENCODING, CURLOT_LONG, 0},
+ {"UNIX_SOCKET_PATH", CURLOPT_UNIX_SOCKET_PATH, CURLOT_STRING, 0},
+ {"UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH, CURLOT_LONG, 0},
+ {"UPKEEP_INTERVAL_MS", CURLOPT_UPKEEP_INTERVAL_MS, CURLOT_LONG, 0},
+ {"UPLOAD", CURLOPT_UPLOAD, CURLOT_LONG, 0},
+ {"UPLOAD_BUFFERSIZE", CURLOPT_UPLOAD_BUFFERSIZE, CURLOT_LONG, 0},
+ {"URL", CURLOPT_URL, CURLOT_STRING, 0},
+ {"USERAGENT", CURLOPT_USERAGENT, CURLOT_STRING, 0},
+ {"USERNAME", CURLOPT_USERNAME, CURLOT_STRING, 0},
+ {"USERPWD", CURLOPT_USERPWD, CURLOT_STRING, 0},
+ {"USE_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, 0},
+ {"VERBOSE", CURLOPT_VERBOSE, CURLOT_LONG, 0},
+ {"WILDCARDMATCH", CURLOPT_WILDCARDMATCH, CURLOT_LONG, 0},
+ {"WRITEDATA", CURLOPT_WRITEDATA, CURLOT_CBPTR, 0},
+ {"WRITEFUNCTION", CURLOPT_WRITEFUNCTION, CURLOT_FUNCTION, 0},
+ {"WRITEHEADER", CURLOPT_HEADERDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0},
+ {"XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0},
+ {"XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0},
+ {NULL, CURLOPT_LASTENTRY, 0, 0} /* end of table */
+};
+
+#ifdef DEBUGBUILD
+/*
+ * Curl_easyopts_check() is a debug-only function that returns non-zero
+ * if this source file is not in sync with the options listed in curl/curl.h
+ */
+int Curl_easyopts_check(void)
+{
+ return ((CURLOPT_LASTENTRY%10000) != (305 + 1));
+}
+#endif
diff --git a/Utilities/cmcurl/lib/easyoptions.h b/Utilities/cmcurl/lib/easyoptions.h
new file mode 100644
index 000000000..91e11908b
--- /dev/null
+++ b/Utilities/cmcurl/lib/easyoptions.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_EASYOPTIONS_H
+#define HEADER_CURL_EASYOPTIONS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, 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.
+ *
+ ***************************************************************************/
+
+/* should probably go into the public header */
+
+#include <curl/curl.h>
+
+/* generated table with all easy options */
+extern struct curl_easyoption Curl_easyopts[];
+
+#ifdef DEBUGBUILD
+int Curl_easyopts_check(void);
+#endif
+#endif
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index 2bea145f4..683b6fc4a 100644
--- a/Utilities/cmcurl/lib/escape.c
+++ b/Utilities/cmcurl/lib/escape.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -86,7 +86,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
if(inlength < 0)
return NULL;
- Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH);
+ Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH * 3);
length = (inlength?(size_t)inlength:strlen(string));
if(!length)
diff --git a/Utilities/cmcurl/lib/escape.h b/Utilities/cmcurl/lib/escape.h
index 586db7e67..46cb59039 100644
--- a/Utilities/cmcurl/lib/escape.h
+++ b/Utilities/cmcurl/lib/escape.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index cd3e49c33..dd8a1fd12 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -67,8 +67,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \
- defined(__SYMBIAN32__)
+#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
#define DOS_FILESYSTEM 1
#endif
@@ -82,13 +81,15 @@
* Forward declarations.
*/
-static CURLcode file_do(struct connectdata *, bool *done);
-static CURLcode file_done(struct connectdata *conn,
+static CURLcode file_do(struct Curl_easy *data, bool *done);
+static CURLcode file_done(struct Curl_easy *data,
CURLcode status, bool premature);
-static CURLcode file_connect(struct connectdata *conn, bool *done);
-static CURLcode file_disconnect(struct connectdata *conn,
+static CURLcode file_connect(struct Curl_easy *data, bool *done);
+static CURLcode file_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
-static CURLcode file_setup_connection(struct connectdata *conn);
+static CURLcode file_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* FILE scheme handler.
@@ -112,15 +113,18 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* connection_check */
0, /* defport */
CURLPROTO_FILE, /* protocol */
+ CURLPROTO_FILE, /* family */
PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
};
-static CURLcode file_setup_connection(struct connectdata *conn)
+static CURLcode file_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
+ (void)conn;
/* allocate the FILE specific struct */
- conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO));
- if(!conn->data->req.protop)
+ data->req.p.file = calloc(1, sizeof(struct FILEPROTO));
+ if(!data->req.p.file)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -131,11 +135,10 @@ static CURLcode file_setup_connection(struct connectdata *conn)
* do protocol-specific actions at connect-time. We emulate a
* connect-then-transfer protocol and "connect" to the file here
*/
-static CURLcode file_connect(struct connectdata *conn, bool *done)
+static CURLcode file_connect(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
char *real_path;
- struct FILEPROTO *file = data->req.protop;
+ struct FILEPROTO *file = data->req.p.file;
int fd;
#ifdef DOS_FILESYSTEM
size_t i;
@@ -198,7 +201,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
file->fd = fd;
if(!data->set.upload && (fd == -1)) {
failf(data, "Couldn't open file %s", data->state.up.path);
- file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
+ file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE);
return CURLE_FILE_COULDNT_READ_FILE;
}
*done = TRUE;
@@ -206,10 +209,10 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode file_done(struct connectdata *conn,
- CURLcode status, bool premature)
+static CURLcode file_done(struct Curl_easy *data,
+ CURLcode status, bool premature)
{
- struct FILEPROTO *file = conn->data->req.protop;
+ struct FILEPROTO *file = data->req.p.file;
(void)status; /* not used */
(void)premature; /* not used */
@@ -224,21 +227,13 @@ static CURLcode file_done(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode file_disconnect(struct connectdata *conn,
+static CURLcode file_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
- struct FILEPROTO *file = conn->data->req.protop;
(void)dead_connection; /* not used */
-
- if(file) {
- Curl_safefree(file->freepath);
- file->path = NULL;
- if(file->fd != -1)
- close(file->fd);
- file->fd = -1;
- }
-
- return CURLE_OK;
+ (void)conn;
+ return file_done(data, 0, 0);
}
#ifdef DOS_FILESYSTEM
@@ -247,14 +242,13 @@ static CURLcode file_disconnect(struct connectdata *conn,
#define DIRSEP '/'
#endif
-static CURLcode file_upload(struct connectdata *conn)
+static CURLcode file_upload(struct Curl_easy *data)
{
- struct FILEPROTO *file = conn->data->req.protop;
+ struct FILEPROTO *file = data->req.p.file;
const char *dir = strchr(file->path, DIRSEP);
int fd;
int mode;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
struct_stat file_stat;
@@ -264,7 +258,7 @@ static CURLcode file_upload(struct connectdata *conn)
* Since FILE: doesn't do the full init, we need to provide some extra
* assignments here.
*/
- conn->data->req.upload_fromhere = buf;
+ data->req.upload_fromhere = buf;
if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
@@ -283,7 +277,7 @@ static CURLcode file_upload(struct connectdata *conn)
else
mode = MODE_DEFAULT|O_TRUNC;
- fd = open(file->path, mode, conn->data->set.new_file_perms);
+ fd = open(file->path, mode, data->set.new_file_perms);
if(fd < 0) {
failf(data, "Can't open %s for writing", file->path);
return CURLE_WRITE_ERROR;
@@ -307,7 +301,7 @@ static CURLcode file_upload(struct connectdata *conn)
size_t nread;
size_t nwrite;
size_t readcount;
- result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount);
+ result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount);
if(result)
break;
@@ -343,12 +337,12 @@ static CURLcode file_upload(struct connectdata *conn)
Curl_pgrsSetUploadCounter(data, bytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, Curl_now());
}
- if(!result && Curl_pgrsUpdate(conn))
+ if(!result && Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
close(fd);
@@ -364,7 +358,7 @@ static CURLcode file_upload(struct connectdata *conn)
* opposed to sockets) we instead perform the whole do-operation in this
* function.
*/
-static CURLcode file_do(struct connectdata *conn, bool *done)
+static CURLcode file_do(struct Curl_easy *data, bool *done)
{
/* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system)
@@ -375,10 +369,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
Windows version to have a different struct without
having to redefine the simple word 'stat' */
- curl_off_t expected_size = 0;
+ curl_off_t expected_size = -1;
bool size_known;
bool fstated = FALSE;
- struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
int fd;
@@ -389,17 +382,17 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
Curl_pgrsStartNow(data);
if(data->set.upload)
- return file_upload(conn);
+ return file_upload(data);
- file = conn->data->req.protop;
+ file = data->req.p.file;
/* get the fd from the connection phase */
fd = file->fd;
/* VMS: This only works reliable for STREAMLF files */
if(-1 != fstat(fd, &statbuf)) {
- /* we could stat it, then read out the size */
- expected_size = statbuf.st_size;
+ if(!S_ISDIR(statbuf.st_mode))
+ expected_size = statbuf.st_size;
/* and store the modification time */
data->info.filetime = statbuf.st_mtime;
fstated = TRUE;
@@ -417,14 +410,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
struct tm buffer;
const struct tm *tm = &buffer;
char header[80];
- msnprintf(header, sizeof(header),
- "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
- expected_size);
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
- if(result)
- return result;
+ if(expected_size >= 0) {
+ msnprintf(header, sizeof(header),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
+ expected_size);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
+ if(result)
+ return result;
+ }
- result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ result = Curl_client_write(data, CLIENTWRITE_HEADER,
(char *)"Accept-ranges: bytes\r\n", 0);
if(result)
return result;
@@ -445,7 +440,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
tm->tm_min,
tm->tm_sec,
data->set.opt_no_body ? "": "\r\n");
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
if(result)
return result;
/* set the file size to make it available post transfer */
@@ -455,7 +450,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
}
/* Check whether file range has been specified */
- result = Curl_range(conn);
+ result = Curl_range(data);
if(result)
return result;
@@ -524,18 +519,18 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
if(size_known)
expected_size -= nread;
- result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
if(result)
return result;
Curl_pgrsSetDownloadCounter(data, bytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, Curl_now());
}
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
return result;
diff --git a/Utilities/cmcurl/lib/file.h b/Utilities/cmcurl/lib/file.h
index f6b74a7f7..338f92e46 100644
--- a/Utilities/cmcurl/lib/file.h
+++ b/Utilities/cmcurl/lib/file.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c
index 2630c9e46..b7e9f0f5e 100644
--- a/Utilities/cmcurl/lib/fileinfo.c
+++ b/Utilities/cmcurl/lib/fileinfo.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h
index f4d8f3b90..5ae23ad4a 100644
--- a/Utilities/cmcurl/lib/fileinfo.h
+++ b/Utilities/cmcurl/lib/fileinfo.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -27,7 +27,7 @@
struct fileinfo {
struct curl_fileinfo info;
- struct curl_llist_element list;
+ struct Curl_llist_element list;
};
struct fileinfo *Curl_fileinfo_alloc(void);
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 1cab2c5c2..769f06a70 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/formdata.h b/Utilities/cmcurl/lib/formdata.h
index 3766d38f2..09c6e9c28 100644
--- a/Utilities/cmcurl/lib/formdata.h
+++ b/Utilities/cmcurl/lib/formdata.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -29,22 +29,22 @@
/* used by FormAdd for temporary storage */
struct FormInfo {
char *name;
- bool name_alloc;
size_t namelength;
char *value;
- bool value_alloc;
curl_off_t contentslength;
char *contenttype;
- bool contenttype_alloc;
long flags;
char *buffer; /* pointer to existing buffer used for file upload */
size_t bufferlength;
char *showfilename; /* The file name to show. If not set, the actual
file name will be used */
- bool showfilename_alloc;
char *userp; /* pointer for the read callback */
struct curl_slist *contentheader;
struct FormInfo *more;
+ bool name_alloc;
+ bool value_alloc;
+ bool contenttype_alloc;
+ bool showfilename_alloc;
};
CURLcode Curl_getformdata(struct Curl_easy *data,
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 7d805fac8..f8f970cc8 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -59,7 +59,7 @@
#include "fileinfo.h"
#include "ftplistparser.h"
#include "curl_range.h"
-#include "curl_sec.h"
+#include "curl_krb5.h"
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
@@ -96,68 +96,65 @@
/* Local API functions */
#ifndef DEBUGBUILD
-static void _state(struct connectdata *conn,
+static void _state(struct Curl_easy *data,
ftpstate newstate);
#define state(x,y) _state(x,y)
#else
-static void _state(struct connectdata *conn,
+static void _state(struct Curl_easy *data,
ftpstate newstate,
int lineno);
#define state(x,y) _state(x,y,__LINE__)
#endif
-static CURLcode ftp_sendquote(struct connectdata *conn,
+static CURLcode ftp_sendquote(struct Curl_easy *data,
+ struct connectdata *conn,
struct curl_slist *quote);
-static CURLcode ftp_quit(struct connectdata *conn);
-static CURLcode ftp_parse_url_path(struct connectdata *conn);
-static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
+static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn);
+static CURLcode ftp_parse_url_path(struct Curl_easy *data);
+static CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *done);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static void ftp_pasv_verbose(struct connectdata *conn,
+static void ftp_pasv_verbose(struct Curl_easy *data,
struct Curl_addrinfo *ai,
char *newhost, /* ascii version */
int port);
#endif
-static CURLcode ftp_state_prepare_transfer(struct connectdata *conn);
-static CURLcode ftp_state_mdtm(struct connectdata *conn);
-static CURLcode ftp_state_quote(struct connectdata *conn,
+static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data);
+static CURLcode ftp_state_mdtm(struct Curl_easy *data);
+static CURLcode ftp_state_quote(struct Curl_easy *data,
bool init, ftpstate instate);
-static CURLcode ftp_nb_type(struct connectdata *conn,
+static CURLcode ftp_nb_type(struct Curl_easy *data,
+ struct connectdata *conn,
bool ascii, ftpstate newstate);
static int ftp_need_type(struct connectdata *conn,
bool ascii);
-static CURLcode ftp_do(struct connectdata *conn, bool *done);
-static CURLcode ftp_done(struct connectdata *conn,
+static CURLcode ftp_do(struct Curl_easy *data, bool *done);
+static CURLcode ftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode ftp_connect(struct connectdata *conn, bool *done);
-static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
-static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
-static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
-static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks);
-static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode ftp_doing(struct connectdata *conn,
+static CURLcode ftp_connect(struct Curl_easy *data, bool *done);
+static CURLcode ftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection);
+static CURLcode ftp_do_more(struct Curl_easy *data, int *completed);
+static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done);
+static int ftp_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
+static int ftp_domore_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+static CURLcode ftp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode ftp_setup_connection(struct connectdata *conn);
-
-static CURLcode init_wc_data(struct connectdata *conn);
-static CURLcode wc_statemach(struct connectdata *conn);
-
+static CURLcode ftp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode init_wc_data(struct Curl_easy *data);
+static CURLcode wc_statemach(struct Curl_easy *data);
static void wc_data_dtor(void *ptr);
-
-static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
-
-static CURLcode ftp_readresp(curl_socket_t sockfd,
+static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
+static CURLcode ftp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *ftpcode,
size_t *size);
-static CURLcode ftp_dophase_done(struct connectdata *conn,
+static CURLcode ftp_dophase_done(struct Curl_easy *data,
bool connected);
-/* easy-to-use macro: */
-#define PPSENDF(x,y,z) result = Curl_pp_sendf(x,y,z); \
- if(result) \
- return result
-
-
/*
* FTP protocol handler.
*/
@@ -180,6 +177,7 @@ const struct Curl_handler Curl_handler_ftp = {
ZERO_NULL, /* connection_check */
PORT_FTP, /* defport */
CURLPROTO_FTP, /* protocol */
+ CURLPROTO_FTP, /* family */
PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
PROTOPT_WILDCARD /* flags */
@@ -209,15 +207,17 @@ const struct Curl_handler Curl_handler_ftps = {
ZERO_NULL, /* connection_check */
PORT_FTPS, /* defport */
CURLPROTO_FTPS, /* protocol */
+ CURLPROTO_FTP, /* family */
PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
};
#endif
-static void close_secondarysocket(struct connectdata *conn)
+static void close_secondarysocket(struct Curl_easy *data,
+ struct connectdata *conn)
{
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
- Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
}
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
@@ -264,9 +264,9 @@ static void freedirs(struct ftp_conn *ftpc)
* called to accept the connection and close the listening socket
*
*/
-static CURLcode AcceptServerConnect(struct connectdata *conn)
+static CURLcode AcceptServerConnect(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[SECONDARYSOCKET];
curl_socket_t s = CURL_SOCKET_BAD;
#ifdef ENABLE_IPV6
@@ -281,7 +281,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
s = accept(sock, (struct sockaddr *) &add, &size);
}
- Curl_closesocket(conn, sock); /* close the first socket */
+ Curl_closesocket(data, conn, sock); /* close the first socket */
if(CURL_SOCKET_BAD == s) {
failf(data, "Error accept()ing server connect");
@@ -307,7 +307,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
Curl_set_in_callback(data, false);
if(error) {
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
return CURLE_ABORTED_BY_CALLBACK;
}
}
@@ -363,9 +363,9 @@ static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
* connection for a negative response regarding a failure in connecting
*
*/
-static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
+static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -389,7 +389,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
/* Data connection could not be established, let's return */
infof(data, "There is negative response in cache while serv connect\n");
- (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
return CURLE_FTP_ACCEPT_FAILED;
}
@@ -411,7 +411,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
}
else if(result & CURL_CSELECT_IN) {
infof(data, "Ctrl conn has data while waiting for data conn\n");
- (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
if(ftpcode/100 > 3)
return CURLE_FTP_ACCEPT_FAILED;
@@ -434,16 +434,16 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
* setup transfer parameters and initiate the data transfer.
*
*/
-static CURLcode InitiateTransfer(struct connectdata *conn)
+static CURLcode InitiateTransfer(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
if(conn->bits.ftp_use_data_ssl) {
/* since we only have a plaintext TCP connection here, we must now
* do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
- result = Curl_ssl_connect(conn, SECONDARYSOCKET);
+ result = Curl_ssl_connect(data, conn, SECONDARYSOCKET);
if(result)
return result;
}
@@ -465,7 +465,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
}
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
@@ -479,9 +479,8 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
* accepted.
*
*/
-static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
+static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
{
- struct Curl_easy *data = conn->data;
timediff_t timeout_ms;
CURLcode result = CURLE_OK;
@@ -499,16 +498,16 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
}
/* see if the connection request is already here */
- result = ReceivedServerConnect(conn, connected);
+ result = ReceivedServerConnect(data, connected);
if(result)
return result;
if(*connected) {
- result = AcceptServerConnect(conn);
+ result = AcceptServerConnect(data);
if(result)
return result;
- result = InitiateTransfer(conn);
+ result = InitiateTransfer(data);
if(result)
return result;
}
@@ -531,9 +530,10 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
/* macro to check for the last line in an FTP server response */
#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
-static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
- int *code)
+static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *code)
{
+ (void)data;
(void)conn;
if((len > 3) && LASTLINE(line)) {
@@ -544,34 +544,35 @@ static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
return FALSE;
}
-static CURLcode ftp_readresp(curl_socket_t sockfd,
+static CURLcode ftp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *ftpcode, /* return the ftp-code if done */
size_t *size) /* size of the response */
{
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data = conn->data;
-#ifdef HAVE_GSSAPI
- char * const buf = data->state.buffer;
-#endif
int code;
- CURLcode result = Curl_pp_readresp(sockfd, pp, &code, size);
+ CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size);
-#if defined(HAVE_GSSAPI)
- /* handle the security-oriented responses 6xx ***/
- switch(code) {
- case 631:
- code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
- break;
- case 632:
- code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE);
- break;
- case 633:
- code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL);
- break;
- default:
- /* normal ftp stuff we pass through! */
- break;
+#ifdef HAVE_GSSAPI
+ {
+ struct connectdata *conn = data->conn;
+ char * const buf = data->state.buffer;
+
+ /* handle the security-oriented responses 6xx ***/
+ switch(code) {
+ case 631:
+ code = Curl_sec_read_msg(data, conn, buf, PROT_SAFE);
+ break;
+ case 632:
+ code = Curl_sec_read_msg(data, conn, buf, PROT_PRIVATE);
+ break;
+ case 633:
+ code = Curl_sec_read_msg(data, conn, buf, PROT_CONFIDENTIAL);
+ break;
+ default:
+ /* normal ftp stuff we pass through! */
+ break;
+ }
}
#endif
@@ -590,7 +591,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
* generically is a good idea.
*/
infof(data, "We got a 421 - timeout!\n");
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OPERATION_TIMEDOUT;
}
@@ -605,8 +606,8 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
*
*/
-CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
- struct connectdata *conn,
+CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
+ ssize_t *nreadp, /* return number of bytes read */
int *ftpcode) /* return the ftp-code */
{
/*
@@ -616,8 +617,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* Alas, read as much as possible, split up into lines, use the ending
* line in a response or continue reading. */
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -635,7 +636,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
- timediff_t timeout = Curl_pp_state_timeout(pp, FALSE);
+ timediff_t timeout = Curl_pp_state_timeout(data, pp, FALSE);
timediff_t interval_ms;
if(timeout <= 0) {
@@ -677,7 +678,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
return CURLE_RECV_ERROR;
case 0: /* timeout */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
continue; /* just continue in our loop for the timeout duration */
@@ -685,7 +686,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
break;
}
}
- result = ftp_readresp(sockfd, pp, ftpcode, &nread);
+ result = ftp_readresp(data, sockfd, pp, ftpcode, &nread);
if(result)
break;
@@ -749,13 +750,14 @@ static const char * const ftp_state_names[]={
#endif
/* This is the ONLY way to change FTP state! */
-static void _state(struct connectdata *conn,
+static void _state(struct Curl_easy *data,
ftpstate newstate
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
#if defined(DEBUGBUILD)
@@ -764,7 +766,7 @@ static void _state(struct connectdata *conn,
(void) lineno;
#else
if(ftpc->state != newstate)
- infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
+ infof(data, "FTP %p (line %d) state change from %s to %s\n",
(void *)ftpc, lineno, ftp_state_names[ftpc->state],
ftp_state_names[newstate]);
#endif
@@ -773,40 +775,43 @@ static void _state(struct connectdata *conn,
ftpc->state = newstate;
}
-static CURLcode ftp_state_user(struct connectdata *conn)
+static CURLcode ftp_state_user(struct Curl_easy *data,
+ struct connectdata *conn)
{
- CURLcode result;
- /* send USER */
- PPSENDF(&conn->proto.ftpc.pp, "USER %s", conn->user?conn->user:"");
-
- state(conn, FTP_USER);
- conn->data->state.ftp_trying_alternative = FALSE;
-
- return CURLE_OK;
+ CURLcode result = Curl_pp_sendf(data,
+ &conn->proto.ftpc.pp, "USER %s",
+ conn->user?conn->user:"");
+ if(!result) {
+ state(data, FTP_USER);
+ data->state.ftp_trying_alternative = FALSE;
+ }
+ return result;
}
-static CURLcode ftp_state_pwd(struct connectdata *conn)
+static CURLcode ftp_state_pwd(struct Curl_easy *data,
+ struct connectdata *conn)
{
- CURLcode result;
-
- /* send PWD to discover our entry point */
- PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
- state(conn, FTP_PWD);
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
+ if(!result)
+ state(data, FTP_PWD);
- return CURLE_OK;
+ return result;
}
/* For the FTP "protocol connect" and "doing" phases only */
-static int ftp_getsock(struct connectdata *conn,
+static int ftp_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
}
/* For the FTP "DO_MORE" phase only */
-static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int ftp_domore_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ (void)data;
/* When in DO_MORE state, we could be either waiting for us to connect to a
* remote site, or we could wait for that site to connect to us. Or just
@@ -824,7 +829,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
connect on the secondary connection */
socks[0] = conn->sock[FIRSTSOCKET];
- if(!conn->data->set.ftp_use_port) {
+ if(!data->set.ftp_use_port) {
int s;
int i;
/* PORT is used to tell the server to connect to us, and during that we
@@ -844,7 +849,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
return bits;
}
- return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
}
/* This is called after the FTP_QUOTE state is passed.
@@ -853,17 +858,18 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
the correct directory. It may also need to send MKD commands to create
missing ones, if that option is enabled.
*/
-static CURLcode ftp_state_cwd(struct connectdata *conn)
+static CURLcode ftp_state_cwd(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(ftpc->cwddone)
/* already done and fine */
- result = ftp_state_mdtm(conn);
+ result = ftp_state_mdtm(data);
else {
/* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
- DEBUGASSERT((conn->data->set.ftp_filemethod != FTPFILE_NOCWD) ||
+ DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) ||
!(ftpc->dirdepth && ftpc->dirs[0][0] == '/'));
ftpc->count2 = 0; /* count2 counts failed CWDs */
@@ -871,7 +877,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
/* count3 is set to allow a MKD to fail once. In the case when first CWD
fails and then MKD fails (due to another session raced it to create the
dir) this then allows for a second try to CWD to it */
- ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0;
+ ftpc->count3 = (data->set.ftp_create_missing_dirs == 2)?1:0;
if(conn->bits.reuse && ftpc->entrypath &&
/* no need to go to entrypath when we have an absolute path */
@@ -881,20 +887,23 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
where we ended up after login: */
ftpc->cwdcount = 0; /* we count this as the first path, then we add one
for all upcoming ones in the ftp->dirs[] array */
- PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
- state(conn, FTP_CWD);
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
+ if(!result)
+ state(data, FTP_CWD);
}
else {
if(ftpc->dirdepth) {
ftpc->cwdcount = 1;
/* issue the first CWD, the rest is sent when the CWD responses are
received... */
- PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]);
- state(conn, FTP_CWD);
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount -1]);
+ if(!result)
+ state(data, FTP_CWD);
}
else {
/* No CWD necessary */
- result = ftp_state_mdtm(conn);
+ result = ftp_state_mdtm(data);
}
}
}
@@ -907,13 +916,12 @@ typedef enum {
DONE
} ftpport;
-static CURLcode ftp_state_use_port(struct connectdata *conn,
+static CURLcode ftp_state_use_port(struct Curl_easy *data,
ftpport fcmd) /* start with this */
-
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct Curl_easy *data = conn->data;
curl_socket_t portsock = CURL_SOCKET_BAD;
char myhost[MAX_IPADR_LEN + 1] = "";
@@ -1070,9 +1078,9 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
}
/* resolv ip/host to ip */
- rc = Curl_resolv(conn, host, 0, FALSE, &h);
+ rc = Curl_resolv(data, host, 0, FALSE, &h);
if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(conn, &h);
+ (void)Curl_resolver_wait_resolv(data, &h);
if(h) {
res = h->addr;
/* when we return from this function, we can forget about this entry
@@ -1096,7 +1104,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
portsock = CURL_SOCKET_BAD;
error = 0;
for(ai = res; ai; ai = ai->ai_next) {
- result = Curl_socket(conn, ai, NULL, &portsock);
+ result = Curl_socket(data, ai, NULL, &portsock);
if(result) {
error = SOCKERRNO;
continue;
@@ -1136,7 +1144,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
port = port_min;
@@ -1146,7 +1154,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(error != EADDRINUSE && error != EACCES) {
failf(data, "bind(port=%hu) failed: %s", port,
Curl_strerror(error, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
}
@@ -1159,7 +1167,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* maybe all ports were in use already*/
if(port > port_max) {
failf(data, "bind() failed, we ran out of ports!");
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
@@ -1169,7 +1177,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
@@ -1178,7 +1186,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(listen(portsock, 1)) {
failf(data, "socket failure: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
@@ -1227,17 +1235,17 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
* EPRT |2|1080::8:800:200C:417A|5282|
*/
- result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
sa->sa_family == AF_INET?1:2,
myhost, port);
if(result) {
failf(data, "Failure sending EPRT command: %s",
curl_easy_strerror(result));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
/* don't retry using PORT */
ftpc->count1 = PORT;
/* bail out */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return result;
}
break;
@@ -1260,13 +1268,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
*dest = 0;
msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
- result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], target);
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target);
if(result) {
failf(data, "Failure sending PORT command: %s",
curl_easy_strerror(result));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
/* bail out */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return result;
}
break;
@@ -1276,7 +1284,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* store which command was sent */
ftpc->count1 = fcmd;
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
/* we set the secondary socket variable to this for now, it is only so that
the cleanup function will close it in case we fail before the true
@@ -1292,11 +1300,12 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
*/
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
- state(conn, FTP_PORT);
+ state(data, FTP_PORT);
return result;
}
-static CURLcode ftp_state_use_pasv(struct connectdata *conn)
+static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
@@ -1326,12 +1335,12 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
modeoff = conn->bits.ftp_use_epsv?0:1;
- PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
-
- ftpc->count1 = modeoff;
- state(conn, FTP_PASV);
- infof(conn->data, "Connect data stream passively\n");
-
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
+ if(!result) {
+ ftpc->count1 = modeoff;
+ state(data, FTP_PASV);
+ infof(data, "Connect data stream passively\n");
+ }
return result;
}
@@ -1342,53 +1351,54 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
* request is made. Thus, if an actual transfer is to be made this is where we
* take off for real.
*/
-static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
+static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
- struct Curl_easy *data = conn->data;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
if(ftp->transfer != FTPTRANSFER_BODY) {
/* doesn't transfer any data */
/* still possibly do PRE QUOTE jobs */
- state(conn, FTP_RETR_PREQUOTE);
- result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+ state(data, FTP_RETR_PREQUOTE);
+ result = ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
}
else if(data->set.ftp_use_port) {
/* We have chosen to use the PORT (or similar) command */
- result = ftp_state_use_port(conn, EPRT);
+ result = ftp_state_use_port(data, EPRT);
}
else {
/* We have chosen (this is default) to use the PASV (or similar) command */
if(data->set.ftp_use_pret) {
/* The user has requested that we send a PRET command
to prepare the server for the upcoming PASV */
- if(!conn->proto.ftpc.file) {
- PPSENDF(&conn->proto.ftpc.pp, "PRET %s",
- data->set.str[STRING_CUSTOMREQUEST]?
- data->set.str[STRING_CUSTOMREQUEST]:
- (data->set.ftp_list_only?"NLST":"LIST"));
- }
- else if(data->set.upload) {
- PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file);
- }
- else {
- PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file);
- }
- state(conn, FTP_PRET);
- }
- else {
- result = ftp_state_use_pasv(conn);
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ if(!conn->proto.ftpc.file)
+ 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"));
+ else if(data->set.upload)
+ result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
+ conn->proto.ftpc.file);
+ else
+ result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
+ conn->proto.ftpc.file);
+ if(!result)
+ state(data, FTP_PRET);
}
+ else
+ result = ftp_state_use_pasv(data, conn);
}
return result;
}
-static CURLcode ftp_state_rest(struct connectdata *conn)
+static CURLcode ftp_state_rest(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
@@ -1396,41 +1406,42 @@ static CURLcode ftp_state_rest(struct connectdata *conn)
/* Determine if server can respond to REST command and therefore
whether it supports range */
- PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
-
- state(conn, FTP_REST);
+ result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
+ if(!result)
+ state(data, FTP_REST);
}
else
- result = ftp_state_prepare_transfer(conn);
+ result = ftp_state_prepare_transfer(data);
return result;
}
-static CURLcode ftp_state_size(struct connectdata *conn)
+static CURLcode ftp_state_size(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer == FTPTRANSFER_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 */
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
-
- state(conn, FTP_SIZE);
+ result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(data, FTP_SIZE);
}
else
- result = ftp_state_rest(conn);
+ result = ftp_state_rest(data, conn);
return result;
}
-static CURLcode ftp_state_list(struct connectdata *conn)
+static CURLcode ftp_state_list(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
/* If this output is to be machine-parsed, the NLST command might be better
to use, since the LIST command output is not specified or standard in any
@@ -1482,34 +1493,32 @@ static CURLcode ftp_state_list(struct connectdata *conn)
if(!cmd)
return CURLE_OUT_OF_MEMORY;
- result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", cmd);
free(cmd);
- if(result)
- return result;
-
- state(conn, FTP_LIST);
+ if(!result)
+ state(data, FTP_LIST);
return result;
}
-static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
+static CURLcode ftp_state_retr_prequote(struct Curl_easy *data)
{
/* We've sent the TYPE, now we must send the list of prequote strings */
- return ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+ return ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
}
-static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
+static CURLcode ftp_state_stor_prequote(struct Curl_easy *data)
{
/* We've sent the TYPE, now we must send the list of prequote strings */
- return ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
+ return ftp_state_quote(data, TRUE, FTP_STOR_PREQUOTE);
}
-static CURLcode ftp_state_type(struct connectdata *conn)
+static CURLcode ftp_state_type(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
- struct Curl_easy *data = conn->data;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
/* If we have selected NOBODY and HEADER, it means that we only want file
@@ -1526,22 +1535,22 @@ static CURLcode ftp_state_type(struct connectdata *conn)
/* 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(conn, data->set.prefer_ascii, FTP_TYPE);
+ result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_TYPE);
if(result)
return result;
}
else
- result = ftp_state_size(conn);
+ result = ftp_state_size(data, conn);
return result;
}
/* This is called after the CWD commands have been done in the beginning of
the DO phase */
-static CURLcode ftp_state_mdtm(struct connectdata *conn)
+static CURLcode ftp_state_mdtm(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
/* Requested time of file or time-depended transfer? */
@@ -1549,24 +1558,25 @@ static CURLcode ftp_state_mdtm(struct connectdata *conn)
/* we have requested to get the modified-time of the file, this is a white
spot as the MDTM is not mentioned in RFC959 */
- PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
+ result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
- state(conn, FTP_MDTM);
+ if(!result)
+ state(data, FTP_MDTM);
}
else
- result = ftp_state_type(conn);
+ result = ftp_state_type(data);
return result;
}
/* This is called after the TYPE and possible quote commands have been sent */
-static CURLcode ftp_state_ul_setup(struct connectdata *conn,
+static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
bool sizechecked)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((data->state.resume_from && !sizechecked) ||
@@ -1587,8 +1597,9 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
if(data->state.resume_from < 0) {
/* Got no given size to start from, figure it out */
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
- state(conn, FTP_STOR_SIZE);
+ result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(data, FTP_STOR_SIZE);
return result;
}
@@ -1643,28 +1654,29 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
* ftp_done() because we didn't transfer anything! */
ftp->transfer = FTPTRANSFER_NONE;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
}
/* we've passed, proceed as normal */
} /* resume_from */
- PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
- ftpc->file);
-
- state(conn, FTP_STOR);
+ result = Curl_pp_sendf(data, &ftpc->pp,
+ data->set.ftp_append?"APPE %s":"STOR %s",
+ ftpc->file);
+ if(!result)
+ state(data, FTP_STOR);
return result;
}
-static CURLcode ftp_state_quote(struct connectdata *conn,
+static CURLcode ftp_state_quote(struct Curl_easy *data,
bool init,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
bool quote = FALSE;
struct curl_slist *item;
@@ -1711,8 +1723,10 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
else
ftpc->count2 = 0; /* failure means cancel operation */
- PPSENDF(&ftpc->pp, "%s", cmd);
- state(conn, instate);
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
+ if(result)
+ return result;
+ state(data, instate);
quote = TRUE;
}
}
@@ -1722,15 +1736,15 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
switch(instate) {
case FTP_QUOTE:
default:
- result = ftp_state_cwd(conn);
+ result = ftp_state_cwd(data, conn);
break;
case FTP_RETR_PREQUOTE:
if(ftp->transfer != FTPTRANSFER_BODY)
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
else {
if(ftpc->known_filesize != -1) {
Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
- result = ftp_state_retr(conn, ftpc->known_filesize);
+ result = ftp_state_retr(data, ftpc->known_filesize);
}
else {
if(data->set.ignorecl) {
@@ -1740,18 +1754,20 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
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.*/
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR);
}
else {
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
- state(conn, FTP_RETR_SIZE);
+ result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR_SIZE);
}
}
}
break;
case FTP_STOR_PREQUOTE:
- result = ftp_state_ul_setup(conn, FALSE);
+ result = ftp_state_ul_setup(data, FALSE);
break;
case FTP_POSTQUOTE:
break;
@@ -1763,7 +1779,8 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
problems */
-static CURLcode ftp_epsv_disable(struct connectdata *conn)
+static CURLcode ftp_epsv_disable(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -1773,19 +1790,21 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
#endif
) {
/* We can't disable EPSV when doing IPv6, so this is instead a fail */
- failf(conn->data, "Failed EPSV attempt, exiting\n");
+ failf(data, "Failed EPSV attempt, exiting");
return CURLE_WEIRD_SERVER_REPLY;
}
- infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
+ infof(data, "Failed EPSV attempt. Disabling EPSV\n");
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
- conn->data->state.errorbuf = FALSE; /* allow error message to get
+ data->state.errorbuf = FALSE; /* allow error message to get
rewritten */
- PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
- conn->proto.ftpc.count1++;
- /* remain in/go to the FTP_PASV state */
- state(conn, FTP_PASV);
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
+ if(!result) {
+ conn->proto.ftpc.count1++;
+ /* remain in/go to the FTP_PASV state */
+ state(data, FTP_PASV);
+ }
return result;
}
@@ -1800,15 +1819,15 @@ static char *control_address(struct connectdata *conn)
if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
return conn->host.name;
#endif
- return conn->ip_addr_str;
+ return conn->primary_ip;
}
-static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
+static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
int ftpcode)
{
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result;
- struct Curl_easy *data = conn->data;
struct Curl_dns_entry *addr = NULL;
enum resolve_t rc;
unsigned short connectport; /* the local port connect() should use! */
@@ -1864,8 +1883,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
else if((ftpc->count1 == 1) &&
(ftpcode == 227)) {
/* positive PASV response */
- unsigned int ip[4];
- unsigned int port[2];
+ unsigned int ip[4] = {0, 0, 0, 0};
+ unsigned int port[2] = {0, 0};
/*
* Scan for a sequence of six comma-separated numbers and use them as
@@ -1909,7 +1928,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
}
else if(ftpc->count1 == 0) {
/* EPSV failed, move on to PASV */
- return ftp_epsv_disable(conn);
+ return ftp_epsv_disable(data, conn);
}
else {
failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
@@ -1925,11 +1944,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
*/
const char * const host_name = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name;
- rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr);
+ rc = Curl_resolv(data, host_name, (int)conn->port, FALSE, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */
- (void)Curl_resolver_wait_resolv(conn, &addr);
+ (void)Curl_resolver_wait_resolv(data, &addr);
connectport =
(unsigned short)conn->port; /* we connect to the proxy's port */
@@ -1943,10 +1962,21 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
#endif
{
/* normal, direct, ftp connection */
- rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
+ DEBUGASSERT(ftpc->newhost);
+
+ /* postponed address resolution in case of tcp fastopen */
+ if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) {
+ Curl_conninfo_remote(data, conn, conn->sock[FIRSTSOCKET]);
+ Curl_safefree(ftpc->newhost);
+ ftpc->newhost = strdup(control_address(conn));
+ if(!ftpc->newhost)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ rc = Curl_resolv(data, ftpc->newhost, ftpc->newport, FALSE, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING */
- (void)Curl_resolver_wait_resolv(conn, &addr);
+ (void)Curl_resolver_wait_resolv(data, &addr);
connectport = ftpc->newport; /* we connect to the remote port */
@@ -1957,12 +1987,12 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
}
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
- result = Curl_connecthost(conn, addr);
+ result = Curl_connecthost(data, conn, addr);
if(result) {
Curl_resolv_unlock(data, addr); /* we're done using this address */
if(ftpc->count1 == 0 && ftpcode == 229)
- return ftp_epsv_disable(conn);
+ return ftp_epsv_disable(data, conn);
return result;
}
@@ -1976,7 +2006,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
if(data->set.verbose)
/* this just dumps information about this second connection */
- ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
+ ftp_pasv_verbose(data, addr->addr, ftpc->newhost, connectport);
Curl_resolv_unlock(data, addr); /* we're done using this address */
@@ -1987,15 +2017,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
conn->bits.do_more = TRUE;
- state(conn, FTP_STOP); /* this phase is completed */
+ state(data, FTP_STOP); /* this phase is completed */
return result;
}
-static CURLcode ftp_state_port_resp(struct connectdata *conn,
+static CURLcode ftp_state_port_resp(struct Curl_easy *data,
int ftpcode)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpport fcmd = (ftpport)ftpc->count1;
CURLcode result = CURLE_OK;
@@ -2017,23 +2047,23 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn,
}
else
/* try next */
- result = ftp_state_use_port(conn, fcmd);
+ result = ftp_state_use_port(data, fcmd);
}
else {
infof(data, "Connect data stream actively\n");
- state(conn, FTP_STOP); /* end of DO phase */
- result = ftp_dophase_done(conn, FALSE);
+ state(data, FTP_STOP); /* end of DO phase */
+ result = ftp_dophase_done(data, FALSE);
}
return result;
}
-static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
+static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
int ftpcode)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
switch(ftpcode) {
@@ -2080,7 +2110,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, 0);
if(result)
return result;
} /* end of a ridiculous amount of conditionals */
@@ -2092,7 +2122,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
break;
case 550: /* "No such file or directory" */
failf(data, "Given file does not exist");
- result = CURLE_FTP_COULDNT_RETR_FILE;
+ result = CURLE_REMOTE_FILE_NOT_FOUND;
break;
}
@@ -2105,7 +2135,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
infof(data, "The requested document is not new enough\n");
ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2114,7 +2144,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
infof(data, "The requested document is not old enough\n");
ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2126,17 +2156,17 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
}
if(!result)
- result = ftp_state_type(conn);
+ result = ftp_state_type(data);
return result;
}
-static CURLcode ftp_state_type_resp(struct connectdata *conn,
+static CURLcode ftp_state_type_resp(struct Curl_easy *data,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
if(ftpcode/100 != 2) {
/* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
@@ -2150,23 +2180,23 @@ static CURLcode ftp_state_type_resp(struct connectdata *conn,
ftpcode);
if(instate == FTP_TYPE)
- result = ftp_state_size(conn);
+ result = ftp_state_size(data, conn);
else if(instate == FTP_LIST_TYPE)
- result = ftp_state_list(conn);
+ result = ftp_state_list(data);
else if(instate == FTP_RETR_TYPE)
- result = ftp_state_retr_prequote(conn);
+ result = ftp_state_retr_prequote(data);
else if(instate == FTP_STOR_TYPE)
- result = ftp_state_stor_prequote(conn);
+ result = ftp_state_stor_prequote(data);
return result;
}
-static CURLcode ftp_state_retr(struct connectdata *conn,
- curl_off_t filesize)
+static CURLcode ftp_state_retr(struct Curl_easy *data,
+ curl_off_t filesize)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
@@ -2221,7 +2251,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
/* 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;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
@@ -2229,26 +2259,26 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
infof(data, "Instructs server to resume from offset %"
CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
- PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
- data->state.resume_from);
-
- state(conn, FTP_RETR_REST);
+ result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
+ data->state.resume_from);
+ if(!result)
+ state(data, FTP_RETR_REST);
}
else {
/* no resume */
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR);
}
return result;
}
-static CURLcode ftp_state_size_resp(struct connectdata *conn,
+static CURLcode ftp_state_size_resp(struct Curl_easy *data,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
curl_off_t filesize = -1;
char *buf = data->state.buffer;
@@ -2272,6 +2302,10 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
(void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
}
+ else if(ftpcode == 550) { /* "No such file or directory" */
+ failf(data, "The file does not exist");
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2279,27 +2313,28 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
char clbuf[128];
msnprintf(clbuf, sizeof(clbuf),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0);
if(result)
return result;
}
#endif
Curl_pgrsSetDownloadSize(data, filesize);
- result = ftp_state_rest(conn);
+ result = ftp_state_rest(data, data->conn);
}
else if(instate == FTP_RETR_SIZE) {
Curl_pgrsSetDownloadSize(data, filesize);
- result = ftp_state_retr(conn, filesize);
+ result = ftp_state_retr(data, filesize);
}
else if(instate == FTP_STOR_SIZE) {
data->state.resume_from = filesize;
- result = ftp_state_ul_setup(conn, TRUE);
+ result = ftp_state_ul_setup(data, TRUE);
}
return result;
}
-static CURLcode ftp_state_rest_resp(struct connectdata *conn,
+static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
+ struct connectdata *conn,
int ftpcode,
ftpstate instate)
{
@@ -2312,22 +2347,23 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(ftpcode == 350) {
char buffer[24]= { "Accept-ranges: bytes\r\n" };
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, 0);
if(result)
return result;
}
#endif
- result = ftp_state_prepare_transfer(conn);
+ result = ftp_state_prepare_transfer(data);
break;
case FTP_RETR_REST:
if(ftpcode != 350) {
- failf(conn->data, "Couldn't use REST");
+ failf(data, "Couldn't use REST");
result = CURLE_FTP_COULDNT_USE_REST;
}
else {
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR);
}
break;
}
@@ -2335,15 +2371,15 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
return result;
}
-static CURLcode ftp_state_stor_resp(struct connectdata *conn,
+static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
int ftpcode, ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
if(ftpcode >= 400) {
failf(data, "Failed FTP upload: %0d", ftpcode);
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
/* oops, we never close the sockets! */
return CURLE_UPLOAD_FAILED;
}
@@ -2354,9 +2390,9 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
if(data->set.ftp_use_port) {
bool connected;
- state(conn, FTP_STOP); /* no longer in STOR state */
+ state(data, FTP_STOP); /* no longer in STOR state */
- result = AllowServerConnect(conn, &connected);
+ result = AllowServerConnect(data, &connected);
if(result)
return result;
@@ -2368,17 +2404,17 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
return CURLE_OK;
}
- return InitiateTransfer(conn);
+ return InitiateTransfer(data);
}
/* for LIST and RETR responses */
-static CURLcode ftp_state_get_resp(struct connectdata *conn,
- int ftpcode,
- ftpstate instate)
+static CURLcode ftp_state_get_resp(struct Curl_easy *data,
+ int ftpcode,
+ ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
if((ftpcode == 150) || (ftpcode == 125)) {
@@ -2468,25 +2504,25 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
if(data->set.ftp_use_port) {
bool connected;
- result = AllowServerConnect(conn, &connected);
+ result = AllowServerConnect(data, &connected);
if(result)
return result;
if(!connected) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
infof(data, "Data conn was not available immediately\n");
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
ftpc->wait_data_conn = TRUE;
}
}
else
- return InitiateTransfer(conn);
+ return InitiateTransfer(data);
}
else {
if((instate == FTP_LIST) && (ftpcode == 450)) {
/* simply no matching files in the dir listing */
ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
- state(conn, FTP_STOP); /* this phase is over */
+ state(data, FTP_STOP); /* this phase is over */
}
else {
failf(data, "RETR response: %03d", ftpcode);
@@ -2500,11 +2536,12 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
}
/* after USER, PASS and ACCT */
-static CURLcode ftp_state_loggedin(struct connectdata *conn)
+static CURLcode ftp_state_loggedin(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- if(conn->ssl[FIRSTSOCKET].use) {
+ if(conn->bits.ftp_use_control_ssl) {
/* PBSZ = PROTECTION BUFFER SIZE.
The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
@@ -2519,22 +2556,23 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
parameter of '0' to indicate that no buffering is taking place
and the data connection should not be encapsulated.
*/
- PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
- state(conn, FTP_PBSZ);
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
+ if(!result)
+ state(data, FTP_PBSZ);
}
else {
- result = ftp_state_pwd(conn);
+ result = ftp_state_pwd(data, conn);
}
return result;
}
/* for USER and PASS responses */
-static CURLcode ftp_state_user_resp(struct connectdata *conn,
+static CURLcode ftp_state_user_resp(struct Curl_easy *data,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
(void)instate; /* no use for this yet */
@@ -2542,18 +2580,22 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
- PPSENDF(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:"");
- state(conn, FTP_PASS);
+ result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
+ conn->passwd?conn->passwd:"");
+ if(!result)
+ state(data, FTP_PASS);
}
else if(ftpcode/100 == 2) {
/* 230 User ... logged in.
(the user logged in with or without password) */
- result = ftp_state_loggedin(conn);
+ result = ftp_state_loggedin(data);
}
else if(ftpcode == 332) {
if(data->set.str[STRING_FTP_ACCOUNT]) {
- PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
- state(conn, FTP_ACCT);
+ result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
+ data->set.str[STRING_FTP_ACCOUNT]);
+ if(!result)
+ state(data, FTP_ACCT);
}
else {
failf(data, "ACCT requested but none available");
@@ -2566,14 +2608,16 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
530 User ... access denied
(the server denies to log the specified user) */
- if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
- !conn->data->state.ftp_trying_alternative) {
+ if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
+ !data->state.ftp_trying_alternative) {
/* Ok, USER failed. Let's try the supplied command. */
- PPSENDF(&conn->proto.ftpc.pp, "%s",
- conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
- conn->data->state.ftp_trying_alternative = TRUE;
- state(conn, FTP_USER);
- result = CURLE_OK;
+ result =
+ Curl_pp_sendf(data, &ftpc->pp, "%s",
+ data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ if(!result) {
+ data->state.ftp_trying_alternative = TRUE;
+ state(data, FTP_USER);
+ }
}
else {
failf(data, "Access denied: %03d", ftpcode);
@@ -2584,27 +2628,26 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
}
/* for ACCT response */
-static CURLcode ftp_state_acct_resp(struct connectdata *conn,
+static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
int ftpcode)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
if(ftpcode != 230) {
failf(data, "ACCT rejected by server: %03d", ftpcode);
result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
}
else
- result = ftp_state_loggedin(conn);
+ result = ftp_state_loggedin(data);
return result;
}
-static CURLcode ftp_statemach_act(struct connectdata *conn)
+static CURLcode ftp_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
int ftpcode;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -2612,9 +2655,9 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
size_t nread = 0;
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
- result = ftp_readresp(sock, pp, &ftpcode, &nread);
+ result = ftp_readresp(data, sock, pp, &ftpcode, &nread);
if(result)
return result;
@@ -2624,7 +2667,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_WAIT220:
if(ftpcode == 230)
/* 230 User logged in - already! */
- return ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ return ftp_state_user_resp(data, ftpcode, ftpc->state);
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
@@ -2642,21 +2685,15 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
set a valid level */
Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
- if(Curl_sec_login(conn))
+ if(Curl_sec_login(data, conn))
infof(data, "Logging in with password in cleartext!\n");
else
infof(data, "Authentication successful\n");
}
#endif
- if(data->set.use_ssl &&
- (!conn->ssl[FIRSTSOCKET].use
-#ifndef CURL_DISABLE_PROXY
- || (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
- !conn->proxy_ssl[FIRSTSOCKET].use)
-#endif
- )) {
- /* We don't have a SSL/TLS connection yet, but FTPS is
+ if(data->set.use_ssl && !conn->bits.ftp_use_control_ssl) {
+ /* We don't have a SSL/TLS control connection yet, but FTPS is
requested. Try a FTPS connection now */
ftpc->count3 = 0;
@@ -2675,15 +2712,13 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
(int)data->set.ftpsslauth);
return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
}
- PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
- state(conn, FTP_AUTH);
- }
- else {
- result = ftp_state_user(conn);
- if(result)
- return result;
+ result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
+ ftpauth[ftpc->count1]);
+ if(!result)
+ state(data, FTP_AUTH);
}
-
+ else
+ result = ftp_state_user(data, conn);
break;
case FTP_AUTH:
@@ -2698,16 +2733,18 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if((ftpcode == 234) || (ftpcode == 334)) {
/* Curl_ssl_connect is BLOCKING */
- result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
if(!result) {
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
- result = ftp_state_user(conn);
+ conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
+ result = ftp_state_user(data, conn);
}
}
else if(ftpc->count3 < 1) {
ftpc->count3++;
ftpc->count1 += ftpc->count2; /* get next attempt */
- result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
+ result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
+ ftpauth[ftpc->count1]);
/* remain in this same state */
}
else {
@@ -2716,27 +2753,25 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
result = CURLE_USE_SSL_FAILED;
else
/* ignore the failure and continue */
- result = ftp_state_user(conn);
+ result = ftp_state_user(data, conn);
}
-
- if(result)
- return result;
break;
case FTP_USER:
case FTP_PASS:
- result = ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_user_resp(data, ftpcode, ftpc->state);
break;
case FTP_ACCT:
- result = ftp_state_acct_resp(conn, ftpcode);
+ result = ftp_state_acct_resp(data, ftpcode);
break;
case FTP_PBSZ:
- PPSENDF(&ftpc->pp, "PROT %c",
- data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
- state(conn, FTP_PROT);
-
+ result =
+ Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
+ data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
+ if(!result)
+ state(data, FTP_PROT);
break;
case FTP_PROT:
@@ -2753,31 +2788,25 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(data->set.ftp_ccc) {
/* CCC - Clear Command Channel
*/
- PPSENDF(&ftpc->pp, "%s", "CCC");
- state(conn, FTP_CCC);
- }
- else {
- result = ftp_state_pwd(conn);
- if(result)
- return result;
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
+ if(!result)
+ state(data, FTP_CCC);
}
+ else
+ result = ftp_state_pwd(data, conn);
break;
case FTP_CCC:
if(ftpcode < 500) {
/* First shut down the SSL layer (note: this call will block) */
- result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
+ result = Curl_ssl_shutdown(data, conn, FIRSTSOCKET);
- if(result) {
- failf(conn->data, "Failed to clear the command channel (CCC)");
- return result;
- }
+ if(result)
+ failf(data, "Failed to clear the command channel (CCC)");
}
-
- /* Then continue as normal */
- result = ftp_state_pwd(conn);
- if(result)
- return result;
+ if(!result)
+ /* Then continue as normal */
+ result = ftp_state_pwd(data, conn);
break;
case FTP_PWD:
@@ -2843,8 +2872,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
systems. */
if(!ftpc->server_os && dir[0] != '/') {
-
- result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
if(result) {
free(dir);
return result;
@@ -2854,7 +2882,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
infof(data, "Entry path is '%s'\n", ftpc->entrypath);
/* also save it where getinfo can access it: */
data->state.most_recent_ftp_entrypath = ftpc->entrypath;
- state(conn, FTP_SYST);
+ state(data, FTP_SYST);
break;
}
@@ -2870,7 +2898,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
infof(data, "Failed to figure out path\n");
}
}
- state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE\n"));
break;
@@ -2897,7 +2925,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(strcasecompare(os, "OS/400")) {
/* Force OS400 name format 1. */
- result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1");
if(result) {
free(os);
return result;
@@ -2905,7 +2933,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* remember target server OS */
Curl_safefree(ftpc->server_os);
ftpc->server_os = os;
- state(conn, FTP_NAMEFMT);
+ state(data, FTP_NAMEFMT);
break;
}
/* Nothing special for the target server. */
@@ -2917,18 +2945,18 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* Cannot identify server OS. Continue anyway and cross fingers. */
}
- state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE\n"));
break;
case FTP_NAMEFMT:
if(ftpcode == 250) {
/* Name format change successful: reload initial path. */
- ftp_state_pwd(conn);
+ ftp_state_pwd(data, conn);
break;
}
- state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE\n"));
break;
@@ -2938,45 +2966,42 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_STOR_PREQUOTE:
if((ftpcode >= 400) && !ftpc->count2) {
/* failure response code, and not allowed to fail */
- failf(conn->data, "QUOT command failed with %03d", ftpcode);
- return CURLE_QUOTE_ERROR;
+ failf(data, "QUOT command failed with %03d", ftpcode);
+ result = CURLE_QUOTE_ERROR;
}
- result = ftp_state_quote(conn, FALSE, ftpc->state);
- if(result)
- return result;
-
+ else
+ result = ftp_state_quote(data, FALSE, ftpc->state);
break;
case FTP_CWD:
if(ftpcode/100 != 2) {
/* failure to CWD there */
- if(conn->data->set.ftp_create_missing_dirs &&
+ if(data->set.ftp_create_missing_dirs &&
ftpc->cwdcount && !ftpc->count2) {
/* try making it */
ftpc->count2++; /* counter to prevent CWD-MKD loops */
- PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]);
- state(conn, FTP_MKD);
+ result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
+ if(!result)
+ state(data, FTP_MKD);
}
else {
/* return failure */
failf(data, "Server denied you to change to the given directory");
ftpc->cwdfail = TRUE; /* don't remember this path as we failed
to enter it */
- return CURLE_REMOTE_ACCESS_DENIED;
+ result = CURLE_REMOTE_ACCESS_DENIED;
}
}
else {
/* success */
ftpc->count2 = 0;
- if(++ftpc->cwdcount <= ftpc->dirdepth) {
+ if(++ftpc->cwdcount <= ftpc->dirdepth)
/* send next CWD */
- PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
- }
- else {
- result = ftp_state_mdtm(conn);
- if(result)
- return result;
- }
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
+ else
+ result = ftp_state_mdtm(data);
}
break;
@@ -2984,33 +3009,36 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if((ftpcode/100 != 2) && !ftpc->count3--) {
/* failure to MKD the dir */
failf(data, "Failed to MKD dir: %03d", ftpcode);
- return CURLE_REMOTE_ACCESS_DENIED;
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ }
+ else {
+ state(data, FTP_CWD);
+ /* send CWD */
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
}
- state(conn, FTP_CWD);
- /* send CWD */
- PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
break;
case FTP_MDTM:
- result = ftp_state_mdtm_resp(conn, ftpcode);
+ result = ftp_state_mdtm_resp(data, ftpcode);
break;
case FTP_TYPE:
case FTP_LIST_TYPE:
case FTP_RETR_TYPE:
case FTP_STOR_TYPE:
- result = ftp_state_type_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_type_resp(data, ftpcode, ftpc->state);
break;
case FTP_SIZE:
case FTP_RETR_SIZE:
case FTP_STOR_SIZE:
- result = ftp_state_size_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_size_resp(data, ftpcode, ftpc->state);
break;
case FTP_REST:
case FTP_RETR_REST:
- result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_rest_resp(data, conn, ftpcode, ftpc->state);
break;
case FTP_PRET:
@@ -3019,31 +3047,31 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
failf(data, "PRET command not accepted: %03d", ftpcode);
return CURLE_FTP_PRET_FAILED;
}
- result = ftp_state_use_pasv(conn);
+ result = ftp_state_use_pasv(data, conn);
break;
case FTP_PASV:
- result = ftp_state_pasv_resp(conn, ftpcode);
+ result = ftp_state_pasv_resp(data, ftpcode);
break;
case FTP_PORT:
- result = ftp_state_port_resp(conn, ftpcode);
+ result = ftp_state_port_resp(data, ftpcode);
break;
case FTP_LIST:
case FTP_RETR:
- result = ftp_state_get_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_get_resp(data, ftpcode, ftpc->state);
break;
case FTP_STOR:
- result = ftp_state_stor_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_stor_resp(data, ftpcode, ftpc->state);
break;
case FTP_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
break;
}
} /* if(ftpcode) */
@@ -3053,11 +3081,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* called repeatedly until done from multi.c */
-static CURLcode ftp_multi_statemach(struct connectdata *conn,
+static CURLcode ftp_multi_statemach(struct Curl_easy *data,
bool *done)
{
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE);
+ CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE);
/* Check for the state outside of the Curl_socket_check() return code checks
since at times we are in fact already in this state when this function
@@ -3067,14 +3096,15 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
return result;
}
-static CURLcode ftp_block_statemach(struct connectdata *conn)
+static CURLcode ftp_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
CURLcode result = CURLE_OK;
while(ftpc->state != FTP_STOP) {
- result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */);
+ result = Curl_pp_statemach(data, pp, TRUE, TRUE /* disconnecting */);
if(result)
break;
}
@@ -3090,10 +3120,11 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
* phase is done when this function returns, or FALSE if not.
*
*/
-static CURLcode ftp_connect(struct connectdata *conn,
- bool *done) /* see description above */
+static CURLcode ftp_connect(struct Curl_easy *data,
+ bool *done) /* see description above */
{
CURLcode result;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -3102,25 +3133,24 @@ static CURLcode ftp_connect(struct connectdata *conn,
/* We always support persistent connections on ftp */
connkeep(conn, "FTP default");
- pp->response_time = RESP_TIMEOUT; /* set default response time-out */
- pp->statemach_act = ftp_statemach_act;
- pp->endofresp = ftp_endofresp;
- pp->conn = conn;
+ PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp);
if(conn->handler->flags & PROTOPT_SSL) {
/* BLOCKING */
- result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
if(result)
return result;
+ conn->bits.ftp_use_control_ssl = TRUE;
}
- Curl_pp_init(pp); /* init the generic pingpong data */
+ Curl_pp_setup(pp); /* once per transfer */
+ Curl_pp_init(data, pp); /* init the generic pingpong data */
/* When we connect, we start in the state where we await the 220
response */
- state(conn, FTP_WAIT220);
+ state(data, FTP_WAIT220);
- result = ftp_multi_statemach(conn, done);
+ result = ftp_multi_statemach(data, done);
return result;
}
@@ -3134,11 +3164,11 @@ static CURLcode ftp_connect(struct connectdata *conn,
*
* Input argument is already checked for validity.
*/
-static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
+static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
ssize_t nread;
@@ -3241,7 +3271,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
/* partial download completed */
- result = Curl_pp_sendf(pp, "%s", "ABOR");
+ result = Curl_pp_sendf(data, pp, "%s", "ABOR");
if(result) {
failf(data, "Failure sending ABOR command: %s",
curl_easy_strerror(result));
@@ -3253,12 +3283,12 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(conn->ssl[SECONDARYSOCKET].use) {
/* The secondary socket is using SSL so we must close down that part
first before we close the socket for real */
- Curl_ssl_close(conn, SECONDARYSOCKET);
+ Curl_ssl_close(data, conn, SECONDARYSOCKET);
/* Note that we keep "use" set to TRUE since that (next) connection is
still requested to use SSL */
}
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
}
if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
@@ -3274,7 +3304,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
pp->response_time = 60*1000; /* give it only a minute for now */
pp->response = Curl_now(); /* timeout relative now */
- result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ result = Curl_GetFTPResponse(data, &nread, &ftpcode);
pp->response_time = old_time; /* set this back to previous value */
@@ -3297,9 +3327,18 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(!ftpc->dont_check) {
/* 226 Transfer complete, 250 Requested file action okay, completed. */
- if((ftpcode != 226) && (ftpcode != 250)) {
+ switch(ftpcode) {
+ case 226:
+ case 250:
+ break;
+ case 552:
+ failf(data, "Exceeded storage allocation");
+ result = CURLE_REMOTE_DISK_FULL;
+ break;
+ default:
failf(data, "server did not report OK, got %d", ftpcode);
result = CURLE_PARTIAL_FILE;
+ break;
}
}
}
@@ -3349,7 +3388,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
/* Send any post-transfer QUOTE strings? */
if(!status && !result && !premature && data->set.postquote)
- result = ftp_sendquote(conn, data->set.postquote);
+ result = ftp_sendquote(data, conn, data->set.postquote);
Curl_safefree(ftp->pathalloc);
return result;
}
@@ -3365,20 +3404,21 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
*/
static
-CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
+CURLcode ftp_sendquote(struct Curl_easy *data,
+ struct connectdata *conn, struct curl_slist *quote)
{
struct curl_slist *item;
- ssize_t nread;
- int ftpcode;
- CURLcode result;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
item = quote;
while(item) {
if(item->data) {
+ ssize_t nread;
char *cmd = item->data;
bool acceptfail = FALSE;
+ CURLcode result;
+ int ftpcode = 0;
/* if a command starts with an asterisk, which a legal FTP command never
can, the command will be allowed to fail without it causing any
@@ -3390,16 +3430,16 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
acceptfail = TRUE;
}
- PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
-
- pp->response = Curl_now(); /* timeout relative now */
-
- result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
+ if(!result) {
+ pp->response = Curl_now(); /* timeout relative now */
+ result = Curl_GetFTPResponse(data, &nread, &ftpcode);
+ }
if(result)
return result;
if(!acceptfail && (ftpcode >= 400)) {
- failf(conn->data, "QUOT string not accepted: %s", cmd);
+ failf(data, "QUOT string not accepted: %s", cmd);
return CURLE_QUOTE_ERROR;
}
}
@@ -3430,7 +3470,8 @@ static int ftp_need_type(struct connectdata *conn,
* sets one of them.
* If the transfer type is not sent, simulate on OK response in newstate
*/
-static CURLcode ftp_nb_type(struct connectdata *conn,
+static CURLcode ftp_nb_type(struct Curl_easy *data,
+ struct connectdata *conn,
bool ascii, ftpstate newstate)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -3438,16 +3479,18 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
char want = (char)(ascii?'A':'I');
if(ftpc->transfertype == want) {
- state(conn, newstate);
- return ftp_state_type_resp(conn, 200, newstate);
+ state(data, newstate);
+ return ftp_state_type_resp(data, 200, newstate);
}
- PPSENDF(&ftpc->pp, "TYPE %c", want);
- state(conn, newstate);
+ result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
+ if(!result) {
+ state(data, newstate);
- /* keep track of our current transfer type */
- ftpc->transfertype = want;
- return CURLE_OK;
+ /* keep track of our current transfer type */
+ ftpc->transfertype = want;
+ }
+ return result;
}
/***************************************************************************
@@ -3461,14 +3504,14 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
*/
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void
-ftp_pasv_verbose(struct connectdata *conn,
+ftp_pasv_verbose(struct Curl_easy *data,
struct Curl_addrinfo *ai,
char *newhost, /* ascii version */
int port)
{
char buf[256];
Curl_printable_address(ai, buf, sizeof(buf));
- infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
+ infof(data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
}
#endif
@@ -3483,28 +3526,28 @@ ftp_pasv_verbose(struct connectdata *conn,
* EPSV).
*/
-static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
+static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
bool connected = FALSE;
bool complete = FALSE;
/* the ftp struct is inited in ftp_connect() */
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
/* if the second connection isn't done yet, wait for it */
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
if(Curl_connect_ongoing(conn)) {
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
aren't used so we blank their arguments. */
- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
+ result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0);
return result;
}
- result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
+ result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected);
/* Ready to do more? */
if(connected) {
@@ -3514,14 +3557,14 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(result && (ftpc->count1 == 0)) {
*completep = -1; /* go back to DOING please */
/* this is a EPSV connect failing, try PASV instead */
- return ftp_epsv_disable(conn);
+ return ftp_epsv_disable(data, conn);
}
return result;
}
}
#ifndef CURL_DISABLE_PROXY
- result = Curl_proxy_connect(conn, SECONDARYSOCKET);
+ result = Curl_proxy_connect(data, SECONDARYSOCKET);
if(result)
return result;
@@ -3536,7 +3579,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(ftpc->state) {
/* already in a state so skip the initial commands.
They are only done to kickstart the do_more state */
- result = ftp_multi_statemach(conn, &complete);
+ result = ftp_multi_statemach(data, &complete);
*completep = (int)complete;
@@ -3558,16 +3601,16 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(ftpc->wait_data_conn == TRUE) {
bool serv_conned;
- result = ReceivedServerConnect(conn, &serv_conned);
+ result = ReceivedServerConnect(data, &serv_conned);
if(result)
return result; /* Failed to accept data connection */
if(serv_conned) {
/* It looks data connection is established */
- result = AcceptServerConnect(conn);
+ result = AcceptServerConnect(data);
ftpc->wait_data_conn = FALSE;
if(!result)
- result = InitiateTransfer(conn);
+ result = InitiateTransfer(data);
if(result)
return result;
@@ -3577,11 +3620,11 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
}
}
else if(data->set.upload) {
- result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
+ result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE);
if(result)
return result;
- result = ftp_multi_statemach(conn, &complete);
+ result = ftp_multi_statemach(data, &complete);
/* ftpc->wait_data_conn is always false here */
*completep = (int)complete;
}
@@ -3589,7 +3632,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* download */
ftp->downloadsize = -1; /* unknown as of yet */
- result = Curl_range(conn);
+ result = Curl_range(data);
if(result == CURLE_OK && data->req.maxdownload >= 0) {
/* Don't check for successful transfer */
@@ -3605,19 +3648,20 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* But only if a body transfer was requested. */
if(ftp->transfer == FTPTRANSFER_BODY) {
- result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE);
+ result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE);
if(result)
return result;
}
/* otherwise just fall through */
}
else {
- result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
+ result = ftp_nb_type(data, conn, data->set.prefer_ascii,
+ FTP_RETR_TYPE);
if(result)
return result;
}
- result = ftp_multi_statemach(conn, &complete);
+ result = ftp_multi_statemach(data, &complete);
*completep = (int)complete;
}
return result;
@@ -3646,37 +3690,38 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
*/
static
-CURLcode ftp_perform(struct connectdata *conn,
+CURLcode ftp_perform(struct Curl_easy *data,
bool *connected, /* connect status after PASV / PORT */
bool *dophase_done)
{
/* this is FTP and no proxy */
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
- if(conn->data->set.opt_no_body) {
+ if(data->set.opt_no_body) {
/* requested no body means no transfer... */
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
ftp->transfer = FTPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- result = ftp_state_quote(conn, TRUE, FTP_QUOTE);
+ result = ftp_state_quote(data, TRUE, FTP_QUOTE);
if(result)
return result;
/* run the state-machine */
- result = ftp_multi_statemach(conn, dophase_done);
+ result = ftp_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[SECONDARYSOCKET];
- infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
+ infof(data, "ftp_perform ends with SECONDARY: %d\n", *connected);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete1\n"));
+ DEBUGF(infof(data, "DO phase is complete1\n"));
}
return result;
@@ -3690,12 +3735,12 @@ static void wc_data_dtor(void *ptr)
free(ftpwc);
}
-static CURLcode init_wc_data(struct connectdata *conn)
+static CURLcode init_wc_data(struct Curl_easy *data)
{
char *last_slash;
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
char *path = ftp->path;
- struct WildcardData *wildcard = &(conn->data->wildcard);
+ struct WildcardData *wildcard = &(data->wildcard);
CURLcode result = CURLE_OK;
struct ftp_wc *ftpwc = NULL;
@@ -3704,7 +3749,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
last_slash++;
if(last_slash[0] == '\0') {
wildcard->state = CURLWC_CLEAN;
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
return result;
}
wildcard->pattern = strdup(last_slash);
@@ -3721,7 +3766,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
}
else { /* only list */
wildcard->state = CURLWC_CLEAN;
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
return result;
}
}
@@ -3747,11 +3792,11 @@ static CURLcode init_wc_data(struct connectdata *conn)
wildcard->dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
- if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
- conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
+ if(data->set.ftp_filemethod == FTPFILE_NOCWD)
+ data->set.ftp_filemethod = FTPFILE_MULTICWD;
/* try to parse ftp url */
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
if(result) {
goto fail;
}
@@ -3763,15 +3808,15 @@ static CURLcode init_wc_data(struct connectdata *conn)
}
/* backup old write_function */
- ftpwc->backup.write_function = conn->data->set.fwrite_func;
+ ftpwc->backup.write_function = data->set.fwrite_func;
/* parsing write function */
- conn->data->set.fwrite_func = Curl_ftp_parselist;
+ data->set.fwrite_func = Curl_ftp_parselist;
/* backup old file descriptor */
- ftpwc->backup.file_descriptor = conn->data->set.out;
- /* let the writefunc callback know what curl pointer is working with */
- conn->data->set.out = conn;
+ ftpwc->backup.file_descriptor = data->set.out;
+ /* let the writefunc callback know the transfer */
+ data->set.out = data;
- infof(conn->data, "Wildcard - Parsing started\n");
+ infof(data, "Wildcard - Parsing started\n");
return CURLE_OK;
fail:
@@ -3785,129 +3830,132 @@ static CURLcode init_wc_data(struct connectdata *conn)
return result;
}
-/* This is called recursively */
-static CURLcode wc_statemach(struct connectdata *conn)
+static CURLcode wc_statemach(struct Curl_easy *data)
{
- struct WildcardData * const wildcard = &(conn->data->wildcard);
+ struct WildcardData * const wildcard = &(data->wildcard);
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
- switch(wildcard->state) {
- case CURLWC_INIT:
- result = init_wc_data(conn);
- if(wildcard->state == CURLWC_CLEAN)
- /* only listing! */
- break;
- wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
- break;
+ for(;;) {
+ switch(wildcard->state) {
+ case CURLWC_INIT:
+ result = init_wc_data(data);
+ if(wildcard->state == CURLWC_CLEAN)
+ /* only listing! */
+ return result;
+ wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
+ return result;
- case CURLWC_MATCHING: {
- /* In this state is LIST response successfully parsed, so lets restore
- previous WRITEFUNCTION callback and WRITEDATA pointer */
- struct ftp_wc *ftpwc = wildcard->protdata;
- conn->data->set.fwrite_func = ftpwc->backup.write_function;
- conn->data->set.out = ftpwc->backup.file_descriptor;
- ftpwc->backup.write_function = ZERO_NULL;
- ftpwc->backup.file_descriptor = NULL;
- wildcard->state = CURLWC_DOWNLOADING;
-
- if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
- /* error found in LIST parsing */
- wildcard->state = CURLWC_CLEAN;
- return wc_statemach(conn);
- }
- if(wildcard->filelist.size == 0) {
- /* no corresponding file */
- wildcard->state = CURLWC_CLEAN;
- return CURLE_REMOTE_FILE_NOT_FOUND;
+ case CURLWC_MATCHING: {
+ /* In this state is LIST response successfully parsed, so lets restore
+ previous WRITEFUNCTION callback and WRITEDATA pointer */
+ struct ftp_wc *ftpwc = wildcard->protdata;
+ data->set.fwrite_func = ftpwc->backup.write_function;
+ data->set.out = ftpwc->backup.file_descriptor;
+ ftpwc->backup.write_function = ZERO_NULL;
+ ftpwc->backup.file_descriptor = NULL;
+ wildcard->state = CURLWC_DOWNLOADING;
+
+ if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
+ /* error found in LIST parsing */
+ wildcard->state = CURLWC_CLEAN;
+ continue;
+ }
+ if(wildcard->filelist.size == 0) {
+ /* no corresponding file */
+ wildcard->state = CURLWC_CLEAN;
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
+ continue;
}
- return wc_statemach(conn);
- }
- case CURLWC_DOWNLOADING: {
- /* filelist has at least one file, lets get first one */
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
- struct FTP *ftp = conn->data->req.protop;
+ case CURLWC_DOWNLOADING: {
+ /* filelist has at least one file, lets get first one */
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
+ struct FTP *ftp = data->req.p.ftp;
- char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
- if(!tmp_path)
- return CURLE_OUT_OF_MEMORY;
+ char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
+ if(!tmp_path)
+ return CURLE_OUT_OF_MEMORY;
- /* switch default ftp->path and tmp_path */
- free(ftp->pathalloc);
- ftp->pathalloc = ftp->path = tmp_path;
-
- infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
- if(conn->data->set.chunk_bgn) {
- long userresponse;
- Curl_set_in_callback(conn->data, true);
- userresponse = conn->data->set.chunk_bgn(
- finfo, wildcard->customptr, (int)wildcard->filelist.size);
- Curl_set_in_callback(conn->data, false);
- switch(userresponse) {
- case CURL_CHUNK_BGN_FUNC_SKIP:
- infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
- finfo->filename);
- wildcard->state = CURLWC_SKIP;
- return wc_statemach(conn);
- case CURL_CHUNK_BGN_FUNC_FAIL:
- return CURLE_CHUNK_FAILED;
+ /* switch default ftp->path and tmp_path */
+ free(ftp->pathalloc);
+ ftp->pathalloc = ftp->path = tmp_path;
+
+ infof(data, "Wildcard - START of \"%s\"\n", finfo->filename);
+ if(data->set.chunk_bgn) {
+ long userresponse;
+ Curl_set_in_callback(data, true);
+ userresponse = data->set.chunk_bgn(
+ finfo, wildcard->customptr, (int)wildcard->filelist.size);
+ Curl_set_in_callback(data, false);
+ switch(userresponse) {
+ case CURL_CHUNK_BGN_FUNC_SKIP:
+ infof(data, "Wildcard - \"%s\" skipped by user\n",
+ finfo->filename);
+ wildcard->state = CURLWC_SKIP;
+ continue;
+ case CURL_CHUNK_BGN_FUNC_FAIL:
+ return CURLE_CHUNK_FAILED;
+ }
}
- }
- if(finfo->filetype != CURLFILETYPE_FILE) {
- wildcard->state = CURLWC_SKIP;
- return wc_statemach(conn);
- }
+ if(finfo->filetype != CURLFILETYPE_FILE) {
+ wildcard->state = CURLWC_SKIP;
+ continue;
+ }
- if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
- ftpc->known_filesize = finfo->size;
+ if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
+ ftpc->known_filesize = finfo->size;
- result = ftp_parse_url_path(conn);
- if(result)
- return result;
+ result = ftp_parse_url_path(data);
+ if(result)
+ return result;
- /* we don't need the Curl_fileinfo of first file anymore */
- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
+ /* we don't need the Curl_fileinfo of first file anymore */
+ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
- if(wildcard->filelist.size == 0) { /* remains only one file to down. */
- wildcard->state = CURLWC_CLEAN;
- /* after that will be ftp_do called once again and no transfer
- will be done because of CURLWC_CLEAN state */
- return CURLE_OK;
+ if(wildcard->filelist.size == 0) { /* remains only one file to down. */
+ wildcard->state = CURLWC_CLEAN;
+ /* after that will be ftp_do called once again and no transfer
+ will be done because of CURLWC_CLEAN state */
+ return CURLE_OK;
+ }
+ return result;
}
- } break;
- case CURLWC_SKIP: {
- if(conn->data->set.chunk_end) {
- Curl_set_in_callback(conn->data, true);
- conn->data->set.chunk_end(conn->data->wildcard.customptr);
- Curl_set_in_callback(conn->data, false);
+ case CURLWC_SKIP: {
+ if(data->set.chunk_end) {
+ Curl_set_in_callback(data, true);
+ data->set.chunk_end(data->wildcard.customptr);
+ Curl_set_in_callback(data, false);
+ }
+ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
+ wildcard->state = (wildcard->filelist.size == 0) ?
+ CURLWC_CLEAN : CURLWC_DOWNLOADING;
+ continue;
}
- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
- wildcard->state = (wildcard->filelist.size == 0) ?
- CURLWC_CLEAN : CURLWC_DOWNLOADING;
- return wc_statemach(conn);
- }
- case CURLWC_CLEAN: {
- struct ftp_wc *ftpwc = wildcard->protdata;
- result = CURLE_OK;
- if(ftpwc)
- result = Curl_ftp_parselist_geterror(ftpwc->parser);
+ case CURLWC_CLEAN: {
+ struct ftp_wc *ftpwc = wildcard->protdata;
+ result = CURLE_OK;
+ if(ftpwc)
+ result = Curl_ftp_parselist_geterror(ftpwc->parser);
- wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
- } break;
+ wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
+ return result;
+ }
- case CURLWC_DONE:
- case CURLWC_ERROR:
- case CURLWC_CLEAR:
- if(wildcard->dtor)
- wildcard->dtor(wildcard->protdata);
- break;
+ case CURLWC_DONE:
+ case CURLWC_ERROR:
+ case CURLWC_CLEAR:
+ if(wildcard->dtor)
+ wildcard->dtor(wildcard->protdata);
+ return result;
+ }
}
-
- return result;
+ /* UNREACHABLE */
}
/***********************************************************************
@@ -3919,18 +3967,19 @@ static CURLcode wc_statemach(struct connectdata *conn)
*
* The input argument is already checked for validity.
*/
-static CURLcode ftp_do(struct connectdata *conn, bool *done)
+static CURLcode ftp_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
*done = FALSE; /* default to false */
ftpc->wait_data_conn = FALSE; /* default to no such wait */
- if(conn->data->state.wildcardmatch) {
- result = wc_statemach(conn);
- if(conn->data->wildcard.state == CURLWC_SKIP ||
- conn->data->wildcard.state == CURLWC_DONE) {
+ if(data->state.wildcardmatch) {
+ result = wc_statemach(data);
+ if(data->wildcard.state == CURLWC_SKIP ||
+ data->wildcard.state == CURLWC_DONE) {
/* do not call ftp_regular_transfer */
return CURLE_OK;
}
@@ -3938,70 +3987,12 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
return result;
}
else { /* no wildcard FSM needed */
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
if(result)
return result;
}
- result = ftp_regular_transfer(conn, done);
-
- return result;
-}
-
-
-CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
-{
- ssize_t bytes_written;
-#define SBUF_SIZE 1024
- char s[SBUF_SIZE];
- size_t write_len;
- char *sptr = s;
- CURLcode result = CURLE_OK;
-#ifdef HAVE_GSSAPI
- enum protection_level data_sec = conn->data_prot;
-#endif
-
- if(!cmd)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- write_len = strlen(cmd);
- if(!write_len || write_len > (sizeof(s) -3))
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- memcpy(&s, cmd, write_len);
- strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
- write_len += 2;
- bytes_written = 0;
-
- result = Curl_convert_to_network(conn->data, s, write_len);
- /* Curl_convert_to_network calls failf if unsuccessful */
- if(result)
- return result;
-
- for(;;) {
-#ifdef HAVE_GSSAPI
- conn->data_prot = PROT_CMD;
-#endif
- result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
- &bytes_written);
-#ifdef HAVE_GSSAPI
- DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
- conn->data_prot = data_sec;
-#endif
-
- if(result)
- break;
-
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
-
- if(bytes_written != (ssize_t)write_len) {
- write_len -= bytes_written;
- sptr += bytes_written;
- }
- else
- break;
- }
+ result = ftp_regular_transfer(data, done);
return result;
}
@@ -4016,24 +4007,24 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
* connection.
*
*/
-static CURLcode ftp_quit(struct connectdata *conn)
+static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn)
{
CURLcode result = CURLE_OK;
if(conn->proto.ftpc.ctl_valid) {
- result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT");
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT");
if(result) {
- failf(conn->data, "Failure sending QUIT command: %s",
+ failf(data, "Failure sending QUIT command: %s",
curl_easy_strerror(result));
conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
connclose(conn, "QUIT command failed"); /* mark for connection closure */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return result;
}
- state(conn, FTP_QUIT);
+ state(data, FTP_QUIT);
- result = ftp_block_statemach(conn);
+ result = ftp_block_statemach(data, conn);
}
return result;
@@ -4046,7 +4037,9 @@ static CURLcode ftp_quit(struct connectdata *conn)
* Disconnect from an FTP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode ftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -4062,29 +4055,20 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
ftpc->ctl_valid = FALSE;
/* The FTP session may or may not have been allocated/setup at this point! */
- (void)ftp_quit(conn); /* ignore errors on the QUIT */
+ (void)ftp_quit(data, conn); /* ignore errors on the QUIT */
if(ftpc->entrypath) {
- struct Curl_easy *data = conn->data;
if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
data->state.most_recent_ftp_entrypath = NULL;
}
- free(ftpc->entrypath);
- ftpc->entrypath = NULL;
+ Curl_safefree(ftpc->entrypath);
}
freedirs(ftpc);
- free(ftpc->prevpath);
- ftpc->prevpath = NULL;
- free(ftpc->server_os);
- ftpc->server_os = NULL;
-
+ Curl_safefree(ftpc->prevpath);
+ Curl_safefree(ftpc->server_os);
Curl_pp_disconnect(pp);
-
-#ifdef HAVE_GSSAPI
Curl_sec_end(conn);
-#endif
-
return CURLE_OK;
}
@@ -4096,11 +4080,11 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
*
*/
static
-CURLcode ftp_parse_url_path(struct connectdata *conn)
+CURLcode ftp_parse_url_path(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
/* the ftp struct is already inited in ftp_connect() */
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
const char *slashPos = NULL;
const char *fileName = NULL;
@@ -4242,25 +4226,25 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
}
/* call this when the DO phase has completed */
-static CURLcode ftp_dophase_done(struct connectdata *conn,
- bool connected)
+static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
{
- struct FTP *ftp = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(connected) {
int completed;
- CURLcode result = ftp_do_more(conn, &completed);
+ CURLcode result = ftp_do_more(data, &completed);
if(result) {
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
return result;
}
}
if(ftp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
- Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
+ Curl_setup_transfer(data, -1, -1, FALSE, -1);
else if(!connected)
/* since we didn't connect now, we want do_more to get called */
conn->bits.do_more = TRUE;
@@ -4271,17 +4255,17 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
}
/* called from multi.c while DOing */
-static CURLcode ftp_doing(struct connectdata *conn,
+static CURLcode ftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = ftp_multi_statemach(conn, dophase_done);
+ CURLcode result = ftp_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = ftp_dophase_done(conn, FALSE /* not connected */);
+ result = ftp_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete2\n"));
+ DEBUGF(infof(data, "DO phase is complete2\n"));
}
return result;
}
@@ -4299,12 +4283,12 @@ static CURLcode ftp_doing(struct connectdata *conn,
* ftp_done() function without finding any major problem.
*/
static
-CURLcode ftp_regular_transfer(struct connectdata *conn,
+CURLcode ftp_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
data->req.size = -1; /* make sure this is unknown at this point */
@@ -4315,7 +4299,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
ftpc->ctl_valid = TRUE; /* starts good */
- result = ftp_perform(conn,
+ result = ftp_perform(data,
&connected, /* have we connected after PASV/PORT */
dophase_done); /* all commands in the DO-phase done? */
@@ -4325,7 +4309,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
/* the DO phase has not completed yet */
return CURLE_OK;
- result = ftp_dophase_done(conn, connected);
+ result = ftp_dophase_done(data, connected);
if(result)
return result;
@@ -4336,13 +4320,13 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
return result;
}
-static CURLcode ftp_setup_connection(struct connectdata *conn)
+static CURLcode ftp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
char *type;
struct FTP *ftp;
- conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1);
+ data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
if(NULL == ftp)
return CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index 06421c6a4..1cfdac085 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -31,8 +31,7 @@ extern const struct Curl_handler Curl_handler_ftp;
extern const struct Curl_handler Curl_handler_ftps;
#endif
-CURLcode Curl_ftpsend(struct connectdata *, const char *cmd);
-CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
+CURLcode Curl_GetFTPResponse(struct Curl_easy *data, ssize_t *nread,
int *ftpcode);
#endif /* CURL_DISABLE_FTP */
@@ -117,9 +116,9 @@ struct FTP {
struct ftp_conn {
struct pingpong pp;
char *entrypath; /* the PWD reply when we logged on */
+ char *file; /* url-decoded file name (or path) */
char **dirs; /* realloc()ed array for path components */
int dirdepth; /* number of entries used in the 'dirs' array */
- char *file; /* url-decoded file name (or path) */
bool dont_check; /* Set to TRUE to prevent the final (post-transfer)
file size and 226/250 status check. It should still
read the line, just ignore the result. */
@@ -132,6 +131,10 @@ struct ftp_conn {
bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
caching the current directory */
bool wait_data_conn; /* this is set TRUE if data connection is waited */
+ /* newhost is the (allocated) IP addr or host name to connect the data
+ connection to */
+ unsigned short newport;
+ char *newhost;
char *prevpath; /* url-decoded conn->path from the previous transfer */
char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
and others (A/I or zero) */
@@ -146,10 +149,6 @@ struct ftp_conn {
curl_off_t known_filesize; /* file size is different from -1, if wildcard
LIST parsing was done and wc_statemach set
it */
- /* newhost is the (allocated) IP addr or host name to connect the data
- connection to */
- char *newhost; /* this is the pair to connect the DATA... */
- unsigned short newport; /* connection to */
};
#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index f399a4c27..d3720b1f1 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -268,13 +268,13 @@ static int ftp_pl_get_permission(const char *str)
return permissions;
}
-static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
+static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
struct fileinfo *infop)
{
curl_fnmatch_callback compare;
- struct WildcardData *wc = &conn->data->wildcard;
+ struct WildcardData *wc = &data->wildcard;
struct ftp_wc *ftpwc = wc->protdata;
- struct curl_llist *llist = &wc->filelist;
+ struct Curl_llist *llist = &wc->filelist;
struct ftp_parselist_data *parser = ftpwc->parser;
bool add = TRUE;
struct curl_fileinfo *finfo = &infop->info;
@@ -293,13 +293,13 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
str + parser->offsets.user : NULL;
/* get correct fnmatch callback */
- compare = conn->data->set.fnmatch;
+ compare = data->set.fnmatch;
if(!compare)
compare = Curl_fnmatch;
/* filter pattern-corresponding filenames */
- Curl_set_in_callback(conn->data, true);
- if(compare(conn->data->set.fnmatch_data, wc->pattern,
+ Curl_set_in_callback(data, true);
+ if(compare(data->set.fnmatch_data, wc->pattern,
finfo->filename) == 0) {
/* discard symlink which is containing multiple " -> " */
if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
@@ -310,7 +310,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
else {
add = FALSE;
}
- Curl_set_in_callback(conn->data, false);
+ Curl_set_in_callback(data, false);
if(add) {
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
@@ -327,8 +327,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr)
{
size_t bufflen = size*nmemb;
- struct connectdata *conn = (struct connectdata *)connptr;
- struct ftp_wc *ftpwc = conn->data->wildcard.protdata;
+ struct Curl_easy *data = (struct Curl_easy *)connptr;
+ struct ftp_wc *ftpwc = data->wildcard.protdata;
struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop;
struct curl_fileinfo *finfo;
@@ -418,8 +418,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_length - 1] = 0;
if(strncmp("total ", finfo->b_data, 6) == 0) {
char *endptr = finfo->b_data + 6;
- /* here we can deal with directory size, pass the leading white
- spaces and then the digits */
+ /* here we can deal with directory size, pass the leading
+ whitespace and then the digits */
while(ISSPACE(*endptr))
endptr++;
while(ISDIGIT(*endptr))
@@ -728,7 +728,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -740,7 +740,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -835,7 +835,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
else if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -847,7 +847,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -967,7 +967,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
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(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -979,7 +979,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
case PL_WINNT_FILENAME_WINEOL:
if(c == '\n') {
parser->offsets.filename = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
diff --git a/Utilities/cmcurl/lib/ftplistparser.h b/Utilities/cmcurl/lib/ftplistparser.h
index b34ae9b63..e4cd8201d 100644
--- a/Utilities/cmcurl/lib/ftplistparser.h
+++ b/Utilities/cmcurl/lib/ftplistparser.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/getenv.c b/Utilities/cmcurl/lib/getenv.c
index 9385b8f67..92c53505c 100644
--- a/Utilities/cmcurl/lib/getenv.c
+++ b/Utilities/cmcurl/lib/getenv.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 82691dcc7..67ea07d2e 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -101,6 +101,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
if(!m) {
if(data->set.opt_no_body)
m = "HEAD";
+#ifndef CURL_DISABLE_HTTP
else {
switch(data->state.httpreq) {
case HTTPREQ_POST:
@@ -120,6 +121,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
break;
}
}
+#endif
}
*param_charp = m;
}
@@ -269,6 +271,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
/* Return the local port of the most recent (primary) connection */
*param_longp = data->info.conn_local_port;
break;
+ case CURLINFO_PROXY_ERROR:
+ *param_longp = (long)data->info.pxcode;
+ break;
case CURLINFO_CONDITION_UNMET:
if(data->info.httpcode == 304)
*param_longp = 1L;
diff --git a/Utilities/cmcurl/lib/getinfo.h b/Utilities/cmcurl/lib/getinfo.h
index 8d2af4266..f35d1b4b3 100644
--- a/Utilities/cmcurl/lib/getinfo.h
+++ b/Utilities/cmcurl/lib/getinfo.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/gopher.c b/Utilities/cmcurl/lib/gopher.c
index b4811b289..a39cc7e6b 100644
--- a/Utilities/cmcurl/lib/gopher.c
+++ b/Utilities/cmcurl/lib/gopher.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,6 +33,7 @@
#include "gopher.h"
#include "select.h"
#include "strdup.h"
+#include "vtls/vtls.h"
#include "url.h"
#include "escape.h"
#include "warnless.h"
@@ -45,7 +46,11 @@
* Forward declarations.
*/
-static CURLcode gopher_do(struct connectdata *conn, bool *done);
+static CURLcode gopher_do(struct Curl_easy *data, bool *done);
+#ifdef USE_SSL
+static CURLcode gopher_connect(struct Curl_easy *data, bool *done);
+static CURLcode gopher_connecting(struct Curl_easy *data, bool *done);
+#endif
/*
* Gopher protocol handler.
@@ -71,13 +76,55 @@ const struct Curl_handler Curl_handler_gopher = {
ZERO_NULL, /* connection_check */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHER, /* protocol */
+ CURLPROTO_GOPHER, /* family */
PROTOPT_NONE /* flags */
};
-static CURLcode gopher_do(struct connectdata *conn, bool *done)
+#ifdef USE_SSL
+const struct Curl_handler Curl_handler_gophers = {
+ "GOPHERS", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ gopher_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ gopher_connect, /* connect_it */
+ gopher_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ PORT_GOPHER, /* defport */
+ CURLPROTO_GOPHERS, /* protocol */
+ CURLPROTO_GOPHER, /* family */
+ PROTOPT_SSL /* flags */
+};
+
+static CURLcode gopher_connect(struct Curl_easy *data, bool *done)
+{
+ (void)data;
+ (void)done;
+ return CURLE_OK;
+}
+
+static CURLcode gopher_connecting(struct Curl_easy *data, bool *done)
+{
+ struct connectdata *conn = data->conn;
+ CURLcode result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
+ if(result)
+ connclose(conn, "Failed TLS connection");
+ *done = TRUE;
+ return result;
+}
+#endif
+
+static CURLcode gopher_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *gopherpath;
char *path = data->state.up.path;
@@ -123,14 +170,17 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
sel_org = sel;
}
- /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is
- sent, which could be sizeable with long selectors. */
k = curlx_uztosz(len);
for(;;) {
- result = Curl_write(conn, sockfd, sel, k, &amount);
+ /* Break out of the loop if the selector is empty because OpenSSL and/or
+ LibreSSL fail with errno 0 if this is the case. */
+ if(strlen(sel) < 1)
+ break;
+
+ result = Curl_write(data, sockfd, sel, k, &amount);
if(!result) { /* Which may not have written it all! */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
if(result)
break;
@@ -142,7 +192,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
else
break;
- timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
+ timeout_ms = Curl_timeleft(data, NULL, FALSE);
if(timeout_ms < 0) {
result = CURLE_OPERATION_TIMEDOUT;
break;
@@ -170,14 +220,12 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
free(sel_org);
if(!result)
- /* We can use Curl_sendf to send the terminal \r\n relatively safely and
- save allocing another string/doing another _write loop. */
- result = Curl_sendf(sockfd, conn, "\r\n");
+ result = Curl_write(data, sockfd, "\r\n", 2, &amount);
if(result) {
failf(data, "Failed sending Gopher request");
return result;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/gopher.h b/Utilities/cmcurl/lib/gopher.h
index dec2557fc..6b8bd554a 100644
--- a/Utilities/cmcurl/lib/gopher.h
+++ b/Utilities/cmcurl/lib/gopher.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -24,6 +24,9 @@
#ifndef CURL_DISABLE_GOPHER
extern const struct Curl_handler Curl_handler_gopher;
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_gophers;
+#endif
#endif
#endif /* HEADER_CURL_GOPHER_H */
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index 421d68f76..5d433ad1f 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -34,8 +34,8 @@
static void
hash_element_dtor(void *user, void *element)
{
- struct curl_hash *h = (struct curl_hash *) user;
- struct curl_hash_element *e = (struct curl_hash_element *) element;
+ struct Curl_hash *h = (struct Curl_hash *) user;
+ struct Curl_hash_element *e = (struct Curl_hash_element *) element;
if(e->ptr) {
h->dtor(e->ptr);
@@ -54,11 +54,11 @@ hash_element_dtor(void *user, void *element)
* @unittest: 1603
*/
int
-Curl_hash_init(struct curl_hash *h,
+Curl_hash_init(struct Curl_hash *h,
int slots,
hash_function hfunc,
comp_function comparator,
- curl_hash_dtor dtor)
+ Curl_hash_dtor dtor)
{
if(!slots || !hfunc || !comparator ||!dtor) {
return 1; /* failure */
@@ -70,22 +70,22 @@ Curl_hash_init(struct curl_hash *h,
h->size = 0;
h->slots = slots;
- h->table = malloc(slots * sizeof(struct curl_llist));
+ h->table = malloc(slots * sizeof(struct Curl_llist));
if(h->table) {
int i;
for(i = 0; i < slots; ++i)
- Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor);
+ Curl_llist_init(&h->table[i], (Curl_llist_dtor) hash_element_dtor);
return 0; /* fine */
}
h->slots = 0;
return 1; /* failure */
}
-static struct curl_hash_element *
+static struct Curl_hash_element *
mk_hash_element(const void *key, size_t key_len, const void *p)
{
/* allocate the struct plus memory after it to store the key */
- struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element) +
+ struct Curl_hash_element *he = malloc(sizeof(struct Curl_hash_element) +
key_len);
if(he) {
/* copy the key */
@@ -106,14 +106,14 @@ mk_hash_element(const void *key, size_t key_len, const void *p)
* @unittest: 1603
*/
void *
-Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
+Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
{
- struct curl_hash_element *he;
- struct curl_llist_element *le;
- struct curl_llist *l = FETCH_LIST(h, key, key_len);
+ struct Curl_hash_element *he;
+ struct Curl_llist_element *le;
+ struct Curl_llist *l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- he = (struct curl_hash_element *) le->ptr;
+ he = (struct Curl_hash_element *) le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *)h);
--h->size;
@@ -136,13 +136,13 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
*
* @unittest: 1603
*/
-int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
+int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len)
{
- struct curl_llist_element *le;
- struct curl_llist *l = FETCH_LIST(h, key, key_len);
+ struct Curl_llist_element *le;
+ struct Curl_llist *l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- struct curl_hash_element *he = le->ptr;
+ struct Curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
--h->size;
@@ -157,15 +157,15 @@ int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
* @unittest: 1603
*/
void *
-Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
+Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len)
{
- struct curl_llist_element *le;
- struct curl_llist *l;
+ struct Curl_llist_element *le;
+ struct Curl_llist *l;
if(h) {
l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- struct curl_hash_element *he = le->ptr;
+ struct Curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
return he->ptr;
}
@@ -175,19 +175,19 @@ Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
return NULL;
}
-#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST)
+#if defined(DEBUGBUILD) && defined(AGGRESSIVE_TEST)
void
-Curl_hash_apply(curl_hash *h, void *user,
+Curl_hash_apply(Curl_hash *h, void *user,
void (*cb)(void *user, void *ptr))
{
- struct curl_llist_element *le;
+ struct Curl_llist_element *le;
int i;
for(i = 0; i < h->slots; ++i) {
for(le = (h->table[i])->head;
le;
le = le->next) {
- curl_hash_element *el = le->ptr;
+ Curl_hash_element *el = le->ptr;
cb(user, el->ptr);
}
}
@@ -202,7 +202,7 @@ Curl_hash_apply(curl_hash *h, void *user,
* @unittest: 1603
*/
void
-Curl_hash_destroy(struct curl_hash *h)
+Curl_hash_destroy(struct Curl_hash *h)
{
int i;
@@ -220,19 +220,19 @@ Curl_hash_destroy(struct curl_hash *h)
* @unittest: 1602
*/
void
-Curl_hash_clean(struct curl_hash *h)
+Curl_hash_clean(struct Curl_hash *h)
{
Curl_hash_clean_with_criterium(h, NULL, NULL);
}
/* Cleans all entries that pass the comp function criteria. */
void
-Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
int (*comp)(void *, void *))
{
- struct curl_llist_element *le;
- struct curl_llist_element *lnext;
- struct curl_llist *list;
+ struct Curl_llist_element *le;
+ struct Curl_llist_element *lnext;
+ struct Curl_llist *list;
int i;
if(!h)
@@ -242,7 +242,7 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
list = &h->table[i];
le = list->head; /* get first list entry */
while(le) {
- struct curl_hash_element *he = le->ptr;
+ 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)) {
@@ -277,18 +277,18 @@ size_t Curl_str_key_compare(void *k1, size_t key1_len,
return 0;
}
-void Curl_hash_start_iterate(struct curl_hash *hash,
- struct curl_hash_iterator *iter)
+void Curl_hash_start_iterate(struct Curl_hash *hash,
+ struct Curl_hash_iterator *iter)
{
iter->hash = hash;
iter->slot_index = 0;
iter->current_element = NULL;
}
-struct curl_hash_element *
-Curl_hash_next_element(struct curl_hash_iterator *iter)
+struct Curl_hash_element *
+Curl_hash_next_element(struct Curl_hash_iterator *iter)
{
- struct curl_hash *h = iter->hash;
+ struct Curl_hash *h = iter->hash;
/* Get the next element in the current list, if any */
if(iter->current_element)
@@ -307,7 +307,7 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
}
if(iter->current_element) {
- struct curl_hash_element *he = iter->current_element->ptr;
+ struct Curl_hash_element *he = iter->current_element->ptr;
return he;
}
iter->current_element = NULL;
@@ -315,11 +315,11 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
}
#if 0 /* useful function for debugging hashes and their contents */
-void Curl_hash_print(struct curl_hash *h,
+void Curl_hash_print(struct Curl_hash *h,
void (*func)(void *))
{
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
int last_index = -1;
if(!h)
diff --git a/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h
index 558d0f47c..b7f828e07 100644
--- a/Utilities/cmcurl/lib/hash.h
+++ b/Utilities/cmcurl/lib/hash.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -41,59 +41,59 @@ typedef size_t (*comp_function) (void *key1,
void *key2,
size_t key2_len);
-typedef void (*curl_hash_dtor)(void *);
+typedef void (*Curl_hash_dtor)(void *);
-struct curl_hash {
- struct curl_llist *table;
+struct Curl_hash {
+ struct Curl_llist *table;
/* Hash function to be used for this hash table */
hash_function hash_func;
/* Comparator function to compare keys */
comp_function comp_func;
- curl_hash_dtor dtor;
+ Curl_hash_dtor dtor;
int slots;
size_t size;
};
-struct curl_hash_element {
- struct curl_llist_element list;
+struct Curl_hash_element {
+ struct Curl_llist_element list;
void *ptr;
size_t key_len;
char key[1]; /* allocated memory following the struct */
};
-struct curl_hash_iterator {
- struct curl_hash *hash;
+struct Curl_hash_iterator {
+ struct Curl_hash *hash;
int slot_index;
- struct curl_llist_element *current_element;
+ struct Curl_llist_element *current_element;
};
-int Curl_hash_init(struct curl_hash *h,
+int Curl_hash_init(struct Curl_hash *h,
int slots,
hash_function hfunc,
comp_function comparator,
- curl_hash_dtor dtor);
+ Curl_hash_dtor dtor);
-void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p);
-int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
-void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len);
-void Curl_hash_apply(struct curl_hash *h, void *user,
+void *Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p);
+int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len);
+void *Curl_hash_pick(struct Curl_hash *, void *key, size_t key_len);
+void Curl_hash_apply(struct Curl_hash *h, void *user,
void (*cb)(void *user, void *ptr));
#define Curl_hash_count(h) ((h)->size)
-void Curl_hash_destroy(struct curl_hash *h);
-void Curl_hash_clean(struct curl_hash *h);
-void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+void Curl_hash_destroy(struct Curl_hash *h);
+void Curl_hash_clean(struct Curl_hash *h);
+void Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
int (*comp)(void *, void *));
size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num);
size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2,
size_t key2_len);
-void Curl_hash_start_iterate(struct curl_hash *hash,
- struct curl_hash_iterator *iter);
-struct curl_hash_element *
-Curl_hash_next_element(struct curl_hash_iterator *iter);
+void Curl_hash_start_iterate(struct Curl_hash *hash,
+ struct Curl_hash_iterator *iter);
+struct Curl_hash_element *
+Curl_hash_next_element(struct Curl_hash_iterator *iter);
-void Curl_hash_print(struct curl_hash *h,
+void Curl_hash_print(struct Curl_hash *h,
void (*func)(void *));
diff --git a/Utilities/cmcurl/lib/hmac.c b/Utilities/cmcurl/lib/hmac.c
index e4fea8a50..590abe6d2 100644
--- a/Utilities/cmcurl/lib/hmac.c
+++ b/Utilities/cmcurl/lib/hmac.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/hostasyn.c b/Utilities/cmcurl/lib/hostasyn.c
index ed9190f4c..b25de1d41 100644
--- a/Utilities/cmcurl/lib/hostasyn.c
+++ b/Utilities/cmcurl/lib/hostasyn.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -66,25 +66,23 @@
*
* The storage operation locks and unlocks the DNS cache.
*/
-CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status,
struct Curl_addrinfo *ai)
{
struct Curl_dns_entry *dns = NULL;
CURLcode result = CURLE_OK;
- conn->async.status = status;
+ data->state.async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
if(ai) {
- struct Curl_easy *data = conn->data;
-
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
- conn->async.hostname,
- conn->async.port);
+ data->state.async.hostname,
+ data->state.async.port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -99,12 +97,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
}
}
- conn->async.dns = dns;
+ data->state.async.dns = dns;
/* Set async.done TRUE last in this function since it may be used multi-
threaded and once this is TRUE the other thread may read fields from the
async struct */
- conn->async.done = TRUE;
+ data->state.async.done = TRUE;
/* IPv4: The input hostent struct will be freed by ares when we return from
this function */
@@ -117,12 +115,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
- return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
+ return Curl_resolver_getaddrinfo(data, hostname, port, waitp);
}
#endif /* CURLRES_ASYNCH */
diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index 9e0db05fa..0fef98b2a 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/hostcheck.h b/Utilities/cmcurl/lib/hostcheck.h
index 9c180856a..52155f43b 100644
--- a/Utilities/cmcurl/lib/hostcheck.h
+++ b/Utilities/cmcurl/lib/hostcheck.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index dd5916e33..8ba3fe81c 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -206,7 +206,7 @@ hostcache_timestamp_remove(void *datap, void *hc)
* Prune the DNS cache. This assumes that a lock has already been taken.
*/
static void
-hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now)
+hostcache_prune(struct Curl_hash *hostcache, long cache_timeout, time_t now)
{
struct hostcache_prune_data user;
@@ -253,14 +253,12 @@ sigjmp_buf curl_jmpenv;
#endif
/* lookup address, returns entry if found and not stale */
-static struct Curl_dns_entry *
-fetch_addr(struct connectdata *conn,
- const char *hostname,
- int port)
+static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
+ const char *hostname,
+ int port)
{
struct Curl_dns_entry *dns = NULL;
size_t entry_len;
- struct Curl_easy *data = conn->data;
char entry_id[MAX_HOSTCACHE_LEN];
/* Create an entry id, based upon the hostname and port */
@@ -311,17 +309,16 @@ fetch_addr(struct connectdata *conn,
* use, or we'll leak memory!
*/
struct Curl_dns_entry *
-Curl_fetch_addr(struct connectdata *conn,
+Curl_fetch_addr(struct Curl_easy *data,
const char *hostname,
int port)
{
- struct Curl_easy *data = conn->data;
struct Curl_dns_entry *dns = NULL;
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
- dns = fetch_addr(conn, hostname, port);
+ dns = fetch_addr(data, hostname, port);
if(dns)
dns->inuse++; /* we use it! */
@@ -444,7 +441,7 @@ Curl_cache_addr(struct Curl_easy *data,
dns->addr = addr; /* this is the address(es) */
time(&dns->timestamp);
if(dns->timestamp == 0)
- dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */
+ dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
@@ -480,16 +477,16 @@ Curl_cache_addr(struct Curl_easy *data,
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
*/
-enum resolve_t Curl_resolv(struct connectdata *conn,
+enum resolve_t Curl_resolv(struct Curl_easy *data,
const char *hostname,
int port,
bool allowDOH,
struct Curl_dns_entry **entry)
{
struct Curl_dns_entry *dns = NULL;
- struct Curl_easy *data = conn->data;
CURLcode result;
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
+ struct connectdata *conn = data->conn;
*entry = NULL;
conn->bits.doh = FALSE; /* default is not */
@@ -497,7 +494,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
- dns = fetch_addr(conn, hostname, port);
+ dns = fetch_addr(data, hostname, port);
if(dns) {
infof(data, "Hostname %s was found in DNS cache\n", hostname);
@@ -523,7 +520,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(data->set.resolver_start) {
int st;
Curl_set_in_callback(data, true);
- st = data->set.resolver_start(data->state.resolver, NULL,
+ st = data->set.resolver_start(data->state.async.resolver, NULL,
data->set.resolver_start_client);
Curl_set_in_callback(data, false);
if(st)
@@ -565,17 +562,17 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(!addr) {
/* Check what IP specifics the app has requested and if we can provide
* it. If not, bail out. */
- if(!Curl_ipvalid(conn))
+ if(!Curl_ipvalid(data, conn))
return CURLRESOLV_ERROR;
if(allowDOH && data->set.doh && !ipnum) {
- addr = Curl_doh(conn, hostname, port, &respwait);
+ addr = Curl_doh(data, hostname, port, &respwait);
}
else {
/* 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(conn,
+ addr = Curl_getaddrinfo(data,
#ifdef DEBUGBUILD
(data->set.str[STRING_DEVICE]
&& !strcmp(data->set.str[STRING_DEVICE],
@@ -589,7 +586,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
/* the response to our resolve call will come asynchronously at
a later time, good or bad */
/* First, check that we haven't received the info by now */
- result = Curl_resolv_check(conn, &dns);
+ result = Curl_resolv_check(data, &dns);
if(result) /* error detected */
return CURLRESOLV_ERROR;
if(dns)
@@ -658,7 +655,7 @@ RETSIGTYPE alarmfunc(int sig)
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
*/
-enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
+enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
const char *hostname,
int port,
struct Curl_dns_entry **entry,
@@ -676,7 +673,6 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
#endif /* HAVE_SIGACTION */
volatile long timeout;
volatile unsigned int prev_alarm = 0;
- struct Curl_easy *data = conn->data;
#endif /* USE_ALARM_TIMEOUT */
enum resolve_t rc;
@@ -695,7 +691,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
if(!timeout)
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
- return Curl_resolv(conn, hostname, port, TRUE, entry);
+ return Curl_resolv(data, hostname, port, TRUE, entry);
if(timeout < 1000) {
/* The alarm() function only provides integer second resolution, so if
@@ -728,7 +724,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
keep_copysig = TRUE; /* yes, we have a copy */
sigact.sa_handler = alarmfunc;
#ifdef SA_RESTART
- /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
+ /* HPUX doesn't have SA_RESTART but defaults to that behavior! */
sigact.sa_flags &= ~SA_RESTART;
#endif
/* now set the new struct */
@@ -748,7 +744,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
#else
#ifndef CURLRES_ASYNCH
if(timeoutms)
- infof(conn->data, "timeout on name lookup is not supported\n");
+ infof(data, "timeout on name lookup is not supported\n");
#else
(void)timeoutms; /* timeoutms not used with an async resolver */
#endif
@@ -757,7 +753,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
/* Perform the actual name resolution. This might be interrupted by an
* alarm if it takes too long.
*/
- rc = Curl_resolv(conn, hostname, port, TRUE, entry);
+ rc = Curl_resolv(data, hostname, port, TRUE, entry);
#ifdef USE_ALARM_TIMEOUT
clean_up:
@@ -784,7 +780,7 @@ clean_up:
if(prev_alarm) {
/* there was an alarm() set before us, now put it back */
timediff_t elapsed_secs = Curl_timediff(Curl_now(),
- conn->created) / 1000;
+ data->conn->created) / 1000;
/* the alarm period is counted in even number of seconds */
unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);
@@ -843,7 +839,7 @@ static void freednsentry(void *freethis)
/*
* Curl_mk_dnscache() inits a new DNS cache and returns success/failure.
*/
-int Curl_mk_dnscache(struct curl_hash *hash)
+int Curl_mk_dnscache(struct Curl_hash *hash)
{
return Curl_hash_init(hash, 7, Curl_hash_str, Curl_str_key_compare,
freednsentry);
@@ -857,7 +853,7 @@ int Curl_mk_dnscache(struct curl_hash *hash)
*/
void Curl_hostcache_clean(struct Curl_easy *data,
- struct curl_hash *hash)
+ struct Curl_hash *hash)
{
if(data && data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@@ -916,17 +912,24 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
char *addr_end;
char *port_ptr;
char *end_ptr;
+ bool permanent = TRUE;
+ char *host_begin;
char *host_end;
unsigned long tmp_port;
bool error = true;
- host_end = strchr(hostp->data, ':');
+ host_begin = hostp->data;
+ if(host_begin[0] == '+') {
+ host_begin++;
+ permanent = FALSE;
+ }
+ host_end = strchr(host_begin, ':');
if(!host_end ||
- ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname)))
+ ((host_end - host_begin) >= (ptrdiff_t)sizeof(hostname)))
goto err;
- memcpy(hostname, hostp->data, host_end - hostp->data);
- hostname[host_end - hostp->data] = '\0';
+ memcpy(hostname, host_begin, host_end - host_begin);
+ hostname[host_end - host_begin] = '\0';
port_ptr = host_end + 1;
tmp_port = strtoul(port_ptr, &end_ptr, 10);
@@ -1008,18 +1011,22 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
- /* See if its already in our dns cache */
+ /* See if it's already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
hostname, port);
- /* delete old entry entry, there are two reasons for this
+ /* delete old entry, there are two reasons for this
1. old entry may have different addresses.
2. even if entry with correct addresses is already in the cache,
but if it is close to expire, then by the time next http
request is made, it can get expired and pruned because old
- entry is not necessarily marked as added by CURLOPT_RESOLVE. */
+ entry is not necessarily marked as permanent.
+ 3. when adding a non-permanent entry, we want it to remove and
+ replace an existing permanent entry.
+ 4. when adding a non-permanent entry, we want it to get a "fresh"
+ timeout that starts _now_. */
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
}
@@ -1027,10 +1034,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
/* put this new host in the cache */
dns = Curl_cache_addr(data, head, hostname, port);
if(dns) {
- dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
+ if(permanent)
+ dns->timestamp = 0; /* mark as permanent */
/* release the returned reference; the cache itself will keep the
* entry alive: */
- dns->inuse--;
+ dns->inuse--;
}
if(data->share)
@@ -1040,8 +1048,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
- infof(data, "Added %s:%d:%s to DNS cache\n",
- hostname, port, addresses);
+ infof(data, "Added %s:%d:%s to DNS cache%s\n",
+ hostname, port, addresses, permanent ? "" : " (non-permanent)");
/* Wildcard hostname */
if(hostname[0] == '*' && hostname[1] == '\0') {
@@ -1056,29 +1064,29 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
return CURLE_OK;
}
-CURLcode Curl_resolv_check(struct connectdata *conn,
+CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
(void)dns;
#endif
- if(conn->bits.doh)
- return Curl_doh_is_resolved(conn, dns);
- return Curl_resolver_is_resolved(conn, dns);
+ if(data->conn->bits.doh)
+ return Curl_doh_is_resolved(data, dns);
+ return Curl_resolver_is_resolved(data, dns);
}
-int Curl_resolv_getsock(struct connectdata *conn,
+int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
#ifdef CURLRES_ASYNCH
- if(conn->bits.doh)
+ if(data->conn->bits.doh)
/* nothing to wait for during DOH resolve, those handles have their own
sockets */
return GETSOCK_BLANK;
- return Curl_resolver_getsock(conn, socks);
+ return Curl_resolver_getsock(data, socks);
#else
- (void)conn;
+ (void)data;
(void)socks;
return GETSOCK_BLANK;
#endif
@@ -1089,21 +1097,19 @@ int Curl_resolv_getsock(struct connectdata *conn,
Note: this function disconnects and frees the conn data in case of
resolve failure */
-CURLcode Curl_once_resolved(struct connectdata *conn,
- bool *protocol_done)
+CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
- if(conn->async.dns) {
- conn->dns_entry = conn->async.dns;
- conn->async.dns = NULL;
+ if(data->state.async.dns) {
+ conn->dns_entry = data->state.async.dns;
+ data->state.async.dns = NULL;
}
- result = Curl_setup_conn(conn, protocol_done);
+ result = Curl_setup_conn(data, protocol_done);
if(result) {
- struct Curl_easy *data = conn->data;
- DEBUGASSERT(data);
Curl_detach_connnection(data);
Curl_conncache_remove_conn(data, conn, TRUE);
Curl_disconnect(data, conn, TRUE);
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 374b06c85..c495c21e0 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -59,13 +59,13 @@ struct connectdata;
* Global DNS cache is general badness. Do not use. This will be removed in
* a future version. Use the share interface instead!
*
- * Returns a struct curl_hash pointer on success, NULL on failure.
+ * Returns a struct Curl_hash pointer on success, NULL on failure.
*/
-struct curl_hash *Curl_global_host_cache_init(void);
+struct Curl_hash *Curl_global_host_cache_init(void);
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
- /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */
+ /* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (doesn't time out) */
time_t timestamp;
/* use-counter, use Curl_resolv_unlock to release reference */
long inuse;
@@ -85,12 +85,12 @@ enum resolve_t {
CURLRESOLV_RESOLVED = 0,
CURLRESOLV_PENDING = 1
};
-enum resolve_t Curl_resolv(struct connectdata *conn,
+enum resolve_t Curl_resolv(struct Curl_easy *data,
const char *hostname,
int port,
bool allowDOH,
struct Curl_dns_entry **dnsentry);
-enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
+enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
const char *hostname, int port,
struct Curl_dns_entry **dnsentry,
timediff_t timeoutms);
@@ -99,7 +99,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
-bool Curl_ipv6works(struct connectdata *conn);
+bool Curl_ipv6works(struct Curl_easy *data);
#else
#define Curl_ipv6works(x) FALSE
#endif
@@ -108,7 +108,7 @@ bool Curl_ipv6works(struct connectdata *conn);
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
-bool Curl_ipvalid(struct connectdata *conn);
+bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn);
/*
@@ -117,7 +117,7 @@ bool Curl_ipvalid(struct connectdata *conn);
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
@@ -128,7 +128,7 @@ void Curl_resolv_unlock(struct Curl_easy *data,
struct Curl_dns_entry *dns);
/* init a new dns cache and return success */
-int Curl_mk_dnscache(struct curl_hash *hash);
+int Curl_mk_dnscache(struct Curl_hash *hash);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct Curl_easy *data);
@@ -148,7 +148,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
/* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
-CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
+CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect);
/*
* Curl_addrinfo_callback() is used when we build with any asynch specialty.
@@ -156,7 +156,7 @@ CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
* status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
* request completed whether successful or failed.
*/
-CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status,
struct Curl_addrinfo *ai);
@@ -177,7 +177,7 @@ void Curl_printable_address(const struct Curl_addrinfo *ip,
* use, or we'll leak memory!
*/
struct Curl_dns_entry *
-Curl_fetch_addr(struct connectdata *conn,
+Curl_fetch_addr(struct Curl_easy *data,
const char *hostname,
int port);
@@ -234,16 +234,15 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
/*
* Clean off entries from the cache
*/
-void Curl_hostcache_clean(struct Curl_easy *data, struct curl_hash *hash);
+void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash);
/*
* Populate the cache with specified entries from CURLOPT_RESOLVE.
*/
CURLcode Curl_loadhostpairs(struct Curl_easy *data);
-
-CURLcode Curl_resolv_check(struct connectdata *conn,
+CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns);
-int Curl_resolv_getsock(struct connectdata *conn,
+int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks);
#endif /* HEADER_CURL_HOSTIP_H */
diff --git a/Utilities/cmcurl/lib/hostip4.c b/Utilities/cmcurl/lib/hostip4.c
index eae941674..d0754af22 100644
--- a/Utilities/cmcurl/lib/hostip4.c
+++ b/Utilities/cmcurl/lib/hostip4.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -61,8 +61,9 @@
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
-bool Curl_ipvalid(struct connectdata *conn)
+bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
{
+ (void)data;
if(conn->ip_version == CURL_IPRESOLVE_V6)
/* An IPv6 address was requested and we can't get/use one */
return FALSE;
@@ -88,7 +89,7 @@ bool Curl_ipvalid(struct connectdata *conn)
* flavours have thread-safe versions of the plain gethostbyname() etc.
*
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
@@ -96,14 +97,14 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct Curl_addrinfo *ai = NULL;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
- (void)conn;
+ (void)data;
#endif
*waitp = 0; /* synchronous response only */
ai = Curl_ipv4_resolve_r(hostname, port);
if(!ai)
- infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
+ infof(data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
return ai;
}
diff --git a/Utilities/cmcurl/lib/hostip6.c b/Utilities/cmcurl/lib/hostip6.c
index 11215758d..53b3c6722 100644
--- a/Utilities/cmcurl/lib/hostip6.c
+++ b/Utilities/cmcurl/lib/hostip6.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -62,16 +62,15 @@
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
-bool Curl_ipv6works(struct connectdata *conn)
+bool Curl_ipv6works(struct Curl_easy *data)
{
- if(conn) {
+ if(data) {
/* the nature of most system is that IPv6 status doesn't come and go
during a program's lifetime so we only probe the first time and then we
have the info kept for fast re-use */
- DEBUGASSERT(conn);
- DEBUGASSERT(conn->data);
- DEBUGASSERT(conn->data->multi);
- return conn->data->multi->ipv6_works;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->multi);
+ return data->multi->ipv6_works;
}
else {
int ipv6_works = -1;
@@ -82,7 +81,7 @@ bool Curl_ipv6works(struct connectdata *conn)
ipv6_works = 0;
else {
ipv6_works = 1;
- Curl_closesocket(NULL, s);
+ sclose(s);
}
return (ipv6_works>0)?TRUE:FALSE;
}
@@ -92,10 +91,10 @@ bool Curl_ipv6works(struct connectdata *conn)
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
-bool Curl_ipvalid(struct connectdata *conn)
+bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
{
if(conn->ip_version == CURL_IPRESOLVE_V6)
- return Curl_ipv6works(conn);
+ return Curl_ipv6works(data);
return TRUE;
}
@@ -128,7 +127,7 @@ static void dump_addrinfo(struct connectdata *conn,
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
@@ -142,14 +141,11 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char addrbuf[128];
#endif
int pf;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
- struct Curl_easy *data = conn->data;
-#endif
*waitp = 0; /* synchronous response only */
/* Check if a limited name resolve has been requested */
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
@@ -161,13 +157,13 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
break;
}
- if((pf != PF_INET) && !Curl_ipv6works(conn))
+ 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;
- hints.ai_socktype = (conn->transport == TRNSPRT_TCP) ?
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
SOCK_STREAM : SOCK_DGRAM;
#ifndef USE_RESOLVE_ON_IPS
diff --git a/Utilities/cmcurl/lib/hostsyn.c b/Utilities/cmcurl/lib/hostsyn.c
index 9e31008d2..550b43a08 100644
--- a/Utilities/cmcurl/lib/hostsyn.c
+++ b/Utilities/cmcurl/lib/hostsyn.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/hsts.c b/Utilities/cmcurl/lib/hsts.c
new file mode 100644
index 000000000..0e7c19cfb
--- /dev/null
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -0,0 +1,522 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * 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
+ * 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.
+ *
+ ***************************************************************************/
+/*
+ * The Strict-Transport-Security header is defined in RFC 6797:
+ * https://tools.ietf.org/html/rfc6797
+ */
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
+#include <curl/curl.h>
+#include "urldata.h"
+#include "llist.h"
+#include "hsts.h"
+#include "curl_get_line.h"
+#include "strcase.h"
+#include "sendf.h"
+#include "strtoofft.h"
+#include "parsedate.h"
+#include "rand.h"
+#include "rename.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#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"
+
+#ifdef DEBUGBUILD
+/* to play well with debug builds, we can *set* a fixed time this will
+ return */
+time_t deltatime; /* allow for "adjustments" for unit test purposes */
+static time_t debugtime(void *unused)
+{
+ char *timestr = getenv("CURL_TIME");
+ (void)unused;
+ if(timestr) {
+ unsigned long val = strtol(timestr, NULL, 10) + deltatime;
+ return (time_t)val;
+ }
+ return time(NULL);
+}
+#define time(x) debugtime(x)
+#endif
+
+struct hsts *Curl_hsts_init(void)
+{
+ struct hsts *h = calloc(sizeof(struct hsts), 1);
+ if(h) {
+ Curl_llist_init(&h->list, NULL);
+ }
+ return h;
+}
+
+static void hsts_free(struct stsentry *e)
+{
+ free((char *)e->host);
+ free(e);
+}
+
+void Curl_hsts_cleanup(struct hsts **hp)
+{
+ struct hsts *h = *hp;
+ if(h) {
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ n = e->next;
+ hsts_free(sts);
+ }
+ free(h->filename);
+ free(h);
+ *hp = NULL;
+ }
+}
+
+static struct stsentry *hsts_entry(void)
+{
+ return calloc(sizeof(struct stsentry), 1);
+}
+
+static CURLcode hsts_create(struct hsts *h,
+ const char *hostname,
+ bool subdomains,
+ curl_off_t expires)
+{
+ struct stsentry *sts = hsts_entry();
+ if(!sts)
+ return CURLE_OUT_OF_MEMORY;
+
+ sts->expires = expires;
+ sts->includeSubDomains = subdomains;
+ sts->host = strdup(hostname);
+ if(!sts->host) {
+ free(sts);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ Curl_llist_insert_next(&h->list, h->list.tail, sts, &sts->node);
+ return CURLE_OK;
+}
+
+CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
+ const char *header)
+{
+ const char *p = header;
+ curl_off_t expires = 0;
+ bool gotma = FALSE;
+ bool gotinc = FALSE;
+ bool subdomains = FALSE;
+ struct stsentry *sts;
+ time_t now = time(NULL);
+
+ do {
+ while(*p && ISSPACE(*p))
+ p++;
+ if(Curl_strncasecompare("max-age=", p, 8)) {
+ bool quoted = FALSE;
+ CURLofft offt;
+ char *endp;
+
+ if(gotma)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ p += 8;
+ while(*p && ISSPACE(*p))
+ p++;
+ if(*p == '\"') {
+ p++;
+ quoted = TRUE;
+ }
+ offt = curlx_strtoofft(p, &endp, 10, &expires);
+ if(offt == CURL_OFFT_FLOW)
+ expires = CURL_OFF_T_MAX;
+ else if(offt)
+ /* invalid max-age */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ p = endp;
+ if(quoted) {
+ if(*p != '\"')
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ p++;
+ }
+ gotma = TRUE;
+ }
+ else if(Curl_strncasecompare("includesubdomains", p, 17)) {
+ if(gotinc)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ subdomains = TRUE;
+ p += 17;
+ gotinc = TRUE;
+ }
+ else {
+ /* unknown directive, do a lame attempt to skip */
+ while(*p && (*p != ';'))
+ p++;
+ }
+
+ while(*p && ISSPACE(*p))
+ p++;
+ if(*p == ';')
+ p++;
+ } while (*p);
+
+ if(!gotma)
+ /* max-age is mandatory */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(!expires) {
+ /* remove the entry if present verbatim (without subdomain match) */
+ sts = Curl_hsts(h, hostname, FALSE);
+ if(sts) {
+ Curl_llist_remove(&h->list, &sts->node, NULL);
+ hsts_free(sts);
+ }
+ return CURLE_OK;
+ }
+
+ if(CURL_OFF_T_MAX - now < expires)
+ /* would overflow, use maximum value */
+ expires = CURL_OFF_T_MAX;
+ else
+ expires += now;
+
+ /* check if it already exists */
+ sts = Curl_hsts(h, hostname, FALSE);
+ if(sts) {
+ /* just update these fields */
+ sts->expires = expires;
+ sts->includeSubDomains = subdomains;
+ }
+ else
+ return hsts_create(h, hostname, subdomains, expires);
+
+ return CURLE_OK;
+}
+
+/*
+ * Return TRUE if the given host name is currently an HSTS one.
+ *
+ * The 'subdomain' argument tells the function if subdomain matching should be
+ * attempted.
+ */
+struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
+ bool subdomain)
+{
+ if(h) {
+ time_t now = time(NULL);
+ size_t hlen = strlen(hostname);
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ n = e->next;
+ if(sts->expires <= now) {
+ /* remove expired entries */
+ Curl_llist_remove(&h->list, &sts->node, NULL);
+ hsts_free(sts);
+ continue;
+ }
+ if(subdomain && sts->includeSubDomains) {
+ size_t ntail = strlen(sts->host);
+ if(ntail < hlen) {
+ size_t offs = hlen - ntail;
+ if((hostname[offs-1] == '.') &&
+ Curl_strncasecompare(&hostname[offs], sts->host, ntail))
+ return sts;
+ }
+ }
+ if(Curl_strcasecompare(hostname, sts->host))
+ return sts;
+ }
+ }
+ return NULL; /* no match */
+}
+
+/*
+ * Send this HSTS entry to the write callback.
+ */
+static CURLcode hsts_push(struct Curl_easy *data,
+ struct curl_index *i,
+ struct stsentry *sts,
+ bool *stop)
+{
+ struct curl_hstsentry e;
+ CURLSTScode sc;
+ struct tm stamp;
+ CURLcode result;
+
+ e.name = (char *)sts->host;
+ e.namelen = strlen(sts->host);
+ e.includeSubDomains = sts->includeSubDomains;
+
+ result = Curl_gmtime(sts->expires, &stamp);
+ if(result)
+ return result;
+
+ msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d",
+ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+
+ sc = data->set.hsts_write(data, &e, i,
+ data->set.hsts_write_userp);
+ *stop = (sc != CURLSTS_OK);
+ return sc == CURLSTS_FAIL ? CURLE_BAD_FUNCTION_ARGUMENT : CURLE_OK;
+}
+
+/*
+ * Write this single hsts entry to a single output line
+ */
+static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
+{
+ struct tm stamp;
+ CURLcode result = Curl_gmtime(sts->expires, &stamp);
+ if(result)
+ return result;
+
+ fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
+ sts->includeSubDomains ? ".": "", sts->host,
+ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+ return CURLE_OK;
+}
+
+
+/*
+ * Curl_https_save() writes the HSTS cache to file and callback.
+ */
+CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
+ const char *file)
+{
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ CURLcode result = CURLE_OK;
+ FILE *out;
+ char *tempstore;
+ unsigned char randsuffix[9];
+
+ if(!h)
+ /* no cache activated */
+ return CURLE_OK;
+
+ /* if no new name is given, use the one we stored from the load */
+ if(!file && h->filename)
+ file = h->filename;
+
+ if((h->flags & CURLHSTS_READONLYFILE) || !file || !file[0])
+ /* marked as read-only, no file or zero length file name */
+ goto skipsave;
+
+ if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
+ return CURLE_FAILED_INIT;
+
+ tempstore = aprintf("%s.%s.tmp", file, randsuffix);
+ if(!tempstore)
+ return CURLE_OUT_OF_MEMORY;
+
+ out = fopen(tempstore, FOPEN_WRITETEXT);
+ if(!out)
+ result = CURLE_WRITE_ERROR;
+ else {
+ fputs("# Your HSTS cache. https://curl.se/docs/hsts.html\n"
+ "# This file was generated by libcurl! Edit at your own risk.\n",
+ out);
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ n = e->next;
+ result = hsts_out(sts, out);
+ if(result)
+ break;
+ }
+ fclose(out);
+ if(!result && Curl_rename(tempstore, file))
+ result = CURLE_WRITE_ERROR;
+
+ if(result)
+ unlink(tempstore);
+ }
+ free(tempstore);
+ skipsave:
+ if(data->set.hsts_write) {
+ /* if there's a write callback */
+ struct curl_index i; /* count */
+ i.total = h->list.size;
+ i.index = 0;
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ bool stop;
+ n = e->next;
+ result = hsts_push(data, &i, sts, &stop);
+ if(result || stop)
+ break;
+ i.index++;
+ }
+ }
+ return result;
+}
+
+/* only returns SERIOUS errors */
+static CURLcode hsts_add(struct hsts *h, char *line)
+{
+ /* Example lines:
+ example.com "20191231 10:00:00"
+ .example.net "20191231 10:00:00"
+ */
+ char host[MAX_HSTS_HOSTLEN + 1];
+ char date[MAX_HSTS_DATELEN + 1];
+ int rc;
+
+ rc = sscanf(line,
+ "%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"",
+ host, date);
+ if(2 == rc) {
+ time_t expires = Curl_getdate_capped(date);
+ CURLcode result;
+ char *p = host;
+ bool subdomain = FALSE;
+ if(p[0] == '.') {
+ p++;
+ subdomain = TRUE;
+ }
+ result = hsts_create(h, p, subdomain, expires);
+ if(result)
+ return result;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Load HSTS data from callback.
+ *
+ */
+static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
+{
+ /* if the HSTS read callback is set, use it */
+ if(data->set.hsts_read) {
+ CURLSTScode sc;
+ DEBUGASSERT(h);
+ do {
+ char buffer[257];
+ struct curl_hstsentry e;
+ e.name = buffer;
+ e.namelen = sizeof(buffer)-1;
+ e.includeSubDomains = FALSE; /* default */
+ e.expire[0] = 0;
+ e.name[0] = 0; /* just to make it clean */
+ sc = data->set.hsts_read(data, &e, data->set.hsts_read_userp);
+ if(sc == CURLSTS_OK) {
+ time_t expires;
+ CURLcode result;
+ if(!e.name[0])
+ /* bail out if no name was stored */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(e.expire[0])
+ expires = Curl_getdate_capped(e.expire);
+ else
+ expires = TIME_T_MAX; /* the end of time */
+ result = hsts_create(h, e.name, e.includeSubDomains, expires);
+ if(result)
+ return result;
+ }
+ else if(sc == CURLSTS_FAIL)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ } while(sc == CURLSTS_OK);
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Load the HSTS cache from the given file. The text based line-oriented file
+ * format is documented here:
+ * https://github.com/curl/curl/wiki/HSTS
+ *
+ * This function only returns error on major problems that prevent hsts
+ * handling to work completely. It will ignore individual syntactical errors
+ * etc.
+ */
+static CURLcode hsts_load(struct hsts *h, const char *file)
+{
+ CURLcode result = CURLE_OK;
+ char *line = NULL;
+ FILE *fp;
+
+ /* we need a private copy of the file name so that the hsts cache file
+ name survives an easy handle reset */
+ free(h->filename);
+ h->filename = strdup(file);
+ if(!h->filename)
+ return CURLE_OUT_OF_MEMORY;
+
+ fp = fopen(file, FOPEN_READTEXT);
+ if(fp) {
+ line = malloc(MAX_HSTS_LINE);
+ if(!line)
+ goto fail;
+ while(Curl_get_line(line, MAX_HSTS_LINE, fp)) {
+ char *lineptr = line;
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
+ if(*lineptr == '#')
+ /* skip commented lines */
+ continue;
+
+ hsts_add(h, lineptr);
+ }
+ free(line); /* free the line buffer */
+ fclose(fp);
+ }
+ return result;
+
+ fail:
+ Curl_safefree(h->filename);
+ fclose(fp);
+ return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * Curl_hsts_loadfile() loads HSTS from file
+ */
+CURLcode Curl_hsts_loadfile(struct Curl_easy *data,
+ struct hsts *h, const char *file)
+{
+ DEBUGASSERT(h);
+ (void)data;
+ return hsts_load(h, file);
+}
+
+/*
+ * Curl_hsts_loadcb() loads HSTS from callback
+ */
+CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
+{
+ return hsts_pull(data, h);
+}
+
+#endif /* CURL_DISABLE_HTTP || USE_HSTS */
diff --git a/Utilities/cmcurl/lib/hsts.h b/Utilities/cmcurl/lib/hsts.h
new file mode 100644
index 000000000..ae5db74a2
--- /dev/null
+++ b/Utilities/cmcurl/lib/hsts.h
@@ -0,0 +1,65 @@
+#ifndef HEADER_CURL_HSTS_H
+#define HEADER_CURL_HSTS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020, 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"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
+#include <curl/curl.h>
+#include "llist.h"
+
+#ifdef DEBUGBUILD
+extern time_t deltatime;
+#endif
+
+struct stsentry {
+ struct Curl_llist_element node;
+ const char *host;
+ bool includeSubDomains;
+ time_t expires; /* the timestamp of this entry's expiry */
+};
+
+/* The HSTS cache. Needs to be able to tailmatch host names. */
+struct hsts {
+ struct Curl_llist list;
+ char *filename;
+ unsigned int flags;
+};
+
+struct hsts *Curl_hsts_init(void);
+void Curl_hsts_cleanup(struct hsts **hp);
+CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
+ const char *sts);
+struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
+ bool subdomain);
+CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
+ const char *file);
+CURLcode Curl_hsts_loadfile(struct Curl_easy *data,
+ struct hsts *h, const char *file);
+CURLcode Curl_hsts_loadcb(struct Curl_easy *data,
+ struct hsts *h);
+#else
+#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 /* HEADER_CURL_HSTS_H */
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 8fcdd436d..6f7f55d07 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -45,6 +45,10 @@
#include <sys/param.h>
#endif
+#ifdef USE_HYPER
+#include <hyper.h>
+#endif
+
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -60,6 +64,7 @@
#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
#include "http_negotiate.h"
+#include "http_aws_sigv4.h"
#include "url.h"
#include "share.h"
#include "hostip.h"
@@ -77,6 +82,8 @@
#include "connect.h"
#include "strdup.h"
#include "altsvc.h"
+#include "hsts.h"
+#include "c-hyper.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -87,22 +94,25 @@
* Forward declarations.
*/
-static int http_getsock_do(struct connectdata *conn,
+static int http_getsock_do(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks);
-static int http_should_fail(struct connectdata *conn);
+static bool http_should_fail(struct Curl_easy *data);
#ifndef CURL_DISABLE_PROXY
-static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
#endif
#ifdef USE_SSL
-static CURLcode https_connecting(struct connectdata *conn, bool *done);
-static int https_getsock(struct connectdata *conn,
+static CURLcode https_connecting(struct Curl_easy *data, bool *done);
+static int https_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks);
#else
#define https_connecting(x,y) CURLE_COULDNT_CONNECT
#endif
-static CURLcode http_setup_conn(struct connectdata *conn);
+static CURLcode http_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* HTTP handler interface.
@@ -125,6 +135,7 @@ const struct Curl_handler Curl_handler_http = {
ZERO_NULL, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_CREDSPERREQUEST | /* flags */
PROTOPT_USERPWDCTRL
};
@@ -151,25 +162,26 @@ const struct Curl_handler Curl_handler_https = {
ZERO_NULL, /* connection_check */
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
PROTOPT_USERPWDCTRL
};
#endif
-static CURLcode http_setup_conn(struct connectdata *conn)
+static CURLcode http_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
struct HTTP *http;
- struct Curl_easy *data = conn->data;
- DEBUGASSERT(data->req.protop == NULL);
+ DEBUGASSERT(data->req.p.http == NULL);
http = calloc(1, sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
- Curl_mime_initpart(&http->form, conn->data);
- data->req.protop = http;
+ Curl_mime_initpart(&http->form, data);
+ data->req.p.http = http;
if(data->set.httpversion == CURL_HTTP_VERSION_3) {
if(conn->handler->flags & PROTOPT_SSL)
@@ -196,16 +208,16 @@ static CURLcode http_setup_conn(struct connectdata *conn)
* if proxy headers are not available, then it will lookup into http header
* link list
*
- * It takes a connectdata struct as input instead of the Curl_easy simply to
- * know if this is a proxy request or not, as it then might check a different
- * header list. Provide the header prefix without colon!.
+ * It takes a connectdata struct as input to see if this is a proxy request or
+ * not, as it then might check a different header list. Provide the header
+ * prefix without colon!
*/
-char *Curl_checkProxyheaders(const struct connectdata *conn,
+char *Curl_checkProxyheaders(struct Curl_easy *data,
+ const struct connectdata *conn,
const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
- struct Curl_easy *data = conn->data;
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
@@ -219,7 +231,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
}
#else
/* disabled */
-#define Curl_checkProxyheaders(x,y) NULL
+#define Curl_checkProxyheaders(x,y,z) NULL
#endif
/*
@@ -282,11 +294,11 @@ char *Curl_copy_header_value(const char *header)
*
* Returns CURLcode.
*/
-static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
+static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
{
size_t size = 0;
char *authorization = NULL;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
char **userp;
const char *user;
const char *pwd;
@@ -342,16 +354,15 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
*
* Returns CURLcode.
*/
-static CURLcode http_output_bearer(struct connectdata *conn)
+static CURLcode http_output_bearer(struct Curl_easy *data)
{
char **userp;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
userp = &data->state.aptr.userpwd;
free(*userp);
*userp = aprintf("Authorization: Bearer %s\r\n",
- conn->data->set.str[STRING_BEARER]);
+ data->set.str[STRING_BEARER]);
if(!*userp) {
result = CURLE_OUT_OF_MEMORY;
@@ -390,6 +401,8 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
pick->picked = CURLAUTH_NTLM_WB;
else if(avail & CURLAUTH_BASIC)
pick->picked = CURLAUTH_BASIC;
+ else if(avail & CURLAUTH_AWS_SIGV4)
+ pick->picked = CURLAUTH_AWS_SIGV4;
else {
pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
picked = FALSE;
@@ -422,10 +435,10 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
* }
* }
*/
-static CURLcode http_perhapsrewind(struct connectdata *conn)
+static CURLcode http_perhapsrewind(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
curl_off_t bytessent;
curl_off_t expectsend = -1; /* default is unknown */
@@ -542,7 +555,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
if(bytessent)
/* we rewind now at once since if we already sent something */
- return Curl_readrewind(conn);
+ return Curl_readrewind(data);
return CURLE_OK;
}
@@ -554,9 +567,9 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
* picked.
*/
-CURLcode Curl_http_auth_act(struct connectdata *conn)
+CURLcode Curl_http_auth_act(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
bool pickhost = FALSE;
bool pickproxy = FALSE;
CURLcode result = CURLE_OK;
@@ -582,7 +595,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
conn->httpversion > 11) {
infof(data, "Forcing HTTP/1.1 for NTLM");
connclose(conn, "Force HTTP/1.1 connection");
- conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
+ data->set.httpversion = CURL_HTTP_VERSION_1_1;
}
}
#ifndef CURL_DISABLE_PROXY
@@ -600,7 +613,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
if((data->state.httpreq != HTTPREQ_GET) &&
(data->state.httpreq != HTTPREQ_HEAD) &&
!conn->bits.rewindaftersend) {
- result = http_perhapsrewind(conn);
+ result = http_perhapsrewind(data, conn);
if(result)
return result;
}
@@ -627,7 +640,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
data->state.authhost.done = TRUE;
}
}
- if(http_should_fail(conn)) {
+ if(http_should_fail(data)) {
failf(data, "The requested URL returned error: %d",
data->req.httpcode);
result = CURLE_HTTP_RETURNED_ERROR;
@@ -642,7 +655,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
* and whether or not it is to a proxy.
*/
static CURLcode
-output_auth_headers(struct connectdata *conn,
+output_auth_headers(struct Curl_easy *data,
+ struct connectdata *conn,
struct auth *authstatus,
const char *request,
const char *path,
@@ -650,17 +664,24 @@ output_auth_headers(struct connectdata *conn,
{
const char *auth = NULL;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
#ifdef CURL_DISABLE_CRYPTO_AUTH
(void)request;
(void)path;
#endif
-
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
+ auth = "AWS_SIGV4";
+ result = Curl_output_aws_sigv4(data, proxy);
+ if(result)
+ return result;
+ }
+ else
+#endif
#ifdef USE_SPNEGO
if(authstatus->picked == CURLAUTH_NEGOTIATE) {
auth = "Negotiate";
- result = Curl_output_negotiate(conn, proxy);
+ result = Curl_output_negotiate(data, conn, proxy);
if(result)
return result;
}
@@ -669,7 +690,7 @@ output_auth_headers(struct connectdata *conn,
#ifdef USE_NTLM
if(authstatus->picked == CURLAUTH_NTLM) {
auth = "NTLM";
- result = Curl_output_ntlm(conn, proxy);
+ result = Curl_output_ntlm(data, proxy);
if(result)
return result;
}
@@ -678,7 +699,7 @@ output_auth_headers(struct connectdata *conn,
#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
if(authstatus->picked == CURLAUTH_NTLM_WB) {
auth = "NTLM_WB";
- result = Curl_output_ntlm_wb(conn, proxy);
+ result = Curl_output_ntlm_wb(data, conn, proxy);
if(result)
return result;
}
@@ -687,7 +708,8 @@ output_auth_headers(struct connectdata *conn,
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(authstatus->picked == CURLAUTH_DIGEST) {
auth = "Digest";
- result = Curl_output_digest(conn,
+ result = Curl_output_digest(data,
+ conn,
proxy,
(const unsigned char *)request,
(const unsigned char *)path);
@@ -701,12 +723,12 @@ output_auth_headers(struct connectdata *conn,
if(
#ifndef CURL_DISABLE_PROXY
(proxy && conn->bits.proxy_user_passwd &&
- !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
+ !Curl_checkProxyheaders(data, conn, "Proxy-authorization")) ||
#endif
(!proxy && conn->bits.user_passwd &&
- !Curl_checkheaders(conn, "Authorization"))) {
+ !Curl_checkheaders(data, "Authorization"))) {
auth = "Basic";
- result = http_output_basic(conn, proxy);
+ result = http_output_basic(data, proxy);
if(result)
return result;
}
@@ -718,9 +740,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_BEARER) {
/* Bearer */
if((!proxy && data->set.str[STRING_BEARER] &&
- !Curl_checkheaders(conn, "Authorization:"))) {
+ !Curl_checkheaders(data, "Authorization:"))) {
auth = "Bearer";
- result = http_output_bearer(conn);
+ result = http_output_bearer(data);
if(result)
return result;
}
@@ -751,7 +773,7 @@ output_auth_headers(struct connectdata *conn,
/**
* Curl_http_output_auth() setups the authentication headers for the
* host/proxy and the correct authentication
- * method. conn->data->state.authdone is set to TRUE when authentication is
+ * method. data->state.authdone is set to TRUE when authentication is
* done.
*
* @param conn all information about the current connection
@@ -763,14 +785,15 @@ output_auth_headers(struct connectdata *conn,
* @returns CURLcode
*/
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) /* TRUE if this is the request setting
up the proxy tunnel */
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct auth *authhost;
struct auth *authproxy;
@@ -807,7 +830,7 @@ Curl_http_output_auth(struct connectdata *conn,
/* Send proxy authentication header if needed */
if(conn->bits.httpproxy &&
(conn->bits.tunnel_proxy == (bit)proxytunnel)) {
- result = output_auth_headers(conn, authproxy, request, path, TRUE);
+ result = output_auth_headers(data, conn, authproxy, request, path, TRUE);
if(result)
return result;
}
@@ -826,11 +849,22 @@ Curl_http_output_auth(struct connectdata *conn,
!data->state.first_host ||
data->set.allow_auth_to_other_hosts ||
strcasecompare(data->state.first_host, conn->host.name)) {
- result = output_auth_headers(conn, authhost, request, path, FALSE);
+ result = output_auth_headers(data, conn, authhost, request, path, FALSE);
}
else
authhost->done = TRUE;
+ if(((authhost->multipass && !authhost->done) ||
+ (authproxy->multipass && !authproxy->done)) &&
+ (httpreq != HTTPREQ_GET) &&
+ (httpreq != HTTPREQ_HEAD)) {
+ /* Auth is required and we are not authenticated yet. Make a PUT or POST
+ with content-length zero as a "probe". */
+ conn->bits.authneg = TRUE;
+ }
+ else
+ conn->bits.authneg = FALSE;
+
return result;
}
@@ -856,14 +890,13 @@ Curl_http_output_auth(struct connectdata *conn,
* proxy CONNECT loop.
*/
-CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth) /* the first non-space */
{
/*
* This resource requires authentication
*/
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
#ifdef USE_SPNEGO
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state;
@@ -871,6 +904,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
unsigned long *availp;
struct auth *authp;
+ (void) conn; /* In case conditionals make it unused. */
+
if(proxy) {
availp = &data->info.proxyauthavail;
authp = &data->state.authproxy;
@@ -905,7 +940,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
authp->avail |= CURLAUTH_NEGOTIATE;
if(authp->picked == CURLAUTH_NEGOTIATE) {
- CURLcode result = Curl_input_negotiate(conn, proxy, auth);
+ CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
if(!result) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url);
@@ -934,7 +969,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
if(authp->picked == CURLAUTH_NTLM ||
authp->picked == CURLAUTH_NTLM_WB) {
/* NTLM authentication is picked and activated */
- CURLcode result = Curl_input_ntlm(conn, proxy, auth);
+ CURLcode result = Curl_input_ntlm(data, proxy, auth);
if(!result) {
data->state.authproblem = FALSE;
#ifdef NTLM_WB_ENABLED
@@ -944,7 +979,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
*availp |= CURLAUTH_NTLM_WB;
authp->avail |= CURLAUTH_NTLM_WB;
- result = Curl_input_ntlm_wb(conn, proxy, auth);
+ result = Curl_input_ntlm_wb(data, conn, proxy, auth);
if(result) {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
@@ -975,7 +1010,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
* authentication isn't activated yet, as we need to store the
* incoming data from this header in case we are going to use
* Digest */
- result = Curl_input_digest(conn, proxy, auth);
+ result = Curl_input_digest(data, proxy, auth);
if(result) {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
@@ -1027,18 +1062,15 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
*
* @param conn all information about the current connection
*
- * @retval 0 communications should continue
+ * @retval FALSE communications should continue
*
- * @retval 1 communications should not continue
+ * @retval TRUE communications should not continue
*/
-static int http_should_fail(struct connectdata *conn)
+static bool http_should_fail(struct Curl_easy *data)
{
- struct Curl_easy *data;
int httpcode;
-
- DEBUGASSERT(conn);
- data = conn->data;
DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
httpcode = data->req.httpcode;
@@ -1047,20 +1079,20 @@ static int http_should_fail(struct connectdata *conn)
** don't fail.
*/
if(!data->set.http_fail_on_error)
- return 0;
+ return FALSE;
/*
** Any code < 400 is never terminal.
*/
if(httpcode < 400)
- return 0;
+ return FALSE;
/*
** Any code >= 400 that's not 401 or 407 is always
** a terminal error
*/
if((httpcode != 401) && (httpcode != 407))
- return 1;
+ return TRUE;
/*
** All we have left to deal with is 401 and 407
@@ -1085,16 +1117,17 @@ static int http_should_fail(struct connectdata *conn)
** Either we're not authenticating, or we're supposed to
** be authenticating something else. This is an error.
*/
- if((httpcode == 401) && !conn->bits.user_passwd)
+ if((httpcode == 401) && !data->conn->bits.user_passwd)
return TRUE;
#ifndef CURL_DISABLE_PROXY
- if((httpcode == 407) && !conn->bits.proxy_user_passwd)
+ if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
return TRUE;
#endif
return data->state.authproblem;
}
+#ifndef USE_HYPER
/*
* readmoredata() is a "fread() emulation" to provide POST and/or request
* data. It is used when a huge POST is to be made and the entire chunk wasn't
@@ -1108,8 +1141,8 @@ static size_t readmoredata(char *buffer,
size_t nitems,
void *userp)
{
- struct connectdata *conn = (struct connectdata *)userp;
- struct HTTP *http = conn->data->req.protop;
+ struct Curl_easy *data = (struct Curl_easy *)userp;
+ struct HTTP *http = data->req.p.http;
size_t fullsize = size * nitems;
if(!http->postsize)
@@ -1117,7 +1150,7 @@ static size_t readmoredata(char *buffer,
return 0;
/* make sure that a HTTP request is never sent away chunked! */
- conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
+ data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(http->postsize <= (curl_off_t)fullsize) {
memcpy(buffer, http->postdata, (size_t)http->postsize);
@@ -1127,8 +1160,8 @@ static size_t readmoredata(char *buffer,
/* move backup data into focus and continue on that */
http->postdata = http->backup.postdata;
http->postsize = http->backup.postsize;
- conn->data->state.fread_func = http->backup.fread_func;
- conn->data->state.in = http->backup.fread_in;
+ data->state.fread_func = http->backup.fread_func;
+ data->state.in = http->backup.fread_in;
http->sending++; /* move one step up */
@@ -1154,7 +1187,7 @@ static size_t readmoredata(char *buffer,
* Returns CURLcode
*/
CURLcode Curl_buffer_send(struct dynbuf *in,
- struct connectdata *conn,
+ struct Curl_easy *data,
/* add the number of sent bytes to this
counter */
curl_off_t *bytes_written,
@@ -1166,8 +1199,8 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
CURLcode result;
char *ptr;
size_t size;
- struct Curl_easy *data = conn->data;
- struct HTTP *http = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *http = data->req.p.http;
size_t sendsize;
curl_socket_t sockfd;
size_t headersize;
@@ -1226,7 +1259,9 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
}
else {
#ifdef CURLDEBUG
- /* Allow debug builds override this logic to force short initial sends */
+ /* Allow debug builds to override this logic to force short initial
+ sends
+ */
char *p = getenv("CURL_SMALLREQSEND");
if(p) {
size_t altsize = (size_t)strtoul(p, NULL, 10);
@@ -1240,7 +1275,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
sendsize = size;
}
- result = Curl_write(conn, sockfd, ptr, sendsize, &amount);
+ result = Curl_write(data, sockfd, ptr, sendsize, &amount);
if(!result) {
/*
@@ -1252,16 +1287,12 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
size_t bodylen = amount - headlen;
- if(data->set.verbose) {
- /* this data _may_ contain binary stuff */
- Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
- if(bodylen) {
- /* there was body data sent beyond the initial header part, pass that
- on to the debug callback too */
- Curl_debug(data, CURLINFO_DATA_OUT,
- ptr + headlen, bodylen);
- }
- }
+ /* this data _may_ contain binary stuff */
+ Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
+ if(bodylen)
+ /* there was body data sent beyond the initial header part, pass that on
+ to the debug callback too */
+ Curl_debug(data, CURLINFO_DATA_OUT, ptr + headlen, bodylen);
/* 'amount' can never be a very large value here so typecasting it so a
signed 31 bit value should not cause problems even if ssize_t is
@@ -1291,10 +1322,13 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
/* set the new pointers for the request-sending */
data->state.fread_func = (curl_read_callback)readmoredata;
- data->state.in = (void *)conn;
+ data->state.in = (void *)data;
http->postdata = ptr;
http->postsize = (curl_off_t)size;
+ /* this much data is remaining header: */
+ data->req.pendingheader = headersize - headlen;
+
http->send_buffer = *in; /* copy the whole struct */
http->sending = HTTPSEND_REQUEST;
@@ -1317,9 +1351,13 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
}
Curl_dyn_free(in);
+ /* no remaining header data */
+ data->req.pendingheader = 0;
return result;
}
+#endif
+
/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */
@@ -1353,7 +1391,7 @@ Curl_compareheader(const char *headerline, /* line to check */
/* pass the header */
start = &headerline[hlen];
- /* pass all white spaces */
+ /* pass all whitespace */
while(*start && ISSPACE(*start))
start++;
@@ -1384,9 +1422,10 @@ Curl_compareheader(const char *headerline, /* line to check */
* Curl_http_connect() performs HTTP stuff to do at connect-time, called from
* the generic Curl_connect().
*/
-CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
+CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
@@ -1394,7 +1433,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
#ifndef CURL_DISABLE_PROXY
/* the CONNECT procedure might not have been completed */
- result = Curl_proxy_connect(conn, FIRSTSOCKET);
+ result = Curl_proxy_connect(data, FIRSTSOCKET);
if(result)
return result;
@@ -1409,9 +1448,9 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
- if(conn->data->set.haproxyprotocol) {
+ if(data->set.haproxyprotocol) {
/* add HAProxy PROXY protocol header */
- result = add_haproxy_protocol_header(conn);
+ result = add_haproxy_protocol_header(data);
if(result)
return result;
}
@@ -1419,7 +1458,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
if(conn->given->protocol & CURLPROTO_HTTPS) {
/* perform SSL initialization */
- result = https_connecting(conn, done);
+ result = https_connecting(data, done);
if(result)
return result;
}
@@ -1432,24 +1471,27 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */
-static int http_getsock_do(struct connectdata *conn,
+static int http_getsock_do(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
/* write mode */
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
#ifndef CURL_DISABLE_PROXY
-static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
+static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
{
char proxy_header[128];
struct dynbuf req;
CURLcode result;
char tcp_version[5];
+ DEBUGASSERT(data->conn);
/* Emit the correct prefix for IPv6 */
- if(conn->bits.ipv6) {
+ if(data->conn->bits.ipv6) {
strcpy(tcp_version, "TCP6");
}
else {
@@ -1460,10 +1502,10 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
sizeof(proxy_header),
"PROXY %s %s %s %li %li\r\n",
tcp_version,
- conn->data->info.conn_local_ip,
- conn->data->info.conn_primary_ip,
- conn->data->info.conn_local_port,
- conn->data->info.conn_primary_port);
+ data->info.conn_local_ip,
+ data->info.conn_primary_ip,
+ data->info.conn_local_port,
+ data->info.conn_primary_port);
Curl_dyn_init(&req, DYN_HAXPROXY);
@@ -1471,7 +1513,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
if(result)
return result;
- result = Curl_buffer_send(&req, conn, &conn->data->info.request_size,
+ result = Curl_buffer_send(&req, data, &data->info.request_size,
0, FIRSTSOCKET);
return result;
@@ -1479,10 +1521,11 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
#endif
#ifdef USE_SSL
-static CURLcode https_connecting(struct connectdata *conn, bool *done)
+static CURLcode https_connecting(struct Curl_easy *data, bool *done)
{
CURLcode result;
- DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
+ struct connectdata *conn = data->conn;
+ DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC) {
@@ -1492,16 +1535,18 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
#endif
/* perform SSL initialization for this socket */
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
+ result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, done);
if(result)
connclose(conn, "Failed HTTPS connection");
return result;
}
-static int https_getsock(struct connectdata *conn,
+static int https_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
+ (void)data;
if(conn->handler->flags & PROTOPT_SSL)
return Curl_ssl_getsock(conn, socks);
return GETSOCK_BLANK;
@@ -1513,18 +1558,18 @@ static int https_getsock(struct connectdata *conn,
* performed.
*/
-CURLcode Curl_http_done(struct connectdata *conn,
+CURLcode Curl_http_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct Curl_easy *data = conn->data;
- struct HTTP *http = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *http = data->req.p.http;
/* Clear multipass flag. If authentication isn't done yet, then it will get
* a chance to be set back to true when we output the next auth header */
data->state.authhost.multipass = FALSE;
data->state.authproxy.multipass = FALSE;
- Curl_unencode_cleanup(conn);
+ Curl_unencode_cleanup(data);
/* set the proper values (possibly modified on POST) */
conn->seek_func = data->set.seek_func; /* restore */
@@ -1538,6 +1583,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
Curl_quic_done(data, premature);
Curl_mime_cleanpart(&http->form);
Curl_dyn_reset(&data->state.headerb);
+ Curl_hyper_done(data);
if(status)
return status;
@@ -1553,6 +1599,8 @@ CURLcode Curl_http_done(struct connectdata *conn,
read from the HTTP server (that counts), this can't be right so we
return an error here */
failf(data, "Empty reply from server");
+ /* Mark it as closed to avoid the "left intact" message */
+ streamclose(conn, "Empty reply from server");
return CURLE_GOT_NOTHING;
}
@@ -1580,6 +1628,7 @@ static bool use_http_1_1plus(const struct Curl_easy *data,
(data->set.httpversion >= CURL_HTTP_VERSION_1_1));
}
+#ifndef USE_HYPER
static const char *get_http_string(const struct Curl_easy *data,
const struct connectdata *conn)
{
@@ -1599,6 +1648,7 @@ static const char *get_http_string(const struct Curl_easy *data,
return "1.0";
}
+#endif
/* check and possibly add an Expect: header */
static CURLcode expect100(struct Curl_easy *data,
@@ -1613,7 +1663,7 @@ static CURLcode expect100(struct Curl_easy *data,
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
- const char *ptr = Curl_checkheaders(conn, "Expect");
+ const char *ptr = Curl_checkheaders(data, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -1679,15 +1729,20 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
return result;
}
-CURLcode Curl_add_custom_headers(struct connectdata *conn,
+CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect,
- struct dynbuf *req)
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *req
+#endif
+ )
{
+ struct connectdata *conn = data->conn;
char *ptr;
struct curl_slist *h[2];
struct curl_slist *headers;
int numlists = 1; /* by default */
- struct Curl_easy *data = conn->data;
int i;
#ifndef CURL_DISABLE_PROXY
@@ -1748,7 +1803,9 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
/* copy the source */
semicolonp = strdup(headers->data);
if(!semicolonp) {
+#ifndef USE_HYPER
Curl_dyn_free(req);
+#endif
return CURLE_OUT_OF_MEMORY;
}
/* put a colon where the semicolon is */
@@ -1809,7 +1866,11 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
+#ifdef USE_HYPER
+ result = Curl_hyper_header(data, req, compare);
+#else
result = Curl_dyn_addf(req, "%s\r\n", compare);
+#endif
}
if(semicolonp)
free(semicolonp);
@@ -1825,10 +1886,14 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
}
#ifndef CURL_DISABLE_PARSEDATE
-CURLcode Curl_add_timecondition(const struct connectdata *conn,
- struct dynbuf *req)
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *req
+#endif
+ )
{
- struct Curl_easy *data = conn->data;
const struct tm *tm;
struct tm keeptime;
CURLcode result;
@@ -1861,7 +1926,7 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
break;
}
- if(Curl_checkheaders(conn, condp)) {
+ if(Curl_checkheaders(data, condp)) {
/* A custom header was specified; it will be sent instead. */
return CURLE_OK;
}
@@ -1885,7 +1950,11 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
tm->tm_min,
tm->tm_sec);
+#ifndef USE_HYPER
result = Curl_dyn_add(req, datestr);
+#else
+ result = Curl_hyper_header(data, req, datestr);
+#endif
return result;
}
@@ -1900,102 +1969,14 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
}
#endif
-/*
- * Curl_http() gets called from the generic multi_do() function when a HTTP
- * request is to be performed. This creates and sends a properly constructed
- * HTTP request.
- */
-CURLcode Curl_http(struct connectdata *conn, bool *done)
+void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
+ const char **method, Curl_HttpReq *reqp)
{
- struct Curl_easy *data = conn->data;
- CURLcode result = CURLE_OK;
- struct HTTP *http;
- const char *path = data->state.up.path;
- const char *query = data->state.up.query;
- bool paste_ftp_userpwd = FALSE;
- char ftp_typecode[sizeof("/;type=?")] = "";
- const char *host = conn->host.name;
- const char *te = ""; /* transfer-encoding */
- const char *ptr;
- const char *request;
Curl_HttpReq httpreq = data->state.httpreq;
-#if !defined(CURL_DISABLE_COOKIES)
- char *addcookies = NULL;
-#endif
- curl_off_t included_body = 0;
- const char *httpstring;
- struct dynbuf req;
- curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
- char *altused = NULL;
-
- /* Always consider the DO phase done after this function call, even if there
- may be parts of the request that is not yet sent, since we can deal with
- the rest of the request in the PERFORM phase. */
- *done = TRUE;
-
- if(conn->transport != TRNSPRT_QUIC) {
- if(conn->httpversion < 20) { /* unless the connection is re-used and
- already http2 */
- switch(conn->negnpn) {
- case CURL_HTTP_VERSION_2:
- conn->httpversion = 20; /* we know we're on HTTP/2 now */
-
- result = Curl_http2_switched(conn, NULL, 0);
- if(result)
- return result;
- break;
- case CURL_HTTP_VERSION_1_1:
- /* continue with HTTP/1.1 when explicitly requested */
- break;
- default:
- /* Check if user wants to use HTTP/2 with clear TCP*/
-#ifdef USE_NGHTTP2
- if(conn->data->set.httpversion ==
- 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
- whether or not this setting should apply to HTTP/2 proxies. */
- infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
- break;
- }
-#endif
- DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
- conn->httpversion = 20;
-
- result = Curl_http2_switched(conn, NULL, 0);
- if(result)
- return result;
- }
-#endif
- break;
- }
- }
- else {
- /* prepare for a http2 request */
- result = Curl_http2_setup(conn);
- if(result)
- return result;
- }
- }
- http = data->req.protop;
- DEBUGASSERT(http);
-
- if(!data->state.this_is_a_follow) {
- /* Free to avoid leaking memory on multiple requests*/
- free(data->state.first_host);
-
- data->state.first_host = strdup(conn->host.name);
- if(!data->state.first_host)
- return CURLE_OUT_OF_MEMORY;
-
- data->state.first_remote_port = conn->remote_port;
- }
-
+ const char *request;
if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
- data->set.upload) {
+ data->set.upload)
httpreq = HTTPREQ_PUT;
- }
/* Now set the 'request' pointer to the proper request string */
if(data->set.str[STRING_CUSTOMREQUEST])
@@ -2004,7 +1985,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(data->set.opt_no_body)
request = "HEAD";
else {
- DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
+ DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD));
switch(httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
@@ -2024,180 +2005,40 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
}
+ *method = request;
+ *reqp = httpreq;
+}
+CURLcode Curl_http_useragent(struct Curl_easy *data)
+{
/* The User-Agent string might have been allocated in url.c already, because
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent")) {
+ if(Curl_checkheaders(data, "User-Agent")) {
free(data->state.aptr.uagent);
data->state.aptr.uagent = NULL;
}
+ return CURLE_OK;
+}
- /* setup the authentication headers */
- {
- char *pq = NULL;
- if(query && *query) {
- pq = aprintf("%s?%s", path, query);
- if(!pq)
- return CURLE_OUT_OF_MEMORY;
- }
- result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
- free(pq);
- if(result)
- return result;
- }
-
- if(((data->state.authhost.multipass && !data->state.authhost.done)
- || (data->state.authproxy.multipass && !data->state.authproxy.done)) &&
- (httpreq != HTTPREQ_GET) &&
- (httpreq != HTTPREQ_HEAD)) {
- /* Auth is required and we are not authenticated yet. Make a PUT or POST
- with content-length zero as a "probe". */
- conn->bits.authneg = TRUE;
- }
- else
- conn->bits.authneg = FALSE;
-
- Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
- data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
- if(!data->state.aptr.ref)
- return CURLE_OUT_OF_MEMORY;
- }
- else
- data->state.aptr.ref = NULL;
-
-#if !defined(CURL_DISABLE_COOKIES)
- if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
- addcookies = data->set.str[STRING_COOKIE];
-#endif
-
- if(!Curl_checkheaders(conn, "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;
- }
- 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 */
-
- if(!Curl_checkheaders(conn, "TE") &&
- data->set.http_transfer_encoding) {
- /* When we are to insert a TE: header in the request, we must also insert
- TE in a Connection: header, so we need to merge the custom provided
- Connection: header and prevent the original to get sent. Note that if
- the user has inserted his/hers own TE: header we don't do this magic
- but then assume that the user will handle it all! */
- char *cptr = Curl_checkheaders(conn, "Connection");
-#define TE_HEADER "TE: gzip\r\n"
-
- Curl_safefree(data->state.aptr.te);
-
- if(cptr) {
- cptr = Curl_copy_header_value(cptr);
- if(!cptr)
- return CURLE_OUT_OF_MEMORY;
- }
- /* Create the (updated) Connection: header */
- data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
- cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
+{
+ const char *ptr;
+ if(!data->state.this_is_a_follow) {
+ /* Free to avoid leaking memory on multiple requests*/
+ free(data->state.first_host);
- free(cptr);
- if(!data->state.aptr.te)
+ data->state.first_host = strdup(conn->host.name);
+ if(!data->state.first_host)
return CURLE_OUT_OF_MEMORY;
- }
-#endif
-
- switch(httpreq) {
- case HTTPREQ_POST_MIME:
- http->sendit = &data->set.mimepost;
- break;
- case HTTPREQ_POST_FORM:
- /* Convert the form structure into a mime structure. */
- Curl_mime_cleanpart(&http->form);
- result = Curl_getformdata(data, &http->form, data->set.httppost,
- data->state.fread_func);
- if(result)
- return result;
- http->sendit = &http->form;
- break;
- default:
- http->sendit = NULL;
- }
-
-#ifndef CURL_DISABLE_MIME
- if(http->sendit) {
- const char *cthdr = Curl_checkheaders(conn, "Content-Type");
-
- /* Read and seek body only. */
- http->sendit->flags |= MIME_BODY_ONLY;
-
- /* Prepare the mime structure headers & set content type. */
-
- if(cthdr)
- for(cthdr += 13; *cthdr == ' '; cthdr++)
- ;
- else if(http->sendit->kind == MIMEKIND_MULTIPART)
- cthdr = "multipart/form-data";
- curl_mime_headers(http->sendit, data->set.headers, 0);
- result = Curl_mime_prepare_headers(http->sendit, cthdr,
- NULL, MIMESTRATEGY_FORM);
- curl_mime_headers(http->sendit, NULL, 0);
- if(!result)
- result = Curl_mime_rewind(http->sendit);
- if(result)
- return result;
- http->postsize = Curl_mime_size(http->sendit);
- }
-#endif
-
- ptr = Curl_checkheaders(conn, "Transfer-Encoding");
- if(ptr) {
- /* Some kind of TE is requested, check if 'chunked' is chosen */
- data->req.upload_chunky =
- Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
- }
- else {
- if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
- (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
- http->postsize < 0) ||
- ((data->set.upload || httpreq == HTTPREQ_POST) &&
- data->state.infilesize == -1))) {
- if(conn->bits.authneg)
- /* don't enable chunked during auth neg */
- ;
- else if(use_http_1_1plus(data, conn)) {
- if(conn->httpversion < 20)
- /* HTTP, upload, unknown file size and not HTTP 1.0 */
- data->req.upload_chunky = TRUE;
- }
- else {
- failf(data, "Chunky upload is not supported by HTTP 1.0");
- return CURLE_UPLOAD_FAILED;
- }
- }
- else {
- /* else, no chunky upload */
- data->req.upload_chunky = FALSE;
- }
-
- if(data->req.upload_chunky)
- te = "Transfer-Encoding: chunked\r\n";
+ data->state.first_remote_port = conn->remote_port;
}
-
Curl_safefree(data->state.aptr.host);
- ptr = Curl_checkheaders(conn, "Host");
+ ptr = Curl_checkheaders(data, "Host");
if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
@@ -2247,6 +2088,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else {
/* When building Host: headers, we must put the host name within
[brackets] if the host name is a plain IPv6-address. RFC2732-style. */
+ const char *host = conn->host.name;
if(((conn->given->protocol&CURLPROTO_HTTPS) &&
(conn->remote_port == PORT_HTTPS)) ||
@@ -2269,6 +2111,24 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* without Host: we can't make a nice request */
return CURLE_OUT_OF_MEMORY;
}
+ return CURLE_OK;
+}
+
+/*
+ * Append the request-target to the HTTP request
+ */
+CURLcode Curl_http_target(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r)
+{
+ CURLcode result = CURLE_OK;
+ const char *path = data->state.up.path;
+ const char *query = data->state.up.query;
+
+ if(data->set.str[STRING_TARGET]) {
+ path = data->set.str[STRING_TARGET];
+ query = NULL;
+ }
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
@@ -2280,6 +2140,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* and no fragment part */
CURLUcode uc;
+ char *url;
CURLU *h = curl_url_dup(data->state.uh);
if(!h)
return CURLE_OUT_OF_MEMORY;
@@ -2313,7 +2174,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* 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, &data->set.str[STRING_TEMP_URL], 0);
+ uc = curl_url_get(h, CURLUPART_URL, &url, 0);
if(uc) {
curl_url_cleanup(h);
return CURLE_OUT_OF_MEMORY;
@@ -2321,6 +2182,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
curl_url_cleanup(h);
+ /* target or url */
+ result = Curl_dyn_add(r, data->set.str[STRING_TARGET]?
+ data->set.str[STRING_TARGET]:url);
+ free(url);
+ if(result)
+ return (result);
+
if(strcasecompare("ftp", data->state.up.scheme)) {
if(data->set.proxy_transfer_mode) {
/* when doing ftp, append ;type=<a|i> if not present */
@@ -2336,325 +2204,128 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
if(!type) {
- char *p = ftp_typecode;
- /* avoid sending invalid URLs like ftp://example.com;type=i if the
- * user specified ftp://example.com without the slash */
- if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
- *p++ = '/';
- }
- msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
- data->set.prefer_ascii ? 'a' : 'i');
- }
- }
- if(conn->bits.user_passwd)
- paste_ftp_userpwd = TRUE;
- }
- }
-#endif /* CURL_DISABLE_PROXY */
-
- http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";
-
- if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
- data->state.resume_from) {
- /**********************************************************************
- * Resuming upload in HTTP means that we PUT or POST and that we have
- * got a resume_from value set. The resume value has already created
- * a Range: header that will be passed along. We need to "fast forward"
- * the file the given number of bytes and decrease the assume upload
- * file size before we continue this venture in the dark lands of HTTP.
- * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
- *********************************************************************/
-
- if(data->state.resume_from < 0) {
- /*
- * This is meant to get the size of the present remote-file by itself.
- * We don't support this now. Bail out!
- */
- data->state.resume_from = 0;
- }
-
- if(data->state.resume_from && !data->state.this_is_a_follow) {
- /* do we still game? */
-
- /* Now, let's read off the proper amount of bytes from the
- input. */
- int seekerr = CURL_SEEKFUNC_CANTSEEK;
- if(conn->seek_func) {
- Curl_set_in_callback(data, true);
- seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
- SEEK_SET);
- Curl_set_in_callback(data, false);
- }
-
- if(seekerr != CURL_SEEKFUNC_OK) {
- curl_off_t passed = 0;
-
- if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
- failf(data, "Could not seek stream");
- return CURLE_READ_ERROR;
- }
- /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
- do {
- size_t readthisamountnow =
- (data->state.resume_from - passed > data->set.buffer_size) ?
- (size_t)data->set.buffer_size :
- curlx_sotouz(data->state.resume_from - passed);
-
- size_t actuallyread =
- data->state.fread_func(data->state.buffer, 1, readthisamountnow,
- data->state.in);
-
- passed += actuallyread;
- if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
- /* this checks for greater-than only to make sure that the
- CURL_READFUNC_ABORT return code still aborts */
- failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
- " bytes from the input", passed);
- return CURLE_READ_ERROR;
- }
- } while(passed < data->state.resume_from);
- }
-
- /* now, decrease the size of the read */
- if(data->state.infilesize>0) {
- data->state.infilesize -= data->state.resume_from;
-
- if(data->state.infilesize <= 0) {
- failf(data, "File already completely uploaded");
- return CURLE_PARTIAL_FILE;
+ result = Curl_dyn_addf(r, ";type=%c",
+ data->set.prefer_ascii ? 'a' : 'i');
+ if(result)
+ return result;
}
}
- /* we've passed, proceed as normal */
}
}
- if(data->state.use_range) {
- /*
- * A range is selected. We use different headers whether we're downloading
- * or uploading and we always let customized headers override our internal
- * ones if any such are specified.
- */
- if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
- !Curl_checkheaders(conn, "Range")) {
- /* if a line like this was already allocated, free the previous one */
- free(data->state.aptr.rangeline);
- data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
- data->state.range);
- }
- else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
- !Curl_checkheaders(conn, "Content-Range")) {
-
- /* if a line like this was already allocated, free the previous one */
- free(data->state.aptr.rangeline);
-
- if(data->set.set_resume_from < 0) {
- /* Upload resume was asked for, but we don't know the size of the
- remote part so we tell the server (and act accordingly) that we
- upload the whole file (again) */
- data->state.aptr.rangeline =
- aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
- "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
- data->state.infilesize - 1, data->state.infilesize);
- }
- else if(data->state.resume_from) {
- /* This is because "resume" was selected */
- curl_off_t total_expected_size =
- data->state.resume_from + data->state.infilesize;
- data->state.aptr.rangeline =
- aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
- "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
- data->state.range, total_expected_size-1,
- total_expected_size);
- }
- else {
- /* Range was selected and then we just pass the incoming range and
- append total size */
- data->state.aptr.rangeline =
- aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
- data->state.range, data->state.infilesize);
- }
- if(!data->state.aptr.rangeline)
- return CURLE_OUT_OF_MEMORY;
- }
- }
-
- httpstring = get_http_string(data, conn);
-
- /* initialize a dynamic send-buffer */
- Curl_dyn_init(&req, DYN_HTTP_REQUEST);
-
- /* add the main request stuff */
- /* GET/HEAD/POST/PUT */
- result = Curl_dyn_addf(&req, "%s ", request);
- if(result)
- return result;
-
- if(data->set.str[STRING_TARGET]) {
- path = data->set.str[STRING_TARGET];
- query = NULL;
- }
-
-#ifndef CURL_DISABLE_PROXY
- /* url */
- if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
- char *url = data->set.str[STRING_TEMP_URL];
- result = Curl_dyn_add(&req, url);
- Curl_safefree(data->set.str[STRING_TEMP_URL]);
- }
else
+#else
+ (void)conn; /* not used in disabled-proxy builds */
#endif
- if(paste_ftp_userpwd)
- result = Curl_dyn_addf(&req, "ftp://%s:%s@%s", conn->user, conn->passwd,
- path + sizeof("ftp://") - 1);
- else {
- result = Curl_dyn_add(&req, path);
+ {
+ result = Curl_dyn_add(r, path);
if(result)
return result;
if(query)
- result = Curl_dyn_addf(&req, "?%s", query);
+ result = Curl_dyn_addf(r, "?%s", query);
}
- if(result)
- return result;
-
-#ifdef USE_ALTSVC
- if(conn->bits.altused && !Curl_checkheaders(conn, "Alt-Used")) {
- altused = aprintf("Alt-Used: %s:%d\r\n",
- conn->conn_to_host.name, conn->conn_to_port);
- if(!altused) {
- Curl_dyn_free(&req);
- return CURLE_OUT_OF_MEMORY;
- }
- }
-#endif
- result =
- Curl_dyn_addf(&req,
- "%s" /* ftp typecode (;type=x) */
- " HTTP/%s\r\n" /* HTTP version */
- "%s" /* host */
- "%s" /* proxyuserpwd */
- "%s" /* userpwd */
- "%s" /* range */
- "%s" /* user agent */
- "%s" /* accept */
- "%s" /* TE: */
- "%s" /* accept-encoding */
- "%s" /* referer */
- "%s" /* Proxy-Connection */
- "%s" /* transfer-encoding */
- "%s",/* Alt-Used */
- ftp_typecode,
- httpstring,
- (data->state.aptr.host?data->state.aptr.host:""),
- data->state.aptr.proxyuserpwd?
- data->state.aptr.proxyuserpwd:"",
- data->state.aptr.userpwd?data->state.aptr.userpwd:"",
- (data->state.use_range && data->state.aptr.rangeline)?
- data->state.aptr.rangeline:"",
- (data->set.str[STRING_USERAGENT] &&
- *data->set.str[STRING_USERAGENT] &&
- data->state.aptr.uagent)?
- data->state.aptr.uagent:"",
- http->p_accept?http->p_accept:"",
- data->state.aptr.te?data->state.aptr.te:"",
- (data->set.str[STRING_ENCODING] &&
- *data->set.str[STRING_ENCODING] &&
- data->state.aptr.accept_encoding)?
- data->state.aptr.accept_encoding:"",
- (data->change.referer && data->state.aptr.ref)?
- data->state.aptr.ref:"" /* Referer: <data> */,
-#ifndef CURL_DISABLE_PROXY
- (conn->bits.httpproxy &&
- !conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
- "Proxy-Connection: Keep-Alive\r\n":"",
-#else
- "",
-#endif
- te,
- altused ? altused : ""
- );
-
- /* clear userpwd and proxyuserpwd to avoid re-using old credentials
- * from re-used connections */
- Curl_safefree(data->state.aptr.userpwd);
- Curl_safefree(data->state.aptr.proxyuserpwd);
- free(altused);
+ return result;
+}
- if(result)
- return result;
+CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
+ Curl_HttpReq httpreq, const char **tep)
+{
+ CURLcode result = CURLE_OK;
+ const char *ptr;
+ struct HTTP *http = data->req.p.http;
+ http->postsize = 0;
- if(!(conn->handler->flags&PROTOPT_SSL) &&
- conn->httpversion != 20 &&
- (data->set.httpversion == 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);
+ switch(httpreq) {
+ case HTTPREQ_POST_MIME:
+ http->sendit = &data->set.mimepost;
+ break;
+ case HTTPREQ_POST_FORM:
+ /* Convert the form structure into a mime structure. */
+ Curl_mime_cleanpart(&http->form);
+ result = Curl_getformdata(data, &http->form, data->set.httppost,
+ data->state.fread_func);
if(result)
return result;
+ http->sendit = &http->form;
+ break;
+ default:
+ http->sendit = NULL;
}
-#if !defined(CURL_DISABLE_COOKIES)
- if(data->cookies || addcookies) {
- struct Cookie *co = NULL; /* no cookies from start */
- int count = 0;
+#ifndef CURL_DISABLE_MIME
+ if(http->sendit) {
+ const char *cthdr = Curl_checkheaders(data, "Content-Type");
- if(data->cookies && data->state.cookie_engine) {
- Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- co = Curl_cookie_getlist(data->cookies,
- data->state.aptr.cookiehost?
- data->state.aptr.cookiehost:host,
- data->state.up.path,
- (conn->handler->protocol&CURLPROTO_HTTPS)?
- TRUE:FALSE);
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- }
- if(co) {
- struct Cookie *store = co;
- /* now loop through all cookies that matched */
- while(co) {
- if(co->value) {
- if(0 == count) {
- result = Curl_dyn_add(&req, "Cookie: ");
- if(result)
- break;
- }
- result = Curl_dyn_addf(&req, "%s%s=%s", count?"; ":"",
- co->name, co->value);
- if(result)
- break;
- count++;
- }
- co = co->next; /* next cookie please */
- }
- Curl_cookie_freelist(store);
- }
- if(addcookies && !result) {
- if(!count)
- result = Curl_dyn_add(&req, "Cookie: ");
- if(!result) {
- result = Curl_dyn_addf(&req, "%s%s", count?"; ":"", addcookies);
- count++;
- }
- }
- if(count && !result)
- result = Curl_dyn_add(&req, "\r\n");
+ /* Read and seek body only. */
+ http->sendit->flags |= MIME_BODY_ONLY;
+
+ /* Prepare the mime structure headers & set content type. */
+ if(cthdr)
+ for(cthdr += 13; *cthdr == ' '; cthdr++)
+ ;
+ else if(http->sendit->kind == MIMEKIND_MULTIPART)
+ cthdr = "multipart/form-data";
+
+ curl_mime_headers(http->sendit, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(http->sendit, cthdr,
+ NULL, MIMESTRATEGY_FORM);
+ curl_mime_headers(http->sendit, NULL, 0);
+ if(!result)
+ result = Curl_mime_rewind(http->sendit);
if(result)
return result;
+ http->postsize = Curl_mime_size(http->sendit);
}
#endif
- result = Curl_add_timecondition(conn, &req);
- if(result)
- return result;
+ ptr = Curl_checkheaders(data, "Transfer-Encoding");
+ if(ptr) {
+ /* Some kind of TE is requested, check if 'chunked' is chosen */
+ data->req.upload_chunky =
+ Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
+ }
+ else {
+ if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
+ http->postsize < 0) ||
+ ((data->set.upload || httpreq == HTTPREQ_POST) &&
+ data->state.infilesize == -1))) {
+ if(conn->bits.authneg)
+ /* don't enable chunked during auth neg */
+ ;
+ else if(use_http_1_1plus(data, conn)) {
+ if(conn->httpversion < 20)
+ /* HTTP, upload, unknown file size and not HTTP 1.0 */
+ data->req.upload_chunky = TRUE;
+ }
+ else {
+ failf(data, "Chunky upload is not supported by HTTP 1.0");
+ return CURLE_UPLOAD_FAILED;
+ }
+ }
+ else {
+ /* else, no chunky upload */
+ data->req.upload_chunky = FALSE;
+ }
- result = Curl_add_custom_headers(conn, FALSE, &req);
- if(result)
- return result;
+ if(data->req.upload_chunky)
+ *tep = "Transfer-Encoding: chunked\r\n";
+ }
+ return result;
+}
- http->postdata = NULL; /* nothing to post at this point */
- Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */
+CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *r, Curl_HttpReq httpreq)
+{
+#ifndef USE_HYPER
+ /* Hyper always handles the body separately */
+ curl_off_t included_body = 0;
+#endif
+ CURLcode result = CURLE_OK;
+ struct HTTP *http = data->req.p.http;
+ const char *ptr;
/* If 'authdone' is FALSE, we must not set the write socket index to the
Curl_transfer() call below, as we're not ready to actually upload any
@@ -2665,42 +2336,42 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
if(conn->bits.authneg)
- postsize = 0;
+ http->postsize = 0;
else
- postsize = data->state.infilesize;
+ http->postsize = data->state.infilesize;
- if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
+ if((http->postsize != -1) && !data->req.upload_chunky &&
+ (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */
- result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
- "\r\n", postsize);
+ result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", http->postsize);
if(result)
return result;
}
- if(postsize != 0) {
- result = expect100(data, conn, &req);
+ if(http->postsize) {
+ result = expect100(data, conn, r);
if(result)
return result;
}
/* end of headers */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
/* set the upload size to the progress meter */
- Curl_pgrsSetUploadSize(data, postsize);
+ Curl_pgrsSetUploadSize(data, http->postsize);
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending PUT request");
else
/* prepare for transfer */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
- postsize?FIRSTSOCKET:-1);
+ http->postsize?FIRSTSOCKET:-1);
if(result)
return result;
break;
@@ -2710,11 +2381,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* This is form posting using mime data. */
if(conn->bits.authneg) {
/* nothing to post! */
- result = Curl_dyn_add(&req, "Content-Length: 0\r\n\r\n");
+ result = Curl_dyn_add(r, "Content-Length: 0\r\n\r\n");
if(result)
return result;
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
@@ -2724,18 +2395,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break;
}
- data->state.infilesize = postsize = http->postsize;
+ data->state.infilesize = http->postsize;
/* We only set Content-Length and allow a custom Content-Length if
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
- if(postsize != -1 && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
+ if(http->postsize != -1 && !data->req.upload_chunky &&
+ (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
- result = Curl_dyn_addf(&req,
+ result = Curl_dyn_addf(r,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
- "\r\n", postsize);
+ "\r\n", http->postsize);
if(result)
return result;
}
@@ -2746,7 +2417,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
struct curl_slist *hdr;
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
- result = Curl_dyn_addf(&req, "%s\r\n", hdr->data);
+ result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
if(result)
return result;
}
@@ -2757,13 +2428,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect");
+ ptr = Curl_checkheaders(data, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
}
- else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
- result = expect100(data, conn, &req);
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
+ result = expect100(data, conn, r);
if(result)
return result;
}
@@ -2771,12 +2442,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->state.expect100header = FALSE;
/* make the request end in a true CRLF */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
/* set the upload size to the progress meter */
- Curl_pgrsSetUploadSize(data, postsize);
+ Curl_pgrsSetUploadSize(data, http->postsize);
/* Read from mime structure. */
data->state.fread_func = (curl_read_callback) Curl_mime_read;
@@ -2784,14 +2455,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
else
/* prepare for transfer */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
- postsize?FIRSTSOCKET:-1);
+ http->postsize?FIRSTSOCKET:-1);
if(result)
return result;
@@ -2801,26 +2472,26 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* this is the simple POST, using x-www-form-urlencoded style */
if(conn->bits.authneg)
- postsize = 0;
+ http->postsize = 0;
else
/* the size of the post body */
- postsize = data->state.infilesize;
+ http->postsize = data->state.infilesize;
/* We only set Content-Length and allow a custom Content-Length if
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
- if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
+ if((http->postsize != -1) && !data->req.upload_chunky &&
+ (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
- result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
- "\r\n", postsize);
+ result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", http->postsize);
if(result)
return result;
}
- if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_dyn_add(&req, "Content-Type: application/"
+ if(!Curl_checkheaders(data, "Content-Type")) {
+ result = Curl_dyn_add(r, "Content-Type: application/"
"x-www-form-urlencoded\r\n");
if(result)
return result;
@@ -2830,26 +2501,28 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect");
+ ptr = Curl_checkheaders(data, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
}
- else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
- result = expect100(data, conn, &req);
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
+ result = expect100(data, conn, r);
if(result)
return result;
}
else
data->state.expect100header = FALSE;
+#ifndef USE_HYPER
+ /* With Hyper the body is always passed on separately */
if(data->set.postfields) {
/* In HTTP2, we send request body in DATA frame regardless of
its size. */
if(conn->httpversion != 20 &&
!data->state.expect100header &&
- (postsize < MAX_INITIAL_POST_SIZE)) {
+ (http->postsize < MAX_INITIAL_POST_SIZE)) {
/* if we don't use expect: 100 AND
postsize is less than MAX_INITIAL_POST_SIZE
@@ -2858,68 +2531,73 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
get the data duplicated with malloc() and family. */
/* end of headers! */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
if(!data->req.upload_chunky) {
/* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */
- result = Curl_dyn_addn(&req, data->set.postfields,
- (size_t)postsize);
- included_body = postsize;
+ result = Curl_dyn_addn(r, data->set.postfields,
+ (size_t)http->postsize);
+ included_body = http->postsize;
}
else {
- if(postsize) {
+ if(http->postsize) {
+ char chunk[16];
/* Append the POST data chunky-style */
- result = Curl_dyn_addf(&req, "%x\r\n", (int)postsize);
+ msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)http->postsize);
+ result = Curl_dyn_add(r, chunk);
if(!result) {
- result = Curl_dyn_addn(&req, data->set.postfields,
- (size_t)postsize);
+ included_body = http->postsize + strlen(chunk);
+ result = Curl_dyn_addn(r, data->set.postfields,
+ (size_t)http->postsize);
if(!result)
- result = Curl_dyn_add(&req, "\r\n");
- included_body = postsize + 2;
+ result = Curl_dyn_add(r, "\r\n");
+ included_body += 2;
}
}
- if(!result)
- result = Curl_dyn_add(&req, "\x30\x0d\x0a\x0d\x0a");
- /* 0 CR LF CR LF */
- included_body += 5;
+ if(!result) {
+ result = Curl_dyn_add(r, "\x30\x0d\x0a\x0d\x0a");
+ /* 0 CR LF CR LF */
+ included_body += 5;
+ }
}
if(result)
return result;
/* Make sure the progress information is accurate */
- Curl_pgrsSetUploadSize(data, postsize);
+ Curl_pgrsSetUploadSize(data, http->postsize);
}
else {
/* A huge POST coming up, do data separate from the request */
- http->postsize = postsize;
http->postdata = data->set.postfields;
http->sending = HTTPSEND_BODY;
data->state.fread_func = (curl_read_callback)readmoredata;
- data->state.in = (void *)conn;
+ data->state.in = (void *)data;
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
/* end of headers! */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
}
}
- else {
+ else
+#endif
+ {
/* end of headers! */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
if(data->req.upload_chunky && conn->bits.authneg) {
/* Chunky upload is selected and we're negotiating auth still, send
end-of-data only */
- result = Curl_dyn_add(&req, (char *)"\x30\x0d\x0a\x0d\x0a");
+ result = Curl_dyn_add(r, (char *)"\x30\x0d\x0a\x0d\x0a");
/* 0 CR LF CR LF */
if(result)
return result;
@@ -2927,19 +2605,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else if(data->state.infilesize) {
/* set the upload size to the progress meter */
- Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
+ Curl_pgrsSetUploadSize(data, http->postsize?http->postsize:-1);
/* set the pointer to mark that we will send the post body using the
- read callback, but only if we're not in authenticate
- negotiation */
- if(!conn->bits.authneg) {
+ read callback, but only if we're not in authenticate negotiation */
+ if(!conn->bits.authneg)
http->postdata = (char *)&http->postdata;
- http->postsize = postsize;
- }
}
}
/* issue the request */
- result = Curl_buffer_send(&req, conn, &data->info.request_size,
+ result = Curl_buffer_send(r, data, &data->info.request_size,
(size_t)included_body, FIRSTSOCKET);
if(result)
@@ -2950,12 +2625,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break;
default:
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
/* issue the request */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
@@ -2964,24 +2639,567 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* HTTP GET/HEAD download: */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
}
+
+ return result;
+}
+
+#if !defined(CURL_DISABLE_COOKIES)
+CURLcode Curl_http_cookies(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r)
+{
+ CURLcode result = CURLE_OK;
+ char *addcookies = NULL;
+ if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie"))
+ addcookies = data->set.str[STRING_COOKIE];
+
+ if(data->cookies || addcookies) {
+ struct Cookie *co = NULL; /* no cookies from start */
+ int count = 0;
+
+ if(data->cookies && data->state.cookie_engine) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ co = Curl_cookie_getlist(data->cookies,
+ data->state.aptr.cookiehost?
+ data->state.aptr.cookiehost:
+ conn->host.name,
+ data->state.up.path,
+ (conn->handler->protocol&CURLPROTO_HTTPS)?
+ TRUE:FALSE);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ if(co) {
+ struct Cookie *store = co;
+ /* now loop through all cookies that matched */
+ while(co) {
+ if(co->value) {
+ if(0 == count) {
+ result = Curl_dyn_add(r, "Cookie: ");
+ if(result)
+ break;
+ }
+ result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
+ co->name, co->value);
+ if(result)
+ break;
+ count++;
+ }
+ co = co->next; /* next cookie please */
+ }
+ Curl_cookie_freelist(store);
+ }
+ if(addcookies && !result) {
+ if(!count)
+ result = Curl_dyn_add(r, "Cookie: ");
+ if(!result) {
+ result = Curl_dyn_addf(r, "%s%s", count?"; ":"", addcookies);
+ count++;
+ }
+ }
+ if(count && !result)
+ result = Curl_dyn_add(r, "\r\n");
+
+ if(result)
+ return result;
+ }
+ return result;
+}
+#endif
+
+CURLcode Curl_http_range(struct Curl_easy *data,
+ Curl_HttpReq httpreq)
+{
+ if(data->state.use_range) {
+ /*
+ * A range is selected. We use different headers whether we're downloading
+ * or uploading and we always let customized headers override our internal
+ * ones if any such are specified.
+ */
+ if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
+ !Curl_checkheaders(data, "Range")) {
+ /* if a line like this was already allocated, free the previous one */
+ free(data->state.aptr.rangeline);
+ data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
+ data->state.range);
+ }
+ else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
+ !Curl_checkheaders(data, "Content-Range")) {
+
+ /* if a line like this was already allocated, free the previous one */
+ free(data->state.aptr.rangeline);
+
+ if(data->set.set_resume_from < 0) {
+ /* Upload resume was asked for, but we don't know the size of the
+ remote part so we tell the server (and act accordingly) that we
+ upload the whole file (again) */
+ data->state.aptr.rangeline =
+ aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.infilesize - 1, data->state.infilesize);
+
+ }
+ else if(data->state.resume_from) {
+ /* This is because "resume" was selected */
+ curl_off_t total_expected_size =
+ data->state.resume_from + data->state.infilesize;
+ data->state.aptr.rangeline =
+ aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, total_expected_size-1,
+ total_expected_size);
+ }
+ else {
+ /* Range was selected and then we just pass the incoming range and
+ append total size */
+ data->state.aptr.rangeline =
+ aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, data->state.infilesize);
+ }
+ if(!data->state.aptr.rangeline)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_http_resume(struct Curl_easy *data,
+ struct connectdata *conn,
+ Curl_HttpReq httpreq)
+{
+ if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
+ data->state.resume_from) {
+ /**********************************************************************
+ * Resuming upload in HTTP means that we PUT or POST and that we have
+ * got a resume_from value set. The resume value has already created
+ * a Range: header that will be passed along. We need to "fast forward"
+ * the file the given number of bytes and decrease the assume upload
+ * file size before we continue this venture in the dark lands of HTTP.
+ * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
+ *********************************************************************/
+
+ if(data->state.resume_from < 0) {
+ /*
+ * This is meant to get the size of the present remote-file by itself.
+ * We don't support this now. Bail out!
+ */
+ data->state.resume_from = 0;
+ }
+
+ if(data->state.resume_from && !data->state.this_is_a_follow) {
+ /* do we still game? */
+
+ /* Now, let's read off the proper amount of bytes from the
+ input. */
+ int seekerr = CURL_SEEKFUNC_CANTSEEK;
+ if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
+ seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+ SEEK_SET);
+ Curl_set_in_callback(data, false);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ curl_off_t passed = 0;
+
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_READ_ERROR;
+ }
+ /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > data->set.buffer_size) ?
+ (size_t)data->set.buffer_size :
+ curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ data->state.fread_func(data->state.buffer, 1, readthisamountnow,
+ data->state.in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
+ " bytes from the input", passed);
+ return CURLE_READ_ERROR;
+ }
+ } while(passed < data->state.resume_from);
+ }
+
+ /* now, decrease the size of the read */
+ if(data->state.infilesize>0) {
+ data->state.infilesize -= data->state.resume_from;
+
+ if(data->state.infilesize <= 0) {
+ failf(data, "File already completely uploaded");
+ return CURLE_PARTIAL_FILE;
+ }
+ }
+ /* we've passed, proceed as normal */
+ }
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_http_firstwrite(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *done)
+{
+ struct SingleRequest *k = &data->req;
+ DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP));
+ if(data->req.newurl) {
+ if(conn->bits.close) {
+ /* Abort after the headers if "follow Location" is set
+ and we're set to close anyway. */
+ k->keepon &= ~KEEP_RECV;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ /* We have a new url to load, but since we want to be able to re-use this
+ connection properly, we read the full response in "ignore more" */
+ k->ignorebody = TRUE;
+ infof(data, "Ignoring the response-body\n");
+ }
+ if(data->state.resume_from && !k->content_range &&
+ (data->state.httpreq == HTTPREQ_GET) &&
+ !k->ignorebody) {
+
+ if(k->size == data->state.resume_from) {
+ /* The resume point is at the end of file, consider this fine even if it
+ doesn't allow resume from here. */
+ infof(data, "The entire document is already downloaded");
+ connclose(conn, "already downloaded");
+ /* Abort download */
+ k->keepon &= ~KEEP_RECV;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* we wanted to resume a download, although the server doesn't seem to
+ * support this and we did this with a GET (if it wasn't a GET we did a
+ * POST or PUT resume) */
+ failf(data, "HTTP server doesn't seem to support "
+ "byte ranges. Cannot resume.");
+ return CURLE_RANGE_ERROR;
+ }
+
+ if(data->set.timecondition && !data->state.range) {
+ /* A time condition has been set AND no ranges have been requested. This
+ seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
+ action for a HTTP/1.1 client */
+
+ if(!Curl_meets_timecondition(data, k->timeofdoc)) {
+ *done = TRUE;
+ /* We're simulating a http 304 from server so we return
+ what should have been returned from the server */
+ data->info.httpcode = 304;
+ infof(data, "Simulate a HTTP 304 response!\n");
+ /* we abort the transfer before it is completed == we ruin the
+ re-use ability. Close the connection */
+ connclose(conn, "Simulated 304 handling");
+ return CURLE_OK;
+ }
+ } /* we have a time condition */
+
+ return CURLE_OK;
+}
+
+#ifndef USE_HYPER
+/*
+ * Curl_http() gets called from the generic multi_do() function when a HTTP
+ * request is to be performed. This creates and sends a properly constructed
+ * HTTP request.
+ */
+CURLcode Curl_http(struct Curl_easy *data, bool *done)
+{
+ struct connectdata *conn = data->conn;
+ CURLcode result = CURLE_OK;
+ struct HTTP *http;
+ Curl_HttpReq httpreq;
+ const char *te = ""; /* transfer-encoding */
+ const char *request;
+ const char *httpstring;
+ struct dynbuf req;
+ char *altused = NULL;
+ const char *p_accept; /* Accept: string */
+
+ /* Always consider the DO phase done after this function call, even if there
+ may be parts of the request that are not yet sent, since we can deal with
+ the rest of the request in the PERFORM phase. */
+ *done = TRUE;
+
+ if(conn->transport != TRNSPRT_QUIC) {
+ if(conn->httpversion < 20) { /* unless the connection is re-used and
+ already http2 */
+ switch(conn->negnpn) {
+ case CURL_HTTP_VERSION_2:
+ conn->httpversion = 20; /* we know we're on HTTP/2 now */
+
+ result = Curl_http2_switched(data, NULL, 0);
+ if(result)
+ return result;
+ break;
+ case CURL_HTTP_VERSION_1_1:
+ /* continue with HTTP/1.1 when explicitly requested */
+ break;
+ 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) {
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ /* We don't support HTTP/2 proxies yet. Also it's debatable
+ whether or not this setting should apply to HTTP/2 proxies. */
+ infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
+ break;
+ }
+#endif
+ DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
+ conn->httpversion = 20;
+
+ result = Curl_http2_switched(data, NULL, 0);
+ if(result)
+ return result;
+ }
+#endif
+ break;
+ }
+ }
+ else {
+ /* prepare for a http2 request */
+ result = Curl_http2_setup(data, conn);
+ if(result)
+ return result;
+ }
+ }
+ http = data->req.p.http;
+ DEBUGASSERT(http);
+
+ result = Curl_http_host(data, conn);
+ if(result)
+ return result;
+
+ result = Curl_http_useragent(data);
+ if(result)
+ return result;
+
+ Curl_http_method(data, conn, &request, &httpreq);
+
+ /* setup the authentication headers */
+ {
+ char *pq = NULL;
+ if(data->state.up.query) {
+ pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
+ if(!pq)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result = Curl_http_output_auth(data, conn, request, httpreq,
+ (pq ? pq : data->state.up.path), FALSE);
+ free(pq);
+ if(result)
+ return result;
+ }
+
+ 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.aptr.ref)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ 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;
+ }
+ 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 */
+
+ if(!Curl_checkheaders(data, "TE") &&
+ data->set.http_transfer_encoding) {
+ /* When we are to insert a TE: header in the request, we must also insert
+ TE in a Connection: header, so we need to merge the custom provided
+ Connection: header and prevent the original to get sent. Note that if
+ the user has inserted his/her own TE: header we don't do this magic
+ but then assume that the user will handle it all! */
+ char *cptr = Curl_checkheaders(data, "Connection");
+#define TE_HEADER "TE: gzip\r\n"
+
+ Curl_safefree(data->state.aptr.te);
+
+ if(cptr) {
+ cptr = Curl_copy_header_value(cptr);
+ if(!cptr)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Create the (updated) Connection: header */
+ data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+
+ free(cptr);
+ if(!data->state.aptr.te)
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif
+
+ result = Curl_http_body(data, conn, httpreq, &te);
+ if(result)
+ return result;
+
+ p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
+
+ result = Curl_http_resume(data, conn, httpreq);
if(result)
return result;
- if(!postsize && (http->sending != HTTPSEND_REQUEST))
+
+ result = Curl_http_range(data, httpreq);
+ if(result)
+ return result;
+
+ httpstring = get_http_string(data, conn);
+
+ /* initialize a dynamic send-buffer */
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+
+ /* add the main request stuff */
+ /* GET/HEAD/POST/PUT */
+ result = Curl_dyn_addf(&req, "%s ", request);
+ if(!result)
+ result = Curl_http_target(data, conn, &req);
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+
+#ifndef CURL_DISABLE_ALTSVC
+ if(conn->bits.altused && !Curl_checkheaders(data, "Alt-Used")) {
+ altused = aprintf("Alt-Used: %s:%d\r\n",
+ conn->conn_to_host.name, conn->conn_to_port);
+ if(!altused) {
+ Curl_dyn_free(&req);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ result =
+ Curl_dyn_addf(&req,
+ " HTTP/%s\r\n" /* HTTP version */
+ "%s" /* host */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* accept */
+ "%s" /* TE: */
+ "%s" /* accept-encoding */
+ "%s" /* referer */
+ "%s" /* Proxy-Connection */
+ "%s" /* transfer-encoding */
+ "%s",/* Alt-Used */
+
+ httpstring,
+ (data->state.aptr.host?data->state.aptr.host:""),
+ data->state.aptr.proxyuserpwd?
+ data->state.aptr.proxyuserpwd:"",
+ data->state.aptr.userpwd?data->state.aptr.userpwd:"",
+ (data->state.use_range && data->state.aptr.rangeline)?
+ data->state.aptr.rangeline:"",
+ (data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ data->state.aptr.uagent)?
+ data->state.aptr.uagent:"",
+ p_accept?p_accept:"",
+ data->state.aptr.te?data->state.aptr.te:"",
+ (data->set.str[STRING_ENCODING] &&
+ *data->set.str[STRING_ENCODING] &&
+ data->state.aptr.accept_encoding)?
+ data->state.aptr.accept_encoding:"",
+ (data->change.referer && data->state.aptr.ref)?
+ data->state.aptr.ref:"" /* Referer: <data> */,
+#ifndef CURL_DISABLE_PROXY
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !Curl_checkheaders(data, "Proxy-Connection") &&
+ !Curl_checkProxyheaders(data, conn, "Proxy-Connection"))?
+ "Proxy-Connection: Keep-Alive\r\n":"",
+#else
+ "",
+#endif
+ te,
+ altused ? altused : ""
+ );
+
+ /* clear userpwd and proxyuserpwd to avoid re-using old credentials
+ * from re-used connections */
+ Curl_safefree(data->state.aptr.userpwd);
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+ free(altused);
+
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+
+ if(!(conn->handler->flags&PROTOPT_SSL) &&
+ conn->httpversion != 20 &&
+ (data->set.httpversion == 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);
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+ }
+
+ result = Curl_http_cookies(data, conn, &req);
+ if(!result)
+ result = Curl_add_timecondition(data, &req);
+ if(!result)
+ result = Curl_add_custom_headers(data, FALSE, &req);
+
+ if(!result) {
+ http->postdata = NULL; /* nothing to post at this point */
+ if((httpreq == HTTPREQ_GET) ||
+ (httpreq == HTTPREQ_HEAD))
+ Curl_pgrsSetUploadSize(data, 0); /* nothing */
+
+ /* bodysend takes ownership of the 'req' memory on success */
+ result = Curl_http_bodysend(data, conn, &req, httpreq);
+ }
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+
+ if((http->postsize > -1) &&
+ (http->postsize <= data->req.writebytecount) &&
+ (http->sending != HTTPSEND_REQUEST))
data->req.upload_done = TRUE;
if(data->req.writebytecount) {
/* if a request-body has been sent off, we make sure this progress is noted
properly */
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
- if(data->req.writebytecount >= postsize) {
+ if(!http->postsize) {
/* already sent the entire request body, mark the "upload" as
complete */
infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
" out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- data->req.writebytecount, postsize);
+ data->req.writebytecount, http->postsize);
data->req.upload_done = TRUE;
data->req.keepon &= ~KEEP_SEND; /* we're done writing */
data->req.exp100 = EXP100_SEND_DATA; /* already sent */
@@ -2997,6 +3215,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
+#endif /* USE_HYPER */
+
typedef enum {
STATUS_UNKNOWN, /* not enough data to tell yet */
STATUS_DONE, /* a status line was read */
@@ -3101,41 +3321,383 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
return checkhttpprefix(data, s, len);
}
-static void print_http_error(struct Curl_easy *data)
+/*
+ * Curl_http_header() parses a single response header.
+ */
+CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
+ char *headp)
{
+ CURLcode result;
struct SingleRequest *k = &data->req;
- char *beg = Curl_dyn_ptr(&data->state.headerb);
-
- /* make sure that data->req.p points to the HTTP status line */
- if(!strncmp(beg, "HTTP", 4)) {
-
- /* skip to HTTP status code */
- beg = strchr(beg, ' ');
- if(beg && *++beg) {
-
- /* find trailing CR */
- char end_char = '\r';
- char *end = strchr(beg, end_char);
- if(!end) {
- /* try to find LF (workaround for non-compliant HTTP servers) */
- end_char = '\n';
- end = strchr(beg, end_char);
+ /* Check for Content-Length: header lines to get size */
+ if(!k->http_bodyless &&
+ !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
+ curl_off_t contentlength;
+ CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);
+
+ if(offt == CURL_OFFT_OK) {
+ if(data->set.max_filesize &&
+ contentlength > data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
}
+ k->size = contentlength;
+ k->maxdownload = k->size;
+ /* we set the progress download size already at this point
+ just to make it easier for apps/callbacks to extract this
+ info as soon as possible */
+ Curl_pgrsSetDownloadSize(data, k->size);
+ }
+ else if(offt == CURL_OFFT_FLOW) {
+ /* out of range */
+ if(data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+ streamclose(conn, "overflow content-length");
+ infof(data, "Overflow Content-Length: value!\n");
+ }
+ else {
+ /* negative or just rubbish - bad HTTP */
+ failf(data, "Invalid Content-Length: value");
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
+ }
+ /* check for Content-Type: header lines to get the MIME-type */
+ else if(checkprefix("Content-Type:", headp)) {
+ char *contenttype = Curl_copy_header_value(headp);
+ if(!contenttype)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*contenttype)
+ /* ignore empty data */
+ free(contenttype);
+ else {
+ Curl_safefree(data->info.contenttype);
+ data->info.contenttype = contenttype;
+ }
+ }
+#ifndef CURL_DISABLE_PROXY
+ else if((conn->httpversion == 10) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) {
+ /*
+ * When a HTTP/1.0 reply comes when using a proxy, the
+ * 'Proxy-Connection: keep-alive' line tells us the
+ * connection will be kept alive for our pleasure.
+ * Default action for 1.0 is to close.
+ */
+ connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
+ infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
+ }
+ else if((conn->httpversion == 11) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(headp, "Proxy-Connection:", "close")) {
+ /*
+ * We get a HTTP/1.1 response from a proxy and it says it'll
+ * close down after this transfer.
+ */
+ connclose(conn, "Proxy-Connection: asked to close after done");
+ infof(data, "HTTP/1.1 proxy connection set close!\n");
+ }
+#endif
+ else if((conn->httpversion == 10) &&
+ Curl_compareheader(headp, "Connection:", "keep-alive")) {
+ /*
+ * A HTTP/1.0 reply with the 'Connection: keep-alive' line
+ * tells us the connection will be kept alive for our
+ * pleasure. Default action for 1.0 is to close.
+ *
+ * [RFC2068, section 19.7.1] */
+ connkeep(conn, "Connection keep-alive");
+ infof(data, "HTTP/1.0 connection set to keep alive!\n");
+ }
+ else if(Curl_compareheader(headp, "Connection:", "close")) {
+ /*
+ * [RFC 2616, section 8.1.2.1]
+ * "Connection: close" is HTTP/1.1 language and means that
+ * the connection will close when this request has been
+ * served.
+ */
+ streamclose(conn, "Connection: close used");
+ }
+ else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
+ /* One or more encodings. We check for chunked and/or a compression
+ algorithm. */
+ /*
+ * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
+ * means that the server will send a series of "chunks". Each
+ * chunk starts with line with info (including size of the
+ * coming block) (terminated with CRLF), then a block of data
+ * with the previously mentioned size. There can be any amount
+ * of chunks, and a chunk-data set to zero signals the
+ * end-of-chunks. */
+
+ result = Curl_build_unencoding_stack(data, headp + 18, TRUE);
+ if(result)
+ return result;
+ }
+ else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
+ data->set.str[STRING_ENCODING]) {
+ /*
+ * Process Content-Encoding. Look for the values: identity,
+ * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
+ * x-compress are the same as gzip and compress. (Sec 3.5 RFC
+ * 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);
+ 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]);
+ if(-1 == date) {
+ /* not a date, try it as a decimal number */
+ (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
+ }
+ else
+ /* convert date to number of seconds into the future */
+ retry_after = date - time(NULL);
+ data->info.retry_after = retry_after; /* store it */
+ }
+ else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
+ /* Content-Range: bytes [num]-
+ Content-Range: bytes: [num]-
+ Content-Range: [num]-
+ Content-Range: [asterisk]/[total]
+
+ The second format was added since Sun's webserver
+ JavaWebServer/1.1.1 obviously sends the header this way!
+ The third added since some servers use that!
+ The forth means the requested range was unsatisfied.
+ */
+
+ char *ptr = headp + 14;
- if(end) {
- /* temporarily replace CR or LF by NUL and print the error message */
- *end = '\0';
- failf(data, "The requested URL returned error: %s", beg);
+ /* Move forward until first digit or asterisk */
+ while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
+ ptr++;
- /* restore the previously replaced CR or LF */
- *end = end_char;
- return;
+ /* if it truly stopped on a digit */
+ if(ISDIGIT(*ptr)) {
+ if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
+ if(data->state.resume_from == k->offset)
+ /* we asked for a resume and we got it */
+ k->content_range = TRUE;
}
}
+ else
+ data->state.resume_from = 0; /* get everything */
+ }
+#if !defined(CURL_DISABLE_COOKIES)
+ else if(data->cookies && data->state.cookie_engine &&
+ checkprefix("Set-Cookie:", headp)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_add(data,
+ data->cookies, TRUE, FALSE, headp + 11,
+ /* If there is a custom-set Host: name, use it
+ here, or else use real peer host name. */
+ data->state.aptr.cookiehost?
+ data->state.aptr.cookiehost:conn->host.name,
+ data->state.up.path,
+ (conn->handler->protocol&CURLPROTO_HTTPS)?
+ TRUE:FALSE);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+#endif
+ else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
+ (data->set.timecondition || data->set.get_filetime) ) {
+ k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
+ if(data->set.get_filetime)
+ data->info.filetime = k->timeofdoc;
+ }
+ else if((checkprefix("WWW-Authenticate:", headp) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", headp) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(headp);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_http_input_auth(data, proxy, auth);
+
+ free(auth);
+
+ if(result)
+ return result;
+ }
+#ifdef USE_SPNEGO
+ else if(checkprefix("Persistent-Auth", headp)) {
+ struct negotiatedata *negdata = &conn->negotiate;
+ struct auth *authp = &data->state.authhost;
+ if(authp->picked == CURLAUTH_NEGOTIATE) {
+ char *persistentauth = Curl_copy_header_value(headp);
+ if(!persistentauth)
+ return CURLE_OUT_OF_MEMORY;
+ negdata->noauthpersist = checkprefix("false", persistentauth)?
+ TRUE:FALSE;
+ negdata->havenoauthpersist = TRUE;
+ infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
+ negdata->noauthpersist, persistentauth);
+ free(persistentauth);
+ }
}
+#endif
+ else if((k->httpcode >= 300 && k->httpcode < 400) &&
+ checkprefix("Location:", headp) &&
+ !data->req.location) {
+ /* this is the URL that the server advises us to use instead */
+ char *location = Curl_copy_header_value(headp);
+ if(!location)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*location)
+ /* ignore empty data */
+ free(location);
+ else {
+ data->req.location = location;
+
+ if(data->set.http_follow_location) {
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->req.location); /* clone */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
- /* fall-back to printing the HTTP status code only */
- failf(data, "The requested URL returned error: %d", k->httpcode);
+ /* some cases of POST and PUT etc needs to rewind the data
+ stream at this point */
+ result = http_perhapsrewind(data, conn);
+ if(result)
+ return result;
+ }
+ }
+ }
+
+#ifdef USE_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 ]);
+ if(check)
+ infof(data, "Illegal STS header skipped\n");
+#ifdef DEBUGBUILD
+ else
+ infof(data, "Parsed STS header fine (%zu entries)\n",
+ data->hsts->list.size);
+#endif
+ }
+#endif
+#ifndef CURL_DISABLE_ALTSVC
+ /* If enabled, the header is incoming and this is over HTTPS */
+ else if(data->asi && checkprefix("Alt-Svc:", headp) &&
+ ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+ /* allow debug builds to circumvent the HTTPS restriction */
+ getenv("CURL_ALTSVC_HTTP")
+#else
+ 0
+#endif
+ )) {
+ /* 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:") ],
+ id, conn->host.name,
+ curlx_uitous(conn->remote_port));
+ if(result)
+ return result;
+ }
+#endif
+ else if(conn->handler->protocol & CURLPROTO_RTSP) {
+ result = Curl_rtsp_parseheader(data, headp);
+ if(result)
+ return result;
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Called after the first HTTP response line (the status line) has been
+ * received and parsed.
+ */
+
+CURLcode Curl_http_statusline(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ struct SingleRequest *k = &data->req;
+ data->info.httpcode = k->httpcode;
+
+ data->info.httpversion = conn->httpversion;
+ if(!data->state.httpversion ||
+ data->state.httpversion > conn->httpversion)
+ /* store the lowest server version we encounter */
+ data->state.httpversion = conn->httpversion;
+
+ /*
+ * This code executes as part of processing the header. As a
+ * result, it's not totally clear how to interpret the
+ * response code yet as that depends on what other headers may
+ * be present. 401 and 407 may be errors, but may be OK
+ * depending on how authentication is working. Other codes
+ * are definitely errors, so give up here.
+ */
+ if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
+ k->httpcode == 416) {
+ /* "Requested Range Not Satisfiable", just proceed and
+ pretend this is no error */
+ k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
+ }
+
+ if(conn->httpversion == 10) {
+ /* Default action for HTTP/1.0 must be to close, unless
+ we get one of those fancy headers that tell us the
+ server keeps it open for us! */
+ infof(data, "HTTP 1.0, assume close after body\n");
+ connclose(conn, "HTTP/1.0 close after body");
+ }
+ else if(conn->httpversion == 20 ||
+ (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
+ DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
+ /* HTTP/2 cannot avoid multiplexing since it is a core functionality
+ of the protocol */
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+ }
+ else if(conn->httpversion >= 11 &&
+ !conn->bits.close) {
+ /* If HTTP version is >= 1.1 and connection is persistent */
+ DEBUGF(infof(data,
+ "HTTP 1.1 or later with persistent connection\n"));
+ }
+
+ k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
+ switch(k->httpcode) {
+ case 304:
+ /* (quote from RFC2616, section 10.3.5): The 304 response
+ * MUST NOT contain a message-body, and thus is always
+ * terminated by the first empty line after the header
+ * fields. */
+ if(data->set.timecondition)
+ data->info.timecond = TRUE;
+ /* FALLTHROUGH */
+ case 204:
+ /* (quote from RFC2616, section 10.2.5): The server has
+ * fulfilled the request but does not need to return an
+ * entity-body ... The 204 response MUST NOT include a
+ * message-body, and thus is always terminated by the first
+ * empty line after the header fields. */
+ k->size = 0;
+ k->maxdownload = 0;
+ k->http_bodyless = TRUE;
+ break;
+ default:
+ break;
+ }
+ return CURLE_OK;
}
/*
@@ -3186,7 +3748,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
k->badheader = HEADER_ALLBAD;
streamclose(conn, "bad HTTP: No end-of-message indicator");
if(!data->set.http09_allowed) {
- failf(data, "Received HTTP/0.9 when not allowed\n");
+ failf(data, "Received HTTP/0.9 when not allowed");
return CURLE_UNSUPPORTED_PROTOCOL;
}
break;
@@ -3221,7 +3783,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
streamclose(conn, "bad HTTP: No end-of-message indicator");
/* this is not the beginning of a protocol first header line */
if(!data->set.http09_allowed) {
- failf(data, "Received HTTP/0.9 when not allowed\n");
+ failf(data, "Received HTTP/0.9 when not allowed");
return CURLE_UNSUPPORTED_PROTOCOL;
}
k->header = FALSE;
@@ -3296,7 +3858,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* switch to http2 now. The bytes after response headers
are also processed here, otherwise they are lost. */
- result = Curl_http2_switched(conn, k->str, *nread);
+ result = Curl_http2_switched(data, k->str, *nread);
if(result)
return result;
*nread = 0;
@@ -3362,15 +3924,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
conn->proxy_negotiate_state = GSS_AUTHSUCC;
}
#endif
- /*
- * When all the headers have been parsed, see if we should give
- * up and return an error.
- */
- if(http_should_fail(conn)) {
- failf(data, "The requested URL returned error: %d",
- k->httpcode);
- return CURLE_HTTP_RETURNED_ERROR;
- }
/* now, only output this if the header AND body are requested:
*/
@@ -3379,7 +3932,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
writetype |= CLIENTWRITE_BODY;
headerlen = Curl_dyn_len(&data->state.headerb);
- result = Curl_client_write(conn, writetype,
+ result = Curl_client_write(data, writetype,
Curl_dyn_ptr(&data->state.headerb),
headerlen);
if(result)
@@ -3388,13 +3941,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
data->info.header_size += (long)headerlen;
data->req.headerbytecount += (long)headerlen;
+ /*
+ * When all the headers have been parsed, see if we should give
+ * up and return an error.
+ */
+ if(http_should_fail(data)) {
+ failf(data, "The requested URL returned error: %d",
+ k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
/* Curl_http_auth_act() checks what authentication methods
* that are available and decides which one (if any) to
* use. It will set 'newurl' if an auth method was picked. */
- result = Curl_http_auth_act(conn);
+ result = Curl_http_auth_act(data);
if(result)
return result;
@@ -3432,8 +3995,8 @@ 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(conn->data->change.url);
- Curl_done_sending(conn, k);
+ data->req.newurl = strdup(data->change.url);
+ Curl_done_sending(data, k);
}
else if(data->set.http_keep_sending_on_error) {
infof(data, "HTTP error before end of send, keep sending\n");
@@ -3445,7 +4008,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
else {
infof(data, "HTTP error before end of send, stop sending\n");
streamclose(conn, "Stop sending data before everything sent");
- result = Curl_done_sending(conn, k);
+ result = Curl_done_sending(data, k);
if(result)
return result;
k->upload_done = TRUE;
@@ -3531,10 +4094,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
k->keepon &= ~KEEP_RECV;
}
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- str_start, headerlen);
- break; /* exit header line loop */
+ Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
+ break; /* exit header line loop */
}
/* We continue reading headers, reset the line-based header */
@@ -3655,83 +4216,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
if(nc) {
- data->info.httpcode = k->httpcode;
-
- data->info.httpversion = conn->httpversion;
- if(!data->state.httpversion ||
- data->state.httpversion > conn->httpversion)
- /* store the lowest server version we encounter */
- data->state.httpversion = conn->httpversion;
-
- /*
- * This code executes as part of processing the header. As a
- * result, it's not totally clear how to interpret the
- * response code yet as that depends on what other headers may
- * be present. 401 and 407 may be errors, but may be OK
- * depending on how authentication is working. Other codes
- * are definitely errors, so give up here.
- */
- if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
- k->httpcode == 416) {
- /* "Requested Range Not Satisfiable", just proceed and
- pretend this is no error */
- k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
- }
- else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
- ((k->httpcode != 401) || !conn->bits.user_passwd)
-#ifndef CURL_DISABLE_PROXY
- && ((k->httpcode != 407) || !conn->bits.proxy_user_passwd)
-#endif
- ) {
- /* serious error, go home! */
- print_http_error(data);
- return CURLE_HTTP_RETURNED_ERROR;
- }
-
- if(conn->httpversion == 10) {
- /* Default action for HTTP/1.0 must be to close, unless
- we get one of those fancy headers that tell us the
- server keeps it open for us! */
- infof(data, "HTTP 1.0, assume close after body\n");
- connclose(conn, "HTTP/1.0 close after body");
- }
- else if(conn->httpversion == 20 ||
- (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
- DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
- /* HTTP/2 cannot avoid multiplexing since it is a core functionality
- of the protocol */
- conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- }
- else if(conn->httpversion >= 11 &&
- !conn->bits.close) {
- /* If HTTP version is >= 1.1 and connection is persistent */
- DEBUGF(infof(data,
- "HTTP 1.1 or later with persistent connection\n"));
- }
-
- k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
- switch(k->httpcode) {
- case 304:
- /* (quote from RFC2616, section 10.3.5): The 304 response
- * MUST NOT contain a message-body, and thus is always
- * terminated by the first empty line after the header
- * fields. */
- if(data->set.timecondition)
- data->info.timecond = TRUE;
- /* FALLTHROUGH */
- case 204:
- /* (quote from RFC2616, section 10.2.5): The server has
- * fulfilled the request but does not need to return an
- * entity-body ... The 204 response MUST NOT include a
- * message-body, and thus is always terminated by the first
- * empty line after the header fields. */
- k->size = 0;
- k->maxdownload = 0;
- k->http_bodyless = TRUE;
- break;
- default:
- break;
- }
+ result = Curl_http_statusline(data, conn);
+ if(result)
+ return result;
}
else {
k->header = FALSE; /* this is not a header line */
@@ -3744,278 +4231,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(result)
return result;
- /* Check for Content-Length: header lines to get size */
- if(!k->http_bodyless &&
- !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
- curl_off_t contentlength;
- CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);
-
- if(offt == CURL_OFFT_OK) {
- if(data->set.max_filesize &&
- contentlength > data->set.max_filesize) {
- failf(data, "Maximum file size exceeded");
- return CURLE_FILESIZE_EXCEEDED;
- }
- k->size = contentlength;
- k->maxdownload = k->size;
- /* we set the progress download size already at this point
- just to make it easier for apps/callbacks to extract this
- info as soon as possible */
- Curl_pgrsSetDownloadSize(data, k->size);
- }
- else if(offt == CURL_OFFT_FLOW) {
- /* out of range */
- if(data->set.max_filesize) {
- failf(data, "Maximum file size exceeded");
- return CURLE_FILESIZE_EXCEEDED;
- }
- streamclose(conn, "overflow content-length");
- infof(data, "Overflow Content-Length: value!\n");
- }
- else {
- /* negative or just rubbish - bad HTTP */
- failf(data, "Invalid Content-Length: value");
- return CURLE_WEIRD_SERVER_REPLY;
- }
- }
- /* check for Content-Type: header lines to get the MIME-type */
- else if(checkprefix("Content-Type:", headp)) {
- char *contenttype = Curl_copy_header_value(headp);
- if(!contenttype)
- return CURLE_OUT_OF_MEMORY;
- if(!*contenttype)
- /* ignore empty data */
- free(contenttype);
- else {
- Curl_safefree(data->info.contenttype);
- data->info.contenttype = contenttype;
- }
- }
-#ifndef CURL_DISABLE_PROXY
- else if((conn->httpversion == 10) &&
- conn->bits.httpproxy &&
- Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) {
- /*
- * When a HTTP/1.0 reply comes when using a proxy, the
- * 'Proxy-Connection: keep-alive' line tells us the
- * connection will be kept alive for our pleasure.
- * Default action for 1.0 is to close.
- */
- connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
- infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
- }
- else if((conn->httpversion == 11) &&
- conn->bits.httpproxy &&
- Curl_compareheader(headp, "Proxy-Connection:", "close")) {
- /*
- * We get a HTTP/1.1 response from a proxy and it says it'll
- * close down after this transfer.
- */
- connclose(conn, "Proxy-Connection: asked to close after done");
- infof(data, "HTTP/1.1 proxy connection set close!\n");
- }
-#endif
- else if((conn->httpversion == 10) &&
- Curl_compareheader(headp, "Connection:", "keep-alive")) {
- /*
- * A HTTP/1.0 reply with the 'Connection: keep-alive' line
- * tells us the connection will be kept alive for our
- * pleasure. Default action for 1.0 is to close.
- *
- * [RFC2068, section 19.7.1] */
- connkeep(conn, "Connection keep-alive");
- infof(data, "HTTP/1.0 connection set to keep alive!\n");
- }
- else if(Curl_compareheader(headp, "Connection:", "close")) {
- /*
- * [RFC 2616, section 8.1.2.1]
- * "Connection: close" is HTTP/1.1 language and means that
- * the connection will close when this request has been
- * served.
- */
- streamclose(conn, "Connection: close used");
- }
- else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
- /* One or more encodings. We check for chunked and/or a compression
- algorithm. */
- /*
- * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
- * means that the server will send a series of "chunks". Each
- * chunk starts with line with info (including size of the
- * coming block) (terminated with CRLF), then a block of data
- * with the previously mentioned size. There can be any amount
- * of chunks, and a chunk-data set to zero signals the
- * end-of-chunks. */
-
- result = Curl_build_unencoding_stack(conn, headp + 18, TRUE);
- if(result)
- return result;
- }
- else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
- data->set.str[STRING_ENCODING]) {
- /*
- * Process Content-Encoding. Look for the values: identity,
- * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
- * x-compress are the same as gzip and compress. (Sec 3.5 RFC
- * 2616). zlib cannot handle compress. However, errors are
- * handled further down when the response body is processed
- */
- result = Curl_build_unencoding_stack(conn, headp + 17, 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]);
- if(-1 == date) {
- /* not a date, try it as a decimal number */
- (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
- }
- else
- /* convert date to number of seconds into the future */
- retry_after = date - time(NULL);
- data->info.retry_after = retry_after; /* store it */
- }
- else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
- /* Content-Range: bytes [num]-
- Content-Range: bytes: [num]-
- Content-Range: [num]-
- Content-Range: [asterisk]/[total]
-
- The second format was added since Sun's webserver
- JavaWebServer/1.1.1 obviously sends the header this way!
- The third added since some servers use that!
- The forth means the requested range was unsatisfied.
- */
-
- char *ptr = headp + 14;
-
- /* Move forward until first digit or asterisk */
- while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
- ptr++;
-
- /* if it truly stopped on a digit */
- if(ISDIGIT(*ptr)) {
- if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
- if(data->state.resume_from == k->offset)
- /* we asked for a resume and we got it */
- k->content_range = TRUE;
- }
- }
- else
- data->state.resume_from = 0; /* get everything */
- }
-#if !defined(CURL_DISABLE_COOKIES)
- else if(data->cookies && data->state.cookie_engine &&
- checkprefix("Set-Cookie:", headp)) {
- Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
- CURL_LOCK_ACCESS_SINGLE);
- Curl_cookie_add(data,
- data->cookies, TRUE, FALSE, headp + 11,
- /* If there is a custom-set Host: name, use it
- here, or else use real peer host name. */
- data->state.aptr.cookiehost?
- data->state.aptr.cookiehost:conn->host.name,
- data->state.up.path,
- (conn->handler->protocol&CURLPROTO_HTTPS)?
- TRUE:FALSE);
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- }
-#endif
- else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
- (data->set.timecondition || data->set.get_filetime) ) {
- k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
- if(data->set.get_filetime)
- data->info.filetime = k->timeofdoc;
- }
- else if((checkprefix("WWW-Authenticate:", headp) &&
- (401 == k->httpcode)) ||
- (checkprefix("Proxy-authenticate:", headp) &&
- (407 == k->httpcode))) {
-
- bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
- char *auth = Curl_copy_header_value(headp);
- if(!auth)
- return CURLE_OUT_OF_MEMORY;
-
- result = Curl_http_input_auth(conn, proxy, auth);
-
- free(auth);
-
- if(result)
- return result;
- }
-#ifdef USE_SPNEGO
- else if(checkprefix("Persistent-Auth", headp)) {
- struct negotiatedata *negdata = &conn->negotiate;
- struct auth *authp = &data->state.authhost;
- if(authp->picked == CURLAUTH_NEGOTIATE) {
- char *persistentauth = Curl_copy_header_value(headp);
- if(!persistentauth)
- return CURLE_OUT_OF_MEMORY;
- negdata->noauthpersist = checkprefix("false", persistentauth)?
- TRUE:FALSE;
- negdata->havenoauthpersist = TRUE;
- infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
- negdata->noauthpersist, persistentauth);
- free(persistentauth);
- }
- }
-#endif
- else if((k->httpcode >= 300 && k->httpcode < 400) &&
- checkprefix("Location:", headp) &&
- !data->req.location) {
- /* this is the URL that the server advises us to use instead */
- char *location = Curl_copy_header_value(headp);
- if(!location)
- return CURLE_OUT_OF_MEMORY;
- if(!*location)
- /* ignore empty data */
- free(location);
- else {
- data->req.location = location;
-
- if(data->set.http_follow_location) {
- DEBUGASSERT(!data->req.newurl);
- data->req.newurl = strdup(data->req.location); /* clone */
- if(!data->req.newurl)
- return CURLE_OUT_OF_MEMORY;
-
- /* some cases of POST and PUT etc needs to rewind the data
- stream at this point */
- result = http_perhapsrewind(conn);
- if(result)
- return result;
- }
- }
- }
-#ifdef USE_ALTSVC
- /* If enabled, the header is incoming and this is over HTTPS */
- else if(data->asi && checkprefix("Alt-Svc:", headp) &&
- ((conn->handler->flags & PROTOPT_SSL) ||
-#ifdef CURLDEBUG
- /* allow debug builds to circumvent the HTTPS restriction */
- getenv("CURL_ALTSVC_HTTP")
-#else
- 0
-#endif
- )) {
- /* 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:") ],
- id, conn->host.name,
- curlx_uitous(conn->remote_port));
- if(result)
- return result;
- }
-#endif
- else if(conn->handler->protocol & CURLPROTO_RTSP) {
- result = Curl_rtsp_parseheader(conn, headp);
- if(result)
- return result;
- }
+ result = Curl_http_header(data, conn, headp);
+ if(result)
+ return result;
/*
* End of header-checks. Write them to the client.
@@ -4025,11 +4243,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, headp,
- Curl_dyn_len(&data->state.headerb));
+ Curl_debug(data, CURLINFO_HEADER_IN, headp,
+ Curl_dyn_len(&data->state.headerb));
- result = Curl_client_write(conn, writetype, headp,
+ result = Curl_client_write(data, writetype, headp,
Curl_dyn_len(&data->state.headerb));
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index 9ea3eb283..28f9341f6 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,6 +23,15 @@
***************************************************************************/
#include "curl_setup.h"
+typedef enum {
+ HTTPREQ_GET,
+ HTTPREQ_POST,
+ HTTPREQ_POST_FORM, /* we make a difference internally */
+ HTTPREQ_POST_MIME, /* we make a difference internally */
+ HTTPREQ_PUT,
+ HTTPREQ_HEAD
+} Curl_HttpReq;
+
#ifndef CURL_DISABLE_HTTP
#ifdef USE_NGHTTP2
@@ -42,32 +51,78 @@ bool Curl_compareheader(const char *headerline, /* line to check */
char *Curl_copy_header_value(const char *header);
-char *Curl_checkProxyheaders(const struct connectdata *conn,
+char *Curl_checkProxyheaders(struct Curl_easy *data,
+ const struct connectdata *conn,
const char *thisheader);
+#ifndef USE_HYPER
CURLcode Curl_buffer_send(struct dynbuf *in,
- struct connectdata *conn,
+ struct Curl_easy *data,
curl_off_t *bytes_written,
size_t included_body_bytes,
int socketindex);
+#else
+#define Curl_buffer_send(a,b,c,d,e) CURLE_OK
+#endif
-CURLcode Curl_add_timecondition(const struct connectdata *conn,
- struct dynbuf *buf);
-CURLcode Curl_add_custom_headers(struct connectdata *conn,
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *headers
+#endif
+ );
+CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect,
- struct dynbuf *req_buffer);
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *headers
+#endif
+ );
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
struct dynbuf *buf,
struct Curl_easy *handle);
+void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
+ const char **method, Curl_HttpReq *);
+CURLcode Curl_http_useragent(struct Curl_easy *data);
+CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn);
+CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *req);
+CURLcode Curl_http_statusline(struct Curl_easy *data,
+ struct connectdata *conn);
+CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
+ char *headp);
+CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
+ Curl_HttpReq httpreq,
+ const char **teep);
+CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *r, Curl_HttpReq httpreq);
+#ifndef CURL_DISABLE_COOKIES
+CURLcode Curl_http_cookies(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r);
+#else
+#define Curl_http_cookies(a,b,c) CURLE_OK
+#endif
+CURLcode Curl_http_resume(struct Curl_easy *data,
+ struct connectdata *conn,
+ Curl_HttpReq httpreq);
+CURLcode Curl_http_range(struct Curl_easy *data,
+ Curl_HttpReq httpreq);
+CURLcode Curl_http_firstwrite(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *done);
+
/* protocol-specific functions set up to be called by the main engine */
-CURLcode Curl_http(struct connectdata *conn, bool *done);
-CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
-CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
+CURLcode Curl_http(struct Curl_easy *data, bool *done);
+CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
+CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);
/* These functions are in http.c */
-CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth);
-CURLcode Curl_http_auth_act(struct connectdata *conn);
+CURLcode Curl_http_auth_act(struct Curl_easy *data);
/* If only the PICKNONE bit is set, there has been a round-trip and we
selected to use no auth at all. Ie, we actively select no auth, as opposed
@@ -115,7 +170,6 @@ struct HTTP {
const char *postdata;
const char *p_pragma; /* Pragma: string */
- const char *p_accept; /* Accept: string */
/* For FORM posting */
curl_mimepart form;
@@ -234,11 +288,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/**
* Curl_http_output_auth() setups the authentication headers for the
* host/proxy and the correct authentication
- * method. conn->data->state.authdone is set to TRUE when authentication is
+ * method. data->state.authdone is set to TRUE when authentication is
* done.
*
+ * @param data all information about the current transfer
* @param conn all information about the current connection
* @param request pointer to the request keyword
+ * @param httpreq is the request type
* @param path pointer to the requested path
* @param proxytunnel boolean if this is the request setting up a "proxy
* tunnel"
@@ -246,8 +302,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* @returns CURLcode
*/
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); /* TRUE if this is the request setting
up the proxy tunnel */
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index d316da8b6..be4c71242 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -65,12 +65,13 @@
#endif
-static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err);
-static bool http2_connisdead(struct connectdata *conn);
+static bool http2_connisdead(struct Curl_easy *data,
+ struct connectdata *conn);
static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2);
-static int h2_process_pending_input(struct connectdata *conn,
+static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc,
CURLcode *err);
@@ -92,18 +93,20 @@ void Curl_http2_init_userset(struct UserDefined *set)
set->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
}
-static int http2_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int http2_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
const struct http_conn *c = &conn->proto.httpc;
- struct SingleRequest *k = &conn->data->req;
+ struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK;
sock[0] = conn->sock[FIRSTSOCKET];
- /* in a HTTP/2 connection we can basically always get a frame so we should
- always be ready for one */
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+ if(!(k->keepon & KEEP_RECV_PAUSE))
+ /* Unless paused - in a HTTP/2 connection we can basically always get a
+ frame so we should always be ready for one */
+ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
/* we're still uploading or the HTTP/2 layer wants to send data */
if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
@@ -113,12 +116,6 @@ static int http2_perform_getsock(const struct connectdata *conn,
return bitmap;
}
-static int http2_getsock(struct connectdata *conn,
- curl_socket_t *socks)
-{
- return http2_perform_getsock(conn, socks);
-}
-
/*
* http2_stream_free() free HTTP2 stream related data
*/
@@ -139,18 +136,22 @@ static void http2_stream_free(struct HTTP *http)
* connection cache and not the "main" one. Don't touch the easy handle!
*/
-static CURLcode http2_disconnect(struct connectdata *conn,
+static CURLcode http2_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
struct http_conn *c = &conn->proto.httpc;
(void)dead_connection;
+#ifndef DEBUG_HTTP2
+ (void)data;
+#endif
- H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
+ H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
- H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
+ H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n"));
return CURLE_OK;
}
@@ -162,7 +163,7 @@ static CURLcode http2_disconnect(struct connectdata *conn,
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
-static bool http2_connisdead(struct connectdata *conn)
+static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
{
int sval;
bool dead = TRUE;
@@ -192,14 +193,14 @@ static bool http2_connisdead(struct connectdata *conn)
if(httpc->recv_underlying)
/* if called "too early", this pointer isn't setup yet! */
nread = ((Curl_recv *)httpc->recv_underlying)(
- conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
if(nread != -1) {
- infof(conn->data,
+ infof(data,
"%d bytes stray data read before trying h2 connection\n",
(int)nread);
httpc->nread_inbuf = 0;
httpc->inbuflen = nread;
- (void)h2_process_pending_input(conn, httpc, &result);
+ (void)h2_process_pending_input(data, httpc, &result);
}
else
/* the read failed so let's say this is dead anyway */
@@ -210,24 +211,25 @@ static bool http2_connisdead(struct connectdata *conn)
return dead;
}
-static unsigned int http2_conncheck(struct connectdata *check,
+static unsigned int http2_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
- struct http_conn *c = &check->proto.httpc;
+ struct http_conn *c = &conn->proto.httpc;
int rc;
bool send_frames = false;
if(checks_to_perform & CONNCHECK_ISDEAD) {
- if(http2_connisdead(check))
+ if(http2_connisdead(data, conn))
ret_val |= CONNRESULT_DEAD;
}
if(checks_to_perform & CONNCHECK_KEEPALIVE) {
struct curltime now = Curl_now();
- timediff_t elapsed = Curl_timediff(now, check->keepalive);
+ timediff_t elapsed = Curl_timediff(now, conn->keepalive);
- if(elapsed > check->upkeep_interval_ms) {
+ if(elapsed > data->set.upkeep_interval_ms) {
/* Perform an HTTP/2 PING */
rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
if(!rc) {
@@ -236,18 +238,18 @@ static unsigned int http2_conncheck(struct connectdata *check,
send_frames = true;
}
else {
- failf(check->data, "nghttp2_submit_ping() failed: %s(%d)",
+ failf(data, "nghttp2_submit_ping() failed: %s(%d)",
nghttp2_strerror(rc), rc);
}
- check->keepalive = now;
+ conn->keepalive = now;
}
}
if(send_frames) {
rc = nghttp2_session_send(c->h2);
if(rc)
- failf(check->data, "nghttp2_session_send() failed: %s(%d)",
+ failf(data, "nghttp2_session_send() failed: %s(%d)",
nghttp2_strerror(rc), rc);
}
@@ -257,7 +259,7 @@ static unsigned int http2_conncheck(struct connectdata *check,
/* called from http_setup_conn */
void Curl_http2_setup_req(struct Curl_easy *data)
{
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
http->bodystarted = FALSE;
http->status_code = -1;
http->pausedata = NULL;
@@ -294,12 +296,13 @@ static const struct Curl_handler Curl_handler_http2 = {
http2_getsock, /* proto_getsock */
http2_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- http2_perform_getsock, /* perform_getsock */
+ http2_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_STREAM /* flags */
};
@@ -315,12 +318,13 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
http2_getsock, /* proto_getsock */
http2_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- http2_perform_getsock, /* perform_getsock */
+ http2_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
@@ -340,7 +344,7 @@ int Curl_http2_ver(char *p, size_t len)
* written. See the documentation of nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *h2,
- const uint8_t *data, size_t length, int flags,
+ const uint8_t *mem, size_t length, int flags,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
@@ -355,8 +359,8 @@ static ssize_t send_callback(nghttp2_session *h2,
/* called before setup properly! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET,
- data, length, &result);
+ written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET,
+ mem, length, &result);
if(result == CURLE_AGAIN) {
return NGHTTP2_ERR_WOULDBLOCK;
@@ -391,7 +395,7 @@ char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
if(!h || !GOOD_EASY_HANDLE(h->data))
return NULL;
else {
- struct HTTP *stream = h->data->req.protop;
+ struct HTTP *stream = h->data->req.p.http;
if(num < stream->push_headers_used)
return stream->push_headers[num];
}
@@ -413,7 +417,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
!strcmp(header, ":") || strchr(header + 1, ':'))
return NULL;
else {
- struct HTTP *stream = h->data->req.protop;
+ struct HTTP *stream = h->data->req.p.http;
size_t len = strlen(header);
size_t i;
for(i = 0; i<stream->push_headers_used; i++) {
@@ -460,7 +464,7 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
(void)Curl_close(&second);
}
else {
- second->req.protop = http;
+ second->req.p.http = http;
Curl_dyn_init(&http->header_recvbuf, DYN_H2_HEADERS);
Curl_http2_setup_req(second);
second->state.stream_weight = data->state.stream_weight;
@@ -537,9 +541,9 @@ static int push_promise(struct Curl_easy *data,
/* ask the application */
H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
- stream = data->req.protop;
+ stream = data->req.p.http;
if(!stream) {
- failf(data, "Internal NULL stream!\n");
+ failf(data, "Internal NULL stream!");
(void)Curl_close(&newhandle);
rv = CURL_PUSH_DENY;
goto fail;
@@ -567,13 +571,13 @@ static int push_promise(struct Curl_easy *data,
if(rv) {
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
/* denied, kill off the new handle again */
- http2_stream_free(newhandle->req.protop);
- newhandle->req.protop = NULL;
+ http2_stream_free(newhandle->req.p.http);
+ newhandle->req.p.http = NULL;
(void)Curl_close(&newhandle);
goto fail;
}
- newstream = newhandle->req.protop;
+ newstream = newhandle->req.p.http;
newstream->stream_id = frame->promised_stream_id;
newhandle->req.maxdownload = -1;
newhandle->req.size = -1;
@@ -583,8 +587,8 @@ static int push_promise(struct Curl_easy *data,
rc = Curl_multi_add_perform(data->multi, newhandle, conn);
if(rc) {
infof(data, "failed to add handle to multi\n");
- http2_stream_free(newhandle->req.protop);
- newhandle->req.protop = NULL;
+ http2_stream_free(newhandle->req.p.http);
+ newhandle->req.p.http = NULL;
Curl_close(&newhandle);
rv = CURL_PUSH_DENY;
goto fail;
@@ -667,7 +671,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
return 0;
}
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream) {
H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
stream_id));
@@ -783,7 +787,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -849,7 +853,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
}
H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
nghttp2_http2_strerror(error_code), error_code, stream_id));
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -894,7 +898,7 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream || !stream->bodystarted) {
return 0;
}
@@ -952,9 +956,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream) {
- failf(data_s, "Internal NULL stream! 5\n");
+ failf(data_s, "Internal NULL stream!");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -1100,7 +1104,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -1161,7 +1165,7 @@ static void populate_settings(struct connectdata *conn,
void Curl_http2_done(struct Curl_easy *data, bool premature)
{
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
struct http_conn *httpc = &data->conn->proto.httpc;
/* there might be allocated resources done before this got the 'h2' pointer
@@ -1207,19 +1211,12 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
}
http->stream_id = 0;
}
-
- if(0 == nghttp2_session_check_request_allowed(httpc->h2)) {
- /* No more requests are allowed in the current session, so the connection
- may not be reused. This is set when a GOAWAY frame has been received or
- when the limit of stream identifiers has been reached. */
- connclose(data->conn, "http/2: No new requests allowed");
- }
}
/*
* Initialize nghttp2 for a Curl connection
*/
-static CURLcode http2_init(struct connectdata *conn)
+static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
{
if(!conn->proto.httpc.h2) {
int rc;
@@ -1232,7 +1229,7 @@ static CURLcode http2_init(struct connectdata *conn)
rc = nghttp2_session_callbacks_new(&callbacks);
if(rc) {
- failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
+ failf(data, "Couldn't initialize nghttp2 callbacks!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */
}
@@ -1261,7 +1258,7 @@ static CURLcode http2_init(struct connectdata *conn)
nghttp2_session_callbacks_del(callbacks);
if(rc) {
- failf(conn->data, "Couldn't initialize nghttp2!");
+ failf(data, "Couldn't initialize nghttp2!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */
}
}
@@ -1278,7 +1275,8 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
ssize_t binlen;
char *base64;
size_t blen;
- struct SingleRequest *k = &conn->data->req;
+ struct Curl_easy *data = conn->data;
+ struct SingleRequest *k = &data->req;
uint8_t *binsettings = conn->proto.httpc.binsettings;
struct http_conn *httpc = &conn->proto.httpc;
@@ -1288,14 +1286,14 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
httpc->local_settings,
httpc->local_settings_num);
- if(!binlen) {
- failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
+ if(binlen <= 0) {
+ failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
Curl_dyn_free(req);
return CURLE_FAILED_INIT;
}
conn->proto.httpc.binlen = binlen;
- result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
+ result = Curl_base64url_encode(data, (const char *)binsettings, binlen,
&base64, &blen);
if(result) {
Curl_dyn_free(req);
@@ -1329,14 +1327,13 @@ static int should_close_session(struct http_conn *httpc)
* This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err.
*/
-static int h2_process_pending_input(struct connectdata *conn,
+static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc,
CURLcode *err)
{
ssize_t nread;
char *inbuf;
ssize_t rv;
- struct Curl_easy *data = conn->data;
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
@@ -1345,7 +1342,7 @@ static int h2_process_pending_input(struct connectdata *conn,
if(rv < 0) {
failf(data,
"h2_process_pending_input: nghttp2_session_mem_recv() returned "
- "%zd:%s\n", rv, nghttp2_strerror((int)rv));
+ "%zd:%s", rv, nghttp2_strerror((int)rv));
*err = CURLE_RECV_ERROR;
return -1;
}
@@ -1371,6 +1368,14 @@ static int h2_process_pending_input(struct connectdata *conn,
return -1;
}
+ if(nghttp2_session_check_request_allowed(httpc->h2) == 0) {
+ /* No more requests are allowed in the current session, so
+ the connection may not be reused. This is set when a
+ GOAWAY frame has been received or when the limit of stream
+ identifiers has been reached. */
+ connclose(data->conn, "http/2: No new requests allowed");
+ }
+
if(should_close_session(httpc)) {
H2BUGF(infof(data,
"h2_process_pending_input: nothing to do in this session\n"));
@@ -1378,19 +1383,19 @@ static int h2_process_pending_input(struct connectdata *conn,
*err = CURLE_HTTP2;
else {
/* not an error per se, but should still close the connection */
- connclose(conn, "GOAWAY received");
+ connclose(data->conn, "GOAWAY received");
*err = CURLE_OK;
}
return -1;
}
-
return 0;
}
/*
* Called from transfer.c:done_sending when we stop uploading.
*/
-CURLcode Curl_http2_done_sending(struct connectdata *conn)
+CURLcode Curl_http2_done_sending(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -1398,7 +1403,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
(conn->handler == &Curl_handler_http2)) {
/* make sure this is only attempted for HTTP/2 transfers */
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct http_conn *httpc = &conn->proto.httpc;
nghttp2_session *h2 = httpc->h2;
@@ -1411,13 +1416,11 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
/* resume sending here to trigger the callback to get called again so
that it can signal EOF to nghttp2 */
(void)nghttp2_session_resume_data(h2, stream->stream_id);
-
- (void)h2_process_pending_input(conn, httpc, &result);
+ (void)h2_process_pending_input(data, httpc, &result);
}
/* If nghttp2 still has pending frames unsent */
if(nghttp2_session_want_write(h2)) {
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
int rv;
@@ -1448,7 +1451,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
drained_transfer(data, httpc);
if(httpc->pause_stream_id == 0) {
- if(h2_process_pending_input(conn, httpc, err) != 0) {
+ if(h2_process_pending_input(data, httpc, err) != 0) {
return -1;
}
}
@@ -1494,10 +1497,9 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
break;
len = lf + 1 - trailp;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
+ Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
/* pass the trailers one by one to the callback */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, trailp, len);
if(result) {
*err = result;
return -1;
@@ -1522,7 +1524,7 @@ static void h2_pri_spec(struct Curl_easy *data,
nghttp2_priority_spec *pri_spec)
{
struct HTTP *depstream = (data->set.stream_depends_on?
- data->set.stream_depends_on->req.protop:NULL);
+ data->set.stream_depends_on->req.p.http:NULL);
int32_t depstream_id = depstream? depstream->stream_id:0;
nghttp2_priority_spec_init(pri_spec, depstream_id, data->set.stream_weight,
data->set.stream_depends_e);
@@ -1539,7 +1541,7 @@ static void h2_pri_spec(struct Curl_easy *data,
static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2)
{
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
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) ) {
@@ -1561,15 +1563,13 @@ static int h2_session_send(struct Curl_easy *data,
return nghttp2_session_send(h2);
}
-static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
- CURLcode result = CURLE_OK;
- ssize_t rv;
ssize_t nread;
+ struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc;
- struct Curl_easy *data = conn->data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
@@ -1632,8 +1632,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
/* We have paused nghttp2, but we have no pause data (see
on_data_chunk_recv). */
httpc->pause_stream_id = 0;
- if(h2_process_pending_input(conn, httpc, &result) != 0) {
- *err = result;
+ if(h2_process_pending_input(data, httpc, err) != 0) {
return -1;
}
}
@@ -1661,8 +1660,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
frames, then we have to call it again with 0-length data.
Without this, on_stream_close callback will not be called,
and stream could be hanged. */
- if(h2_process_pending_input(conn, httpc, &result) != 0) {
- *err = result;
+ if(h2_process_pending_input(data, httpc, err) != 0) {
return -1;
}
}
@@ -1688,7 +1686,6 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
return -1;
}
else {
- char *inbuf;
/* remember where to store incoming data for this stream and how big the
buffer is */
stream->mem = mem;
@@ -1697,16 +1694,15 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
if(httpc->inbuflen == 0) {
nread = ((Curl_recv *)httpc->recv_underlying)(
- conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err);
if(nread == -1) {
- if(result != CURLE_AGAIN)
+ if(*err != CURLE_AGAIN)
failf(data, "Failed receiving HTTP2 data");
else if(stream->closed)
/* received when the stream was already closed! */
return http2_handle_stream_close(conn, data, stream, err);
- *err = result;
return -1;
}
@@ -1719,47 +1715,18 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
H2BUGF(infof(data, "nread=%zd\n", nread));
httpc->inbuflen = nread;
- inbuf = httpc->inbuf;
+
+ DEBUGASSERT(httpc->nread_inbuf == 0);
}
else {
nread = httpc->inbuflen - httpc->nread_inbuf;
- inbuf = httpc->inbuf + httpc->nread_inbuf;
-
+ (void)nread; /* silence warning, used in debug */
H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
nread));
}
- rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
- if(nghttp2_is_fatal((int)rv)) {
- failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n",
- rv, nghttp2_strerror((int)rv));
- *err = CURLE_RECV_ERROR;
- return -1;
- }
- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
- if(nread == rv) {
- H2BUGF(infof(data, "All data in connection buffer processed\n"));
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
- }
- else {
- httpc->nread_inbuf += rv;
- H2BUGF(infof(data, "%zu bytes left in connection buffer\n",
- httpc->inbuflen - httpc->nread_inbuf));
- }
- /* Always send pending frames in nghttp2 session, because
- nghttp2_session_mem_recv() may queue new frame */
- rv = h2_session_send(data, httpc->h2);
- if(rv != 0) {
- *err = CURLE_SEND_ERROR;
+ if(h2_process_pending_input(data, httpc, err) != 0)
return -1;
- }
-
- if(should_close_session(httpc)) {
- H2BUGF(infof(data, "http2_recv: nothing to do in this session\n"));
- *err = CURLE_HTTP2;
- return -1;
- }
}
if(stream->memlen) {
ssize_t retlen = stream->memlen;
@@ -1864,7 +1831,7 @@ static header_instruction inspect_header(const char *name, size_t namelen,
}
}
-static ssize_t http2_send(struct connectdata *conn, int sockindex,
+static ssize_t http2_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
/*
@@ -1873,8 +1840,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
* request.
*/
int rv;
+ struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
nghttp2_nv *nva = NULL;
size_t nheader;
size_t i;
@@ -1888,16 +1856,16 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
(void)sockindex;
- H2BUGF(infof(conn->data, "http2_send len=%zu\n", len));
+ H2BUGF(infof(data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
if(stream->close_handled) {
- infof(conn->data, "stream %d closed\n", stream->stream_id);
+ infof(data, "stream %d closed\n", stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
}
else if(stream->closed) {
- return http2_handle_stream_close(conn, conn->data, stream, err);
+ return http2_handle_stream_close(conn, data, stream, err);
}
/* If stream_id != -1, we have dispatched request HEADERS, and now
are going to send or sending request body in DATA frame */
@@ -1908,7 +1876,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
*err = CURLE_SEND_ERROR;
return -1;
}
- rv = h2_session_send(conn->data, h2);
+ rv = h2_session_send(data, h2);
if(nghttp2_is_fatal(rv)) {
*err = CURLE_SEND_ERROR;
return -1;
@@ -1921,7 +1889,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
stream->upload_len = 0;
if(should_close_session(httpc)) {
- H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -1934,7 +1902,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nghttp2_session_resume_data(h2, stream->stream_id);
}
- H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
+ H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len,
stream->stream_id));
return len;
}
@@ -1978,7 +1946,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[0].valuelen = (size_t)(end - hdbuf);
nva[0].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[0])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
@@ -2000,7 +1968,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[1].valuelen = (size_t)(end - hdbuf);
nva[1].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[1])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
@@ -2013,7 +1981,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[2].valuelen = strlen((char *)nva[2].value);
nva[2].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[2])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
@@ -2073,7 +2041,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[i])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
++i;
@@ -2097,30 +2065,30 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
for(i = 0; i < nheader; ++i) {
acc += nva[i].namelen + nva[i].valuelen;
- H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
+ H2BUGF(infof(data, "h2 header: %.*s:%.*s\n",
nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value));
}
if(acc > MAX_ACC) {
- infof(conn->data, "http2_send: Warning: The cumulative length of all "
- "headers exceeds %zu bytes and that could cause the "
+ infof(data, "http2_send: Warning: The cumulative length of all "
+ "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC);
}
}
- h2_pri_spec(conn->data, &pri_spec);
+ h2_pri_spec(data, &pri_spec);
- H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n",
- nghttp2_session_check_request_allowed(h2), (void *)conn->data));
+ H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n",
+ nghttp2_session_check_request_allowed(h2), (void *)data));
- switch(conn->data->state.httpreq) {
+ switch(data->state.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
case HTTPREQ_POST_MIME:
case HTTPREQ_PUT:
- if(conn->data->state.infilesize != -1)
- stream->upload_left = conn->data->state.infilesize;
+ if(data->state.infilesize != -1)
+ stream->upload_left = data->state.infilesize;
else
/* data sending without specifying the data amount up front */
stream->upload_left = -1; /* unknown, but not zero */
@@ -2128,36 +2096,41 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
data_prd.read_callback = data_source_read_callback;
data_prd.source.ptr = NULL;
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
- &data_prd, conn->data);
+ &data_prd, data);
break;
default:
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
- NULL, conn->data);
+ NULL, data);
}
Curl_safefree(nva);
if(stream_id < 0) {
- H2BUGF(infof(conn->data, "http2_send() send error\n"));
+ H2BUGF(infof(data,
+ "http2_send() nghttp2_submit_request error (%s)%d\n",
+ nghttp2_strerror(stream_id), stream_id));
*err = CURLE_SEND_ERROR;
return -1;
}
- infof(conn->data, "Using Stream ID: %x (easy handle %p)\n",
- stream_id, (void *)conn->data);
+ infof(data, "Using Stream ID: %x (easy handle %p)\n",
+ stream_id, (void *)data);
stream->stream_id = stream_id;
/* this does not call h2_session_send() since there can not have been any
- * priority upodate since the nghttp2_submit_request() call above */
+ * priority update since the nghttp2_submit_request() call above */
rv = nghttp2_session_send(h2);
-
if(rv != 0) {
+ H2BUGF(infof(data,
+ "http2_send() nghttp2_session_send error (%s)%d\n",
+ nghttp2_strerror(rv), rv));
+
*err = CURLE_SEND_ERROR;
return -1;
}
if(should_close_session(httpc)) {
- H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -2179,13 +2152,14 @@ fail:
return -1;
}
-CURLcode Curl_http2_setup(struct connectdata *conn)
+CURLcode Curl_http2_setup(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
- DEBUGASSERT(conn->data->state.buffer);
+ DEBUGASSERT(data->state.buffer);
stream->stream_id = -1;
@@ -2201,18 +2175,18 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
else
conn->handler = &Curl_handler_http2;
- result = http2_init(conn);
+ result = http2_init(data, conn);
if(result) {
Curl_dyn_free(&stream->header_recvbuf);
return result;
}
- infof(conn->data, "Using HTTP2, server supports multi-use\n");
+ infof(data, "Using HTTP2, server supports multi-use\n");
stream->upload_left = 0;
stream->upload_mem = NULL;
stream->upload_len = 0;
- stream->mem = conn->data->state.buffer;
- stream->len = conn->data->set.buffer_size;
+ stream->mem = data->state.buffer;
+ stream->len = data->set.buffer_size;
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
@@ -2224,23 +2198,22 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
conn->httpversion = 20;
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
- multi_connchanged(conn->data->multi);
+ infof(data, "Connection state changed (HTTP/2 confirmed)\n");
+ multi_connchanged(data->multi);
return CURLE_OK;
}
-CURLcode Curl_http2_switched(struct connectdata *conn,
+CURLcode Curl_http2_switched(struct Curl_easy *data,
const char *mem, size_t nread)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc;
int rv;
- ssize_t nproc;
- struct Curl_easy *data = conn->data;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
- result = Curl_http2_setup(conn);
+ result = Curl_http2_setup(data, conn);
if(result)
return result;
@@ -2249,7 +2222,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
conn->recv[FIRSTSOCKET] = http2_recv;
conn->send[FIRSTSOCKET] = http2_send;
- if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
+ if(data->req.upgr101 == UPGR101_RECEIVED) {
/* stream 1 is opened implicitly on upgrade */
stream->stream_id = 1;
/* queue SETTINGS frame (again) */
@@ -2299,52 +2272,24 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
data into stream->mem, overwriting data already there. */
if(H2_BUFSIZE < nread) {
failf(data, "connection buffer size is too small to store data following "
- "HTTP Upgrade response header: buflen=%zu, datalen=%zu",
+ "HTTP Upgrade response header: buflen=%d, datalen=%zu",
H2_BUFSIZE, nread);
return CURLE_HTTP2;
}
- infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer"
- " after upgrade: len=%zu\n",
+ infof(data, "Copying HTTP/2 data in stream buffer to connection buffer"
+ " after upgrade: len=%zu\n",
nread);
if(nread)
memcpy(httpc->inbuf, mem, nread);
- httpc->inbuflen = nread;
-
- nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf,
- httpc->inbuflen);
-
- if(nghttp2_is_fatal((int)nproc)) {
- failf(data, "nghttp2_session_mem_recv() failed: %s(%d)",
- nghttp2_strerror((int)nproc), (int)nproc);
- return CURLE_HTTP2;
- }
- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
-
- if((ssize_t)nread == nproc) {
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
- }
- else {
- httpc->nread_inbuf += nproc;
- }
-
- /* Try to send some frames since we may read SETTINGS already. */
- rv = h2_session_send(data, httpc->h2);
+ httpc->inbuflen = nread;
- if(rv != 0) {
- failf(data, "nghttp2_session_send() failed: %s(%d)",
- nghttp2_strerror(rv), rv);
- return CURLE_HTTP2;
- }
+ DEBUGASSERT(httpc->nread_inbuf == 0);
- if(should_close_session(httpc)) {
- H2BUGF(infof(data,
- "nghttp2_session_send(): nothing to do in this session\n"));
+ if(-1 == h2_process_pending_input(data, httpc, &result))
return CURLE_HTTP2;
- }
return CURLE_OK;
}
@@ -2358,7 +2303,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
return CURLE_OK;
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
else {
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct http_conn *httpc = &data->conn->proto.httpc;
uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE;
int rv = nghttp2_session_set_local_window_size(httpc->h2,
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index e82b21280..119e584a8 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -44,14 +44,15 @@ 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);
-CURLcode Curl_http2_setup(struct connectdata *conn);
-CURLcode Curl_http2_switched(struct connectdata *conn,
- const char *data, size_t nread);
+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);
/* called from http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn);
void Curl_http2_setup_req(struct Curl_easy *data);
void Curl_http2_done(struct Curl_easy *data, bool premature);
-CURLcode Curl_http2_done_sending(struct connectdata *conn);
+CURLcode Curl_http2_done_sending(struct Curl_easy *data,
+ struct connectdata *conn);
CURLcode Curl_http2_add_child(struct Curl_easy *parent,
struct Curl_easy *child,
bool exclusive);
@@ -64,14 +65,14 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
bool Curl_h2_http_1_1_error(struct connectdata *conn);
#else /* USE_NGHTTP2 */
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup_conn(x) Curl_nop_stmt
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y)
-#define Curl_http2_done_sending(x)
+#define Curl_http2_done_sending(x,y)
#define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x)
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.c b/Utilities/cmcurl/lib/http_aws_sigv4.c
new file mode 100644
index 000000000..8fd1c77e6
--- /dev/null
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.c
@@ -0,0 +1,394 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * 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
+ * are also available at https://curl.haxx.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"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
+#include "urldata.h"
+#include "strcase.h"
+#include "strdup.h"
+#include "vauth/vauth.h"
+#include "vauth/digest.h"
+#include "http_aws_sigv4.h"
+#include "curl_sha256.h"
+#include "transfer.h"
+
+#include "strcase.h"
+#include "parsedate.h"
+#include "sendf.h"
+
+#include <time.h>
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define HMAC_SHA256(k, kl, d, dl, o) \
+ do { \
+ ret = Curl_hmacit(Curl_HMAC_SHA256, \
+ (unsigned char *)k, \
+ (unsigned int)kl, \
+ (unsigned char *)d, \
+ (unsigned int)dl, o); \
+ if(ret != CURLE_OK) { \
+ goto fail; \
+ } \
+ } while(0)
+
+static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l)
+{
+ int i;
+
+ DEBUGASSERT(dst_l >= 65);
+ for(i = 0; i < 32; ++i) {
+ curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ }
+}
+
+CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
+{
+ CURLcode ret = CURLE_OUT_OF_MEMORY;
+ struct connectdata *conn = data->conn;
+ size_t len;
+ const char *tmp0;
+ const char *tmp1;
+ char *provider0_low = NULL;
+ char *provider0_up = NULL;
+ char *provider1_low = NULL;
+ char *provider1_mid = NULL;
+ char *region = NULL;
+ char *service = NULL;
+ const char *hostname = conn->host.name;
+#ifdef DEBUGBUILD
+ char *force_timestamp;
+#endif
+ time_t clock;
+ struct tm tm;
+ char timestamp[17];
+ char date[9];
+ const char *content_type = Curl_checkheaders(data, "Content-Type");
+ char *canonical_headers = NULL;
+ char *signed_headers = NULL;
+ Curl_HttpReq httpreq;
+ const char *method;
+ const char *post_data = data->set.postfields ? data->set.postfields : "";
+ unsigned char sha_hash[32];
+ char sha_hex[65];
+ char *canonical_request = NULL;
+ 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 : "";
+ char *secret = NULL;
+ unsigned char tmp_sign0[32] = {0};
+ unsigned char tmp_sign1[32] = {0};
+ char *auth_headers = NULL;
+
+ DEBUGASSERT(!proxy);
+ (void)proxy;
+
+ if(Curl_checkheaders(data, "Authorization")) {
+ /* Authorization already present, Bailing out */
+ return CURLE_OK;
+ }
+
+ /*
+ * Parameters parsing
+ * Google and Outscale use the same OSC or GOOG,
+ * but Amazon uses AWS and AMZ for header arguments.
+ * AWS is the default because most of non-amazon providers
+ * are still using aws:amz as a prefix.
+ */
+ tmp0 = data->set.str[STRING_AWS_SIGV4] ?
+ data->set.str[STRING_AWS_SIGV4] : "aws:amz";
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "first provider can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ provider0_low = malloc(len + 1);
+ provider0_up = malloc(len + 1);
+ if(!provider0_low || !provider0_up) {
+ goto fail;
+ }
+ Curl_strntolower(provider0_low, tmp0, len);
+ provider0_low[len] = '\0';
+ Curl_strntoupper(provider0_up, tmp0, len);
+ provider0_up[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "second provider can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ provider1_low = malloc(len + 1);
+ provider1_mid = malloc(len + 1);
+ if(!provider1_low || !provider1_mid) {
+ goto fail;
+ }
+ Curl_strntolower(provider1_low, tmp0, len);
+ provider1_low[len] = '\0';
+ Curl_strntolower(provider1_mid, tmp0, len);
+ provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
+ provider1_mid[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "region can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ region = Curl_memdup(tmp0, len + 1);
+ if(!region) {
+ goto fail;
+ }
+ region[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ service = strdup(tmp0);
+ if(!service) {
+ goto fail;
+ }
+ if(strlen(service) < 1) {
+ infof(data, "service can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ }
+ }
+ }
+ else {
+ provider1_low = Curl_memdup(provider0_low, len + 1);
+ provider1_mid = Curl_memdup(provider0_low, len + 1);
+ if(!provider1_low || !provider1_mid) {
+ goto fail;
+ }
+ provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
+ }
+
+ if(!service) {
+ tmp0 = hostname;
+ tmp1 = strchr(tmp0, '.');
+ len = tmp1 - tmp0;
+ if(!tmp1 || len < 1) {
+ infof(data, "service missing in parameters or hostname\n");
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ service = Curl_memdup(tmp0, len + 1);
+ if(!service) {
+ goto fail;
+ }
+ service[len] = '\0';
+
+ if(!region) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, '.');
+ len = tmp1 - tmp0;
+ if(!tmp1 || len < 1) {
+ infof(data, "region missing in parameters or hostname\n");
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ region = Curl_memdup(tmp0, len + 1);
+ if(!region) {
+ goto fail;
+ }
+ region[len] = '\0';
+ }
+ }
+
+#ifdef DEBUGBUILD
+ force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ clock = 0;
+ else
+ time(&clock);
+#else
+ time(&clock);
+#endif
+ ret = Curl_gmtime(clock, &tm);
+ if(ret != CURLE_OK) {
+ goto fail;
+ }
+ if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
+ goto fail;
+ }
+ memcpy(date, timestamp, sizeof(date));
+ date[sizeof(date) - 1] = 0;
+
+ if(content_type) {
+ content_type = strchr(content_type, ':');
+ if(!content_type) {
+ ret = CURLE_FAILED_INIT;
+ goto fail;
+ }
+ content_type++;
+ /* Skip whitespace now */
+ while(*content_type == ' ' || *content_type == '\t')
+ ++content_type;
+
+ canonical_headers = curl_maprintf("content-type:%s\n"
+ "host:%s\n"
+ "x-%s-date:%s\n",
+ content_type,
+ hostname,
+ provider1_low, timestamp);
+ signed_headers = curl_maprintf("content-type;host;x-%s-date",
+ provider1_low);
+ }
+ else {
+ canonical_headers = curl_maprintf("host:%s\n"
+ "x-%s-date:%s\n",
+ hostname,
+ provider1_low, timestamp);
+ signed_headers = curl_maprintf("host;x-%s-date", provider1_low);
+ }
+
+ if(!canonical_headers || !signed_headers) {
+ goto fail;
+ }
+
+ Curl_sha256it(sha_hash,
+ (const unsigned char *) post_data, strlen(post_data));
+ sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+
+ Curl_http_method(data, conn, &method, &httpreq);
+
+ canonical_request =
+ curl_maprintf("%s\n" /* HTTPRequestMethod */
+ "%s\n" /* CanonicalURI */
+ "%s\n" /* CanonicalQueryString */
+ "%s\n" /* CanonicalHeaders */
+ "%s\n" /* SignedHeaders */
+ "%s", /* HashedRequestPayload in hex */
+ method,
+ data->state.up.path,
+ data->state.up.query ? data->state.up.query : "",
+ canonical_headers,
+ signed_headers,
+ sha_hex);
+ if(!canonical_request) {
+ goto fail;
+ }
+
+ request_type = curl_maprintf("%s4_request", provider0_low);
+ if(!request_type) {
+ goto fail;
+ }
+
+ credential_scope = curl_maprintf("%s/%s/%s/%s",
+ date, region, service, request_type);
+ if(!credential_scope) {
+ goto fail;
+ }
+
+ Curl_sha256it(sha_hash, (unsigned char *) canonical_request,
+ strlen(canonical_request));
+ sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+
+ /*
+ * Google allow to use rsa key instead of HMAC, so this code might change
+ * In the furure, but for now we support only HMAC version
+ */
+ str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
+ "%s\n" /* RequestDateTime */
+ "%s\n" /* CredentialScope */
+ "%s", /* HashedCanonicalRequest in hex */
+ provider0_up,
+ timestamp,
+ credential_scope,
+ sha_hex);
+ if(!str_to_sign) {
+ goto fail;
+ }
+
+ secret = curl_maprintf("%s4%s", provider0_up, passwd);
+ if(!secret) {
+ goto fail;
+ }
+
+ HMAC_SHA256(secret, strlen(secret),
+ date, strlen(date), tmp_sign0);
+ HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
+ region, strlen(region), tmp_sign1);
+ HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
+ service, strlen(service), tmp_sign0);
+ HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
+ request_type, strlen(request_type), tmp_sign1);
+ HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
+ str_to_sign, strlen(str_to_sign), tmp_sign0);
+
+ sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex));
+
+ auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 "
+ "Credential=%s/%s, "
+ "SignedHeaders=%s, "
+ "Signature=%s\r\n"
+ "X-%s-Date: %s\r\n",
+ provider0_up,
+ user,
+ credential_scope,
+ signed_headers,
+ sha_hex,
+ provider1_mid,
+ timestamp);
+ if(!auth_headers) {
+ goto fail;
+ }
+
+ Curl_safefree(data->state.aptr.userpwd);
+ data->state.aptr.userpwd = auth_headers;
+ data->state.authhost.done = TRUE;
+ ret = CURLE_OK;
+
+fail:
+ free(provider0_low);
+ free(provider0_up);
+ free(provider1_low);
+ free(provider1_mid);
+ free(region);
+ free(service);
+ free(canonical_headers);
+ free(signed_headers);
+ free(canonical_request);
+ free(request_type);
+ free(credential_scope);
+ free(str_to_sign);
+ free(secret);
+ return ret;
+}
+
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.h b/Utilities/cmcurl/lib/http_aws_sigv4.h
new file mode 100644
index 000000000..886b31440
--- /dev/null
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_HTTP_AWS_SIGV4_H
+#define HEADER_CURL_HTTP_AWS_SIGV4_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * 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
+ * are also available at https://curl.haxx.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"
+
+/* this is for creating aws_sigv4 header output */
+CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy);
+
+#endif /* HEADER_CURL_HTTP_AWS_SIGV4_H */
diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c
index 767f806c8..beb969588 100644
--- a/Utilities/cmcurl/lib/http_chunks.c
+++ b/Utilities/cmcurl/lib/http_chunks.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -77,21 +77,21 @@
#ifdef CURL_DOES_CONVERSIONS
/* Check for an ASCII hex digit.
We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */
-static bool Curl_isxdigit_ascii(char digit)
+static bool isxdigit_ascii(char digit)
{
return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
- || (digit >= 0x41 && digit <= 0x46) /* A-F */
- || (digit >= 0x61 && digit <= 0x66); /* a-f */
+ || (digit >= 0x41 && digit <= 0x46) /* A-F */
+ || (digit >= 0x61 && digit <= 0x66); /* a-f */
}
#else
-#define Curl_isxdigit_ascii(x) Curl_isxdigit(x)
+#define isxdigit_ascii(x) Curl_isxdigit(x)
#endif
-void Curl_httpchunk_init(struct connectdata *conn)
+void Curl_httpchunk_init(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct Curl_chunker *chunk = &conn->chunk;
chunk->hexindex = 0; /* start at 0 */
- chunk->dataleft = 0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */
Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
}
@@ -107,14 +107,14 @@ void Curl_httpchunk_init(struct connectdata *conn)
* This function always uses ASCII hex values to accommodate non-ASCII hosts.
* For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
*/
-CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
+CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
char *datap,
ssize_t datalen,
ssize_t *wrotep,
CURLcode *extrap)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct Curl_chunker *ch = &conn->chunk;
struct SingleRequest *k = &data->req;
size_t piece;
@@ -126,7 +126,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* the original data is written to the client, but we go on with the
chunk read process, to properly calculate the content length*/
if(data->set.http_te_skip && !k->ignorebody) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
if(result) {
*extrap = result;
return CHUNKE_PASSTHRU_ERROR;
@@ -136,8 +136,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(Curl_isxdigit_ascii(*datap)) {
- if(ch->hexindex < MAXNUM_SIZE) {
+ if(isxdigit_ascii(*datap)) {
+ if(ch->hexindex < CHUNK_MAXNUM_LEN) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
length--;
@@ -158,8 +158,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
ch->hexbuffer[ch->hexindex] = 0;
/* convert to host encoding before calling strtoul */
- result = Curl_convert_from_network(conn->data, ch->hexbuffer,
- ch->hexindex);
+ result = Curl_convert_from_network(data, ch->hexbuffer, ch->hexindex);
if(result) {
/* Curl_convert_from_network calls failf if unsuccessful */
/* Treat it as a bad hex character */
@@ -194,11 +193,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
/* Write the data portion available */
- if(!conn->data->set.http_te_skip && !k->ignorebody) {
- if(!conn->data->set.http_ce_skip && k->writer_stack)
- result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
+ if(!data->set.http_te_skip && !k->ignorebody) {
+ if(!data->set.http_ce_skip && k->writer_stack)
+ result = Curl_unencode_write(data, k->writer_stack, datap, piece);
else
- result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
if(result) {
*extrap = result;
@@ -219,7 +218,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
case CHUNK_POSTLF:
if(*datap == 0x0a) {
/* The last one before we go back to hex state and start all over. */
- Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */
+ Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */
}
else if(*datap != 0x0d)
return CHUNKE_BAD_CHUNK;
@@ -242,14 +241,14 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
tr = Curl_dyn_ptr(&conn->trailer);
trlen = Curl_dyn_len(&conn->trailer);
/* Convert to host encoding before calling Curl_client_write */
- result = Curl_convert_from_network(conn->data, tr, trlen);
+ result = Curl_convert_from_network(data, tr, trlen);
if(result)
/* Curl_convert_from_network calls failf if unsuccessful */
/* Treat it as a bad chunk */
return CHUNKE_BAD_CHUNK;
if(!data->set.http_te_skip) {
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tr, trlen);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tr, trlen);
if(result) {
*extrap = result;
return CHUNKE_PASSTHRU_ERROR;
@@ -309,7 +308,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* Record the length of any data left in the end of the buffer
even if there's no more chunks to read */
- ch->dataleft = curlx_sotouz(length);
+ ch->datasize = curlx_sotouz(length);
return CHUNKE_STOP; /* return stop */
}
diff --git a/Utilities/cmcurl/lib/http_chunks.h b/Utilities/cmcurl/lib/http_chunks.h
index 8f4a33c8e..741a9a3bc 100644
--- a/Utilities/cmcurl/lib/http_chunks.h
+++ b/Utilities/cmcurl/lib/http_chunks.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -26,10 +26,10 @@ struct connectdata;
/*
* The longest possible hexadecimal number we support in a chunked transfer.
- * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul()
- * to convert it, we "only" support 2^32 bytes chunk data.
+ * Neither RFC2616 nor the later HTTP specs define a maximum chunk size.
+ * For 64 bit curl_off_t we support 16 digits. For 32 bit, 8 digits.
*/
-#define MAXNUM_SIZE 16
+#define CHUNK_MAXNUM_LEN (SIZEOF_CURL_OFF_T * 2)
typedef enum {
/* await and buffer all hexadecimal digits until we get one that isn't a
@@ -48,7 +48,7 @@ typedef enum {
big deal. */
CHUNK_POSTLF,
- /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft'
+ /* Used to mark that we're out of the game. NOTE: that there's a 'datasize'
field in the struct that will tell how many bytes that were not passed to
the client in the end of the last buffer! */
CHUNK_STOP,
@@ -83,16 +83,15 @@ typedef enum {
const char *Curl_chunked_strerror(CHUNKcode code);
struct Curl_chunker {
- char hexbuffer[ MAXNUM_SIZE + 1];
- int hexindex;
- ChunkyState state;
curl_off_t datasize;
- size_t dataleft; /* untouched data amount at the end of the last buffer */
+ ChunkyState state;
+ unsigned char hexindex;
+ char hexbuffer[ CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */
};
/* The following functions are defined in http_chunks.c */
-void Curl_httpchunk_init(struct connectdata *conn);
-CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
+void Curl_httpchunk_init(struct Curl_easy *data);
+CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap,
ssize_t length, ssize_t *wrote,
CURLcode *passthru);
diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c
index b06dc0d82..596b215db 100644
--- a/Utilities/cmcurl/lib/http_digest.c
+++ b/Utilities/cmcurl/lib/http_digest.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -41,13 +41,11 @@ Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"
*/
-CURLcode Curl_input_digest(struct connectdata *conn,
+CURLcode Curl_input_digest(struct Curl_easy *data,
bool proxy,
const char *header) /* rest of the *-authenticate:
header */
{
- struct Curl_easy *data = conn->data;
-
/* Point to the correct struct with this */
struct digestdata *digest;
@@ -68,13 +66,13 @@ CURLcode Curl_input_digest(struct connectdata *conn,
return Curl_auth_decode_digest_http_message(header, digest);
}
-CURLcode Curl_output_digest(struct connectdata *conn,
+CURLcode Curl_output_digest(struct Curl_easy *data,
+ struct connectdata *conn,
bool proxy,
const unsigned char *request,
const unsigned char *uripath)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
unsigned char *path = NULL;
char *tmp = NULL;
char *response;
diff --git a/Utilities/cmcurl/lib/http_digest.h b/Utilities/cmcurl/lib/http_digest.h
index 96e39a7dc..106caa7c4 100644
--- a/Utilities/cmcurl/lib/http_digest.h
+++ b/Utilities/cmcurl/lib/http_digest.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -26,11 +26,12 @@
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
/* this is for digest header input */
-CURLcode Curl_input_digest(struct connectdata *conn,
+CURLcode Curl_input_digest(struct Curl_easy *data,
bool proxy, const char *header);
/* this is for creating digest header output */
-CURLcode Curl_output_digest(struct connectdata *conn,
+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 0a19ec2af..d759748f2 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -34,11 +34,10 @@
#include "curl_memory.h"
#include "memdebug.h"
-CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
- const char *header)
+CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy, const char *header)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
size_t len;
/* Point to the username, password, service and host */
@@ -90,7 +89,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
neg_ctx->havenegdata = len != 0;
if(!len) {
if(state == GSS_AUTHSUCC) {
- infof(conn->data, "Negotiate auth restarted\n");
+ infof(data, "Negotiate auth restarted\n");
Curl_http_auth_cleanup_negotiate(conn);
}
else if(state != GSS_AUTHNONE) {
@@ -116,15 +115,14 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
return result;
}
-CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
+CURLcode Curl_output_negotiate(struct Curl_easy *data,
+ struct connectdata *conn, bool proxy)
{
struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
&conn->negotiate;
- struct auth *authp = proxy ? &conn->data->state.authproxy :
- &conn->data->state.authhost;
+ struct auth *authp = proxy ? &data->state.authproxy : &data->state.authhost;
curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state;
- struct Curl_easy *data = conn->data;
char *base64 = NULL;
size_t len = 0;
char *userp;
@@ -147,12 +145,12 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
(*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
- infof(conn->data, "Curl_output_negotiate, "
+ infof(data, "Curl_output_negotiate, "
"no persistent authentication: cleanup existing context");
Curl_http_auth_cleanup_negotiate(conn);
}
if(!neg_ctx->context) {
- result = Curl_input_negotiate(conn, proxy, "Negotiate");
+ result = Curl_input_negotiate(data, conn, proxy, "Negotiate");
if(result == CURLE_AUTH_ERROR) {
/* negotiate auth failed, let's continue unauthenticated to stay
* compatible with the behavior before curl-7_64_0-158-g6c6035532 */
@@ -163,8 +161,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
return result;
}
- result = Curl_auth_create_spnego_message(conn->data,
- neg_ctx, &base64, &len);
+ result = Curl_auth_create_spnego_message(data, neg_ctx, &base64, &len);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http_negotiate.h b/Utilities/cmcurl/lib/http_negotiate.h
index a737f6f78..2640a3ee0 100644
--- a/Utilities/cmcurl/lib/http_negotiate.h
+++ b/Utilities/cmcurl/lib/http_negotiate.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -25,11 +25,12 @@
#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
/* this is for Negotiate header input */
-CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
- const char *header);
+CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy, const char *header);
/* this is for creating Negotiate header output */
-CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
+CURLcode Curl_output_negotiate(struct Curl_easy *data,
+ struct connectdata *conn, bool proxy);
void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index cab543c75..6cb829edf 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -59,7 +59,7 @@
# define DEBUG_OUT(x) Curl_nop_stmt
#endif
-CURLcode Curl_input_ntlm(struct connectdata *conn,
+CURLcode Curl_input_ntlm(struct Curl_easy *data,
bool proxy, /* if proxy or not */
const char *header) /* rest of the www-authenticate:
header */
@@ -68,6 +68,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
struct ntlmdata *ntlm;
curlntlm *state;
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
@@ -79,7 +80,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
header++;
if(*header) {
- result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm);
+ result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm);
if(result)
return result;
@@ -87,17 +88,17 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
}
else {
if(*state == NTLMSTATE_LAST) {
- infof(conn->data, "NTLM auth restarted\n");
+ infof(data, "NTLM auth restarted\n");
Curl_http_auth_cleanup_ntlm(conn);
}
else if(*state == NTLMSTATE_TYPE3) {
- infof(conn->data, "NTLM handshake rejected\n");
+ infof(data, "NTLM handshake rejected\n");
Curl_http_auth_cleanup_ntlm(conn);
*state = NTLMSTATE_NONE;
return CURLE_REMOTE_ACCESS_DENIED;
}
else if(*state >= NTLMSTATE_TYPE1) {
- infof(conn->data, "NTLM handshake failure (internal error)\n");
+ infof(data, "NTLM handshake failure (internal error)\n");
return CURLE_REMOTE_ACCESS_DENIED;
}
@@ -111,7 +112,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
/*
* This is for creating ntlm header output
*/
-CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
+CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
{
char *base64 = NULL;
size_t len = 0;
@@ -131,8 +132,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
struct ntlmdata *ntlm;
curlntlm *state;
struct auth *authp;
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
DEBUGASSERT(conn);
DEBUGASSERT(data);
@@ -142,12 +142,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &data->state.aptr.proxyuserpwd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
- service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
- conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
+ service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
+ data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
hostname = conn->http_proxy.host.name;
ntlm = &conn->proxyntlm;
state = &conn->proxy_ntlm_state;
- authp = &conn->data->state.authproxy;
+ authp = &data->state.authproxy;
#else
return CURLE_NOT_BUILT_IN;
#endif
@@ -156,12 +156,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &data->state.aptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
- service = conn->data->set.str[STRING_SERVICE_NAME] ?
- conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
+ service = data->set.str[STRING_SERVICE_NAME] ?
+ data->set.str[STRING_SERVICE_NAME] : "HTTP";
hostname = conn->host.name;
ntlm = &conn->ntlm;
state = &conn->http_ntlm_state;
- authp = &conn->data->state.authhost;
+ authp = &data->state.authhost;
}
authp->done = FALSE;
@@ -188,7 +188,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
case NTLMSTATE_TYPE1:
default: /* for the weird cases we (re)start here */
/* Create a type-1 message */
- result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
+ result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp,
service, hostname,
ntlm, &base64,
&len);
@@ -210,7 +210,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
case NTLMSTATE_TYPE2:
/* We already received the type-2 message, create a type-3 message */
- result = Curl_auth_create_ntlm_type3_message(conn->data, userp, passwdp,
+ result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp,
ntlm, &base64, &len);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http_ntlm.h b/Utilities/cmcurl/lib/http_ntlm.h
index 3ebdf979e..5b4fa00ba 100644
--- a/Utilities/cmcurl/lib/http_ntlm.h
+++ b/Utilities/cmcurl/lib/http_ntlm.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,11 +27,11 @@
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
/* this is for ntlm header input */
-CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
+CURLcode Curl_input_ntlm(struct Curl_easy *data, bool proxy,
const char *header);
/* this is for creating ntlm header output */
-CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
+CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy);
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 f188cbfc6..a03a27fdc 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,6 +27,9 @@
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
#include <curl/curl.h>
+#ifdef USE_HYPER
+#include <hyper.h>
+#endif
#include "sendf.h"
#include "http.h"
#include "url.h"
@@ -47,15 +50,16 @@
* proxy_ssl_connected connection bit when complete. Can be
* called multiple times.
*/
-static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
+static CURLcode https_proxy_connect(struct Curl_easy *data, int sockindex)
{
#ifdef USE_SSL
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
if(!conn->bits.proxy_ssl_connected[sockindex]) {
/* perform SSL initialization for this socket */
result =
- Curl_ssl_connect_nonblocking(conn, sockindex,
+ Curl_ssl_connect_nonblocking(data, conn, sockindex,
&conn->bits.proxy_ssl_connected[sockindex]);
if(result)
/* a failed connection is marked for closure to prevent (bad) re-use or
@@ -64,17 +68,17 @@ static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
}
return result;
#else
- (void) conn;
+ (void) data;
(void) sockindex;
return CURLE_NOT_BUILT_IN;
#endif
}
-CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
+CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
- const CURLcode result = https_proxy_connect(conn, sockindex);
+ const CURLcode result = https_proxy_connect(data, sockindex);
if(result)
return result;
if(!conn->bits.proxy_ssl_connected[sockindex])
@@ -102,9 +106,9 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
* This function might be called several times in the multi interface case
* if the proxy's CONNECT response is not instant.
*/
- prot_save = conn->data->req.protop;
+ prot_save = data->req.p.http;
memset(&http_proxy, 0, sizeof(http_proxy));
- conn->data->req.protop = &http_proxy;
+ data->req.p.http = &http_proxy;
connkeep(conn, "HTTP proxy CONNECT");
/* for the secondary socket (FTP), use the "connect to host"
@@ -124,8 +128,8 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
remote_port = conn->conn_to_port;
else
remote_port = conn->remote_port;
- result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port);
- conn->data->req.protop = prot_save;
+ 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);
@@ -149,15 +153,16 @@ bool Curl_connect_ongoing(struct connectdata *conn)
(conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
}
-static CURLcode connect_init(struct connectdata *conn, bool reinit)
+static CURLcode connect_init(struct Curl_easy *data, bool reinit)
{
struct http_connect_state *s;
+ struct connectdata *conn = data->conn;
if(!reinit) {
DEBUGASSERT(!conn->connect_state);
s = calloc(1, sizeof(struct http_connect_state));
if(!s)
return CURLE_OUT_OF_MEMORY;
- infof(conn->data, "allocate connect buffer!\n");
+ infof(data, "allocate connect buffer!\n");
conn->connect_state = s;
Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
}
@@ -167,29 +172,63 @@ static CURLcode connect_init(struct connectdata *conn, bool reinit)
Curl_dyn_reset(&s->rcvbuf);
}
s->tunnel_state = TUNNEL_INIT;
- s->keepon = TRUE;
+ s->keepon = KEEPON_CONNECT;
s->cl = 0;
s->close_connection = FALSE;
return CURLE_OK;
}
-static void connect_done(struct connectdata *conn)
+static void connect_done(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct http_connect_state *s = conn->connect_state;
s->tunnel_state = TUNNEL_COMPLETE;
Curl_dyn_free(&s->rcvbuf);
- infof(conn->data, "CONNECT phase completed!\n");
+ infof(data, "CONNECT phase completed!\n");
+}
+
+static CURLcode CONNECT_host(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *hostname,
+ int remote_port,
+ char **connecthostp,
+ char **hostp)
+{
+ char *hostheader; /* for CONNECT */
+ char *host = NULL; /* Host: */
+ bool ipv6_ip = conn->bits.ipv6_ip;
+
+ /* the hostname may be different */
+ if(hostname != conn->host.name)
+ ipv6_ip = (strchr(hostname, ':') != NULL);
+ hostheader = /* host:port with IPv6 support */
+ aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+ remote_port);
+ if(!hostheader)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(!Curl_checkProxyheaders(data, conn, "Host")) {
+ host = aprintf("Host: %s\r\n", hostheader);
+ if(!host) {
+ free(hostheader);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ *connecthostp = hostheader;
+ *hostp = host;
+ return CURLE_OK;
}
-static CURLcode CONNECT(struct connectdata *conn,
+static CURLcode CONNECT(struct Curl_easy *data,
int sockindex,
const char *hostname,
int remote_port)
+#ifndef USE_HYPER
{
int subversion = 0;
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t tunnelsocket = conn->sock[sockindex];
struct http_connect_state *s = conn->connect_state;
char *linep;
@@ -207,8 +246,9 @@ static CURLcode CONNECT(struct connectdata *conn,
timediff_t check;
if(TUNNEL_INIT == s->tunnel_state) {
/* BEGIN CONNECT PHASE */
- char *host_port;
struct dynbuf req;
+ char *hostheader = NULL;
+ char *host = NULL;
infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
hostname, remote_port);
@@ -219,50 +259,28 @@ static CURLcode CONNECT(struct connectdata *conn,
free(data->req.newurl);
data->req.newurl = NULL;
- host_port = aprintf("%s:%d", hostname, remote_port);
- if(!host_port)
- return CURLE_OUT_OF_MEMORY;
-
/* initialize a dynamic send-buffer */
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
- /* Setup the proxy-authorization header, if any */
- result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);
+ result = CONNECT_host(data, conn,
+ hostname, remote_port, &hostheader, &host);
+ if(result)
+ return result;
- free(host_port);
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
+ hostheader, TRUE);
if(!result) {
- char *host = NULL;
const char *proxyconn = "";
const char *useragent = "";
const char *httpv =
(conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
- bool ipv6_ip = conn->bits.ipv6_ip;
- char *hostheader;
-
- /* the hostname may be different */
- if(hostname != conn->host.name)
- ipv6_ip = (strchr(hostname, ':') != NULL);
- hostheader = /* host:port with IPv6 support */
- aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
- remote_port);
- if(!hostheader) {
- Curl_dyn_free(&req);
- return CURLE_OUT_OF_MEMORY;
- }
- if(!Curl_checkProxyheaders(conn, "Host")) {
- host = aprintf("Host: %s\r\n", hostheader);
- if(!host) {
- free(hostheader);
- Curl_dyn_free(&req);
- return CURLE_OUT_OF_MEMORY;
- }
- }
- if(!Curl_checkProxyheaders(conn, "Proxy-Connection"))
+ if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
- if(!Curl_checkProxyheaders(conn, "User-Agent") &&
+ if(!Curl_checkProxyheaders(data, conn, "User-Agent") &&
data->set.str[STRING_USERAGENT])
useragent = data->state.aptr.uagent;
@@ -281,12 +299,8 @@ static CURLcode CONNECT(struct connectdata *conn,
useragent,
proxyconn);
- if(host)
- free(host);
- free(hostheader);
-
if(!result)
- result = Curl_add_custom_headers(conn, TRUE, &req);
+ result = Curl_add_custom_headers(data, TRUE, &req);
if(!result)
/* CRLF terminate the request */
@@ -295,13 +309,14 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!result) {
/* Send the connect request to the proxy */
/* BLOCKING */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(&req, data, &data->info.request_size, 0,
sockindex);
}
if(result)
failf(data, "Failed sending CONNECT to proxy");
}
-
+ free(host);
+ free(hostheader);
Curl_dyn_free(&req);
if(result)
return result;
@@ -330,16 +345,16 @@ static CURLcode CONNECT(struct connectdata *conn,
/* Read one byte at a time to avoid a race condition. Wait at most one
second before looping to ensure continuous pgrsUpdates. */
- result = Curl_read(conn, tunnelsocket, &byte, 1, &gotbytes);
+ result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
if(result == CURLE_AGAIN)
/* socket buffer drained, return */
return CURLE_OK;
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
if(result) {
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
break;
}
else if(gotbytes <= 0) {
@@ -353,11 +368,11 @@ static CURLcode CONNECT(struct connectdata *conn,
error = SELECT_ERROR;
failf(data, "Proxy CONNECT aborted");
}
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
break;
}
- if(s->keepon > TRUE) {
+ if(s->keepon == KEEPON_IGNORE) {
/* This means we are currently ignoring a response-body */
if(s->cl) {
@@ -365,7 +380,7 @@ static CURLcode CONNECT(struct connectdata *conn,
and make sure to break out of the loop when we're done! */
s->cl--;
if(s->cl <= 0) {
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
s->tunnel_state = TUNNEL_COMPLETE;
break;
}
@@ -379,11 +394,11 @@ static CURLcode CONNECT(struct connectdata *conn,
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
- r = Curl_httpchunk_read(conn, &byte, 1, &tookcareof, &extra);
+ r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
/* we did the full CONNECT treatment, go COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
}
@@ -410,8 +425,7 @@ static CURLcode CONNECT(struct connectdata *conn,
return result;
/* output debug if that is requested */
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
+ Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
if(!data->set.suppress_connect_headers) {
/* send the header to the callback */
@@ -419,13 +433,12 @@ static CURLcode CONNECT(struct connectdata *conn,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
- result = Curl_client_write(conn, writetype, linep, perline);
+ result = Curl_client_write(data, writetype, linep, perline);
if(result)
return result;
}
data->info.header_size += (long)perline;
- data->req.headerbytecount += (long)perline;
/* Newlines are CRLF, so the CR is ignored as the line isn't
really terminated until the LF comes. Treat a following CR
@@ -439,7 +452,7 @@ static CURLcode CONNECT(struct connectdata *conn,
/* If we get a 407 response code with content length
when we have no auth problem, we must ignore the
whole response-body */
- s->keepon = 2;
+ s->keepon = KEEPON_IGNORE;
if(s->cl) {
infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
@@ -462,12 +475,12 @@ static CURLcode CONNECT(struct connectdata *conn,
/* now parse the chunked piece of data so that we can properly
tell when the stream ends */
- r = Curl_httpchunk_read(conn, linep + 1, 1, &gotbytes,
+ r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
&extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
/* we did the full CONNECT treatment, go to COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
}
@@ -476,14 +489,17 @@ static CURLcode CONNECT(struct connectdata *conn,
/* without content-length or chunked encoding, we
can't keep the connection alive since the close is
the end signal so we bail out at once instead */
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
}
}
else
- s->keepon = FALSE;
- if(!s->cl)
+ s->keepon = KEEPON_DONE;
+
+ if(s->keepon == KEEPON_DONE && !s->cl)
/* we did the full CONNECT treatment, go to COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
+
+ DEBUGASSERT(s->keepon == KEEPON_IGNORE || s->keepon == KEEPON_DONE);
continue;
}
@@ -497,7 +513,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!auth)
return CURLE_OUT_OF_MEMORY;
- result = Curl_http_input_auth(conn, proxy, auth);
+ result = Curl_http_input_auth(data, proxy, auth);
free(auth);
@@ -532,7 +548,7 @@ static CURLcode CONNECT(struct connectdata *conn,
infof(data, "CONNECT responded chunked\n");
s->chunked_encoding = TRUE;
/* init our chunky engine */
- Curl_httpchunk_init(conn);
+ Curl_httpchunk_init(data);
}
}
else if(Curl_compareheader(linep, "Proxy-Connection:", "close"))
@@ -547,7 +563,7 @@ static CURLcode CONNECT(struct connectdata *conn,
Curl_dyn_reset(&s->rcvbuf);
} /* while there's buffer left and loop is requested */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
if(error)
@@ -556,7 +572,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(data->info.httpproxycode/100 != 2) {
/* Deal with the possibly already received authenticate
headers. 'newurl' is set to a new URL if we must loop. */
- result = Curl_http_auth_act(conn);
+ result = Curl_http_auth_act(data);
if(result)
return result;
@@ -569,7 +585,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(s->close_connection && data->req.newurl) {
/* Connection closed by server. Don't use it anymore */
- Curl_closesocket(conn, conn->sock[sockindex]);
+ Curl_closesocket(data, conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
break;
}
@@ -579,7 +595,7 @@ static CURLcode CONNECT(struct connectdata *conn,
* means the HTTP authentication is still going on so if the tunnel
* is complete we start over in INIT state */
if(data->req.newurl && (TUNNEL_COMPLETE == s->tunnel_state)) {
- connect_init(conn, TRUE); /* reinit */
+ connect_init(data, TRUE); /* reinit */
}
} while(data->req.newurl);
@@ -588,14 +604,14 @@ static CURLcode CONNECT(struct connectdata *conn,
if(s->close_connection && data->req.newurl) {
conn->bits.proxy_connect_closed = TRUE;
infof(data, "Connect me again please\n");
- connect_done(conn);
+ connect_done(data);
}
else {
free(data->req.newurl);
data->req.newurl = NULL;
/* failure, close this connection to avoid re-use */
streamclose(conn, "proxy CONNECT failure");
- Curl_closesocket(conn, conn->sock[sockindex]);
+ Curl_closesocket(data, conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
}
@@ -630,6 +646,225 @@ static CURLcode CONNECT(struct connectdata *conn,
Curl_dyn_free(&s->rcvbuf);
return CURLE_OK;
}
+#else
+/* The Hyper version of CONNECT */
+{
+ struct connectdata *conn = data->conn;
+ struct hyptransfer *h = &data->hyp;
+ curl_socket_t tunnelsocket = conn->sock[sockindex];
+ struct http_connect_state *s = conn->connect_state;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ hyper_io *io = NULL;
+ hyper_request *req = NULL;
+ hyper_headers *headers = NULL;
+ hyper_clientconn_options *options = NULL;
+ hyper_task *handshake = NULL;
+ hyper_task *task = NULL; /* for the handshake */
+ hyper_task *sendtask = NULL; /* for the send */
+ hyper_clientconn *client = NULL;
+ hyper_error *hypererr = NULL;
+ char *hostheader = NULL; /* for CONNECT */
+ char *host = NULL; /* Host: */
+
+ if(Curl_connect_complete(conn))
+ return CURLE_OK; /* CONNECT is already completed */
+
+ conn->bits.proxy_connect_closed = FALSE;
+
+ do {
+ switch(s->tunnel_state) {
+ case TUNNEL_INIT:
+ /* BEGIN CONNECT PHASE */
+ io = hyper_io_new();
+ if(!io) {
+ failf(data, "Couldn't create hyper IO");
+ goto error;
+ }
+ /* tell Hyper how to read/write network data */
+ hyper_io_set_userdata(io, data);
+ hyper_io_set_read(io, Curl_hyper_recv);
+ hyper_io_set_write(io, Curl_hyper_send);
+ conn->sockfd = tunnelsocket;
+
+ /* create an executor to poll futures */
+ if(!h->exec) {
+ h->exec = hyper_executor_new();
+ if(!h->exec) {
+ failf(data, "Couldn't create hyper executor");
+ goto error;
+ }
+ }
+
+ options = hyper_clientconn_options_new();
+ if(!options) {
+ failf(data, "Couldn't create hyper client options");
+ goto error;
+ }
+
+ hyper_clientconn_options_exec(options, h->exec);
+
+ /* "Both the `io` and the `options` are consumed in this function
+ call" */
+ handshake = hyper_clientconn_handshake(io, options);
+ if(!handshake) {
+ failf(data, "Couldn't create hyper client handshake");
+ goto error;
+ }
+ io = NULL;
+ options = NULL;
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
+ failf(data, "Couldn't hyper_executor_push the handshake");
+ goto error;
+ }
+ handshake = NULL; /* ownership passed on */
+
+ task = hyper_executor_poll(h->exec);
+ if(!task) {
+ failf(data, "Couldn't hyper_executor_poll the handshake");
+ goto error;
+ }
+
+ client = hyper_task_value(task);
+ hyper_task_free(task);
+ req = hyper_request_new();
+ if(!req) {
+ failf(data, "Couldn't hyper_request_new");
+ goto error;
+ }
+ if(hyper_request_set_method(req, (uint8_t *)"CONNECT",
+ strlen("CONNECT"))) {
+ failf(data, "error setting method");
+ goto error;
+ }
+
+ result = CONNECT_host(data, conn, hostname, remote_port,
+ &hostheader, &host);
+ if(result)
+ goto error;
+
+ if(hyper_request_set_uri(req, (uint8_t *)hostheader,
+ strlen(hostheader))) {
+ failf(data, "error setting path");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
+ hostheader, TRUE);
+ if(result)
+ goto error;
+ Curl_safefree(hostheader);
+
+ /* default is 1.1 */
+ 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");
+ goto error;
+ }
+
+ headers = hyper_request_headers(req);
+ if(!headers) {
+ failf(data, "hyper_request_headers");
+ goto error;
+ }
+ if(host && Curl_hyper_header(data, headers, host))
+ goto error;
+ Curl_safefree(host);
+
+ if(data->state.aptr.proxyuserpwd &&
+ Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd))
+ goto error;
+
+ if(data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ data->state.aptr.uagent &&
+ Curl_hyper_header(data, headers, data->state.aptr.uagent))
+ goto error;
+
+ if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection") &&
+ Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
+ goto error;
+
+ sendtask = hyper_clientconn_send(client, req);
+ if(!sendtask) {
+ failf(data, "hyper_clientconn_send");
+ goto error;
+ }
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
+ failf(data, "Couldn't hyper_executor_push the send");
+ goto error;
+ }
+
+ hyper_clientconn_free(client);
+
+ do {
+ task = hyper_executor_poll(h->exec);
+ if(task) {
+ bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
+ if(error)
+ hypererr = hyper_task_value(task);
+ hyper_task_free(task);
+ if(error)
+ goto error;
+ }
+ } while(task);
+ s->tunnel_state = TUNNEL_CONNECT;
+ /* FALLTHROUGH */
+ case TUNNEL_CONNECT: {
+ int didwhat;
+ bool done = FALSE;
+ result = Curl_hyper_stream(data, conn, &didwhat, &done,
+ CURL_CSELECT_IN | CURL_CSELECT_OUT);
+ if(result)
+ goto error;
+ if(!done)
+ break;
+ fprintf(stderr, "done\n");
+ s->tunnel_state = TUNNEL_COMPLETE;
+ if(h->exec) {
+ hyper_executor_free(h->exec);
+ h->exec = NULL;
+ }
+ if(h->read_waker) {
+ hyper_waker_free(h->read_waker);
+ h->read_waker = NULL;
+ }
+ if(h->write_waker) {
+ hyper_waker_free(h->write_waker);
+ h->write_waker = NULL;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+ } while(data->req.newurl);
+
+ result = CURLE_OK;
+ error:
+ free(host);
+ free(hostheader);
+ if(io)
+ hyper_io_free(io);
+
+ if(options)
+ hyper_clientconn_options_free(options);
+
+ if(handshake)
+ hyper_task_free(handshake);
+
+ if(hypererr) {
+ uint8_t errbuf[256];
+ size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
+ failf(data, "Hyper: %.*s", (int)errlen, errbuf);
+ hyper_error_free(hypererr);
+ }
+ return result;
+}
+
+#endif
void Curl_connect_free(struct Curl_easy *data)
{
@@ -647,21 +882,22 @@ void Curl_connect_free(struct Curl_easy *data)
* this proxy. After that, the socket can be used just as a normal socket.
*/
-CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
int sockindex,
const char *hostname,
int remote_port)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
if(!conn->connect_state) {
- result = connect_init(conn, FALSE);
+ result = connect_init(data, FALSE);
if(result)
return result;
}
- result = CONNECT(conn, sockindex, hostname, remote_port);
+ result = CONNECT(data, sockindex, hostname, remote_port);
if(result || Curl_connect_complete(conn))
- connect_done(conn);
+ connect_done(data);
return result;
}
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index 29988a696..a78db0d04 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,14 +27,14 @@
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
/* ftp can use this as well */
-CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
int tunnelsocket,
const char *hostname, int remote_port);
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
-CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);
bool Curl_connect_complete(struct connectdata *conn);
bool Curl_connect_ongoing(struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/idn_win32.c b/Utilities/cmcurl/lib/idn_win32.c
index 2f5850dd0..1d475a4ef 100644
--- a/Utilities/cmcurl/lib/idn_win32.c
+++ b/Utilities/cmcurl/lib/idn_win32.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/if2ip.c b/Utilities/cmcurl/lib/if2ip.c
index 39388692e..21e00b1f1 100644
--- a/Utilities/cmcurl/lib/if2ip.c
+++ b/Utilities/cmcurl/lib/if2ip.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/if2ip.h b/Utilities/cmcurl/lib/if2ip.h
index f193d4257..e074e476d 100644
--- a/Utilities/cmcurl/lib/if2ip.h
+++ b/Utilities/cmcurl/lib/if2ip.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index cad0e5908..2d8069921 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -88,25 +88,31 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
-static CURLcode imap_do(struct connectdata *conn, bool *done);
-static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+static CURLcode imap_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode imap_do(struct Curl_easy *data, bool *done);
+static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode imap_connect(struct connectdata *conn, bool *done);
-static CURLcode imap_disconnect(struct connectdata *conn, bool dead);
-static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done);
-static int imap_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode imap_setup_connection(struct connectdata *conn);
+static CURLcode imap_connect(struct Curl_easy *data, bool *done);
+static CURLcode imap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done);
+static int imap_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
+static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode imap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
static char *imap_atom(const char *str, bool escape_only);
-static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...);
+static CURLcode imap_sendf(struct Curl_easy *data,
+ struct connectdata *conn, const char *fmt, ...);
static CURLcode imap_parse_url_options(struct connectdata *conn);
-static CURLcode imap_parse_url_path(struct connectdata *conn);
-static CURLcode imap_parse_custom_request(struct connectdata *conn);
-static CURLcode imap_perform_authenticate(struct connectdata *conn,
+static CURLcode imap_parse_url_path(struct Curl_easy *data);
+static CURLcode imap_parse_custom_request(struct Curl_easy *data);
+static CURLcode imap_perform_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp);
-static CURLcode imap_continue_authenticate(struct connectdata *conn,
+static CURLcode imap_continue_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *resp);
static void imap_get_message(char *buffer, char **outptr);
@@ -132,6 +138,7 @@ const struct Curl_handler Curl_handler_imap = {
ZERO_NULL, /* connection_check */
PORT_IMAP, /* defport */
CURLPROTO_IMAP, /* protocol */
+ CURLPROTO_IMAP, /* family */
PROTOPT_CLOSEACTION| /* flags */
PROTOPT_URLOPTIONS
};
@@ -159,6 +166,7 @@ const struct Curl_handler Curl_handler_imaps = {
ZERO_NULL, /* connection_check */
PORT_IMAPS, /* defport */
CURLPROTO_IMAPS, /* protocol */
+ CURLPROTO_IMAP, /* family */
PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
PROTOPT_URLOPTIONS
};
@@ -241,10 +249,10 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
* Checks whether the given string is a valid tagged, untagged or continuation
* response which can be processed by the response handler.
*/
-static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
- int *resp)
+static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *resp)
{
- struct IMAP *imap = conn->data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
const char *id = imapc->resptag;
size_t id_len = strlen(id);
@@ -326,7 +334,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
break;
default:
- failf(conn->data, "Unexpected continuation response");
+ failf(data, "Unexpected continuation response");
*resp = -1;
break;
}
@@ -379,9 +387,9 @@ static void imap_get_message(char *buffer, char **outptr)
*
* This is the ONLY way to change IMAP state!
*/
-static void state(struct connectdata *conn, imapstate newstate)
+static void state(struct Curl_easy *data, imapstate newstate)
{
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc = &data->conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
@@ -404,7 +412,7 @@ static void state(struct connectdata *conn, imapstate newstate)
};
if(imapc->state != newstate)
- infof(conn->data, "IMAP %p state change from %s to %s\n",
+ infof(data, "IMAP %p state change from %s to %s\n",
(void *)imapc, names[imapc->state], names[newstate]);
#endif
@@ -418,7 +426,8 @@ static void state(struct connectdata *conn, imapstate newstate)
* Sends the CAPABILITY command in order to obtain a list of server side
* supported capabilities.
*/
-static CURLcode imap_perform_capability(struct connectdata *conn)
+static CURLcode imap_perform_capability(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
@@ -427,10 +436,10 @@ static CURLcode imap_perform_capability(struct connectdata *conn)
imapc->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPABILITY command */
- result = imap_sendf(conn, "CAPABILITY");
+ result = imap_sendf(data, conn, "CAPABILITY");
if(!result)
- state(conn, IMAP_CAPABILITY);
+ state(data, IMAP_CAPABILITY);
return result;
}
@@ -441,13 +450,14 @@ static CURLcode imap_perform_capability(struct connectdata *conn)
*
* Sends the STARTTLS command to start the upgrade to TLS.
*/
-static CURLcode imap_perform_starttls(struct connectdata *conn)
+static CURLcode imap_perform_starttls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the STARTTLS command */
- CURLcode result = imap_sendf(conn, "STARTTLS");
+ CURLcode result = imap_sendf(data, conn, "STARTTLS");
if(!result)
- state(conn, IMAP_STARTTLS);
+ state(data, IMAP_STARTTLS);
return result;
}
@@ -458,20 +468,21 @@ static CURLcode imap_perform_starttls(struct connectdata *conn)
*
* Performs the upgrade to TLS.
*/
-static CURLcode imap_perform_upgrade_tls(struct connectdata *conn)
+static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Start the SSL connection */
struct imap_conn *imapc = &conn->proto.imapc;
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&imapc->ssldone);
if(!result) {
if(imapc->state != IMAP_UPGRADETLS)
- state(conn, IMAP_UPGRADETLS);
+ state(data, IMAP_UPGRADETLS);
if(imapc->ssldone) {
imap_to_imaps(conn);
- result = imap_perform_capability(conn);
+ result = imap_perform_capability(data, conn);
}
}
@@ -484,7 +495,8 @@ static CURLcode imap_perform_upgrade_tls(struct connectdata *conn)
*
* Sends a clear text LOGIN command to authenticate with.
*/
-static CURLcode imap_perform_login(struct connectdata *conn)
+static CURLcode imap_perform_login(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
char *user;
@@ -493,7 +505,7 @@ static CURLcode imap_perform_login(struct connectdata *conn)
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!conn->bits.user_passwd) {
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
@@ -503,14 +515,14 @@ static CURLcode imap_perform_login(struct connectdata *conn)
passwd = imap_atom(conn->passwd, false);
/* Send the LOGIN command */
- result = imap_sendf(conn, "LOGIN %s %s", user ? user : "",
+ result = imap_sendf(data, conn, "LOGIN %s %s", user ? user : "",
passwd ? passwd : "");
free(user);
free(passwd);
if(!result)
- state(conn, IMAP_LOGIN);
+ state(data, IMAP_LOGIN);
return result;
}
@@ -522,19 +534,21 @@ static CURLcode imap_perform_login(struct connectdata *conn)
* Sends an AUTHENTICATE command allowing the client to login with the given
* SASL authentication mechanism.
*/
-static CURLcode imap_perform_authenticate(struct connectdata *conn,
+static CURLcode imap_perform_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp)
{
CURLcode result = CURLE_OK;
+ (void)data;
if(initresp) {
/* Send the AUTHENTICATE command with the initial response */
- result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp);
+ result = imap_sendf(data, conn, "AUTHENTICATE %s %s", mech, initresp);
}
else {
/* Send the AUTHENTICATE command */
- result = imap_sendf(conn, "AUTHENTICATE %s", mech);
+ result = imap_sendf(data, conn, "AUTHENTICATE %s", mech);
}
return result;
@@ -546,12 +560,13 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn,
*
* Sends SASL continuation data or cancellation.
*/
-static CURLcode imap_continue_authenticate(struct connectdata *conn,
+static CURLcode imap_continue_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *resp)
{
struct imap_conn *imapc = &conn->proto.imapc;
- return Curl_pp_sendf(&imapc->pp, "%s", resp);
+ return Curl_pp_sendf(data, &imapc->pp, "%s", resp);
}
/***********************************************************************
@@ -562,7 +577,8 @@ static CURLcode imap_continue_authenticate(struct connectdata *conn,
* authentication mechanism, falling back to clear text should a common
* mechanism not be available between the client and server.
*/
-static CURLcode imap_perform_authentication(struct connectdata *conn)
+static CURLcode imap_perform_authentication(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
@@ -572,22 +588,23 @@ static CURLcode imap_perform_authentication(struct connectdata *conn)
with and end the connect phase if we don't */
if(imapc->preauth ||
!Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* Calculate the SASL login details */
- result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress);
+ result = Curl_sasl_start(&imapc->sasl, data, conn,
+ imapc->ir_supported, &progress);
if(!result) {
if(progress == SASL_INPROGRESS)
- state(conn, IMAP_AUTHENTICATE);
+ state(data, IMAP_AUTHENTICATE);
else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
- result = imap_perform_login(conn);
+ result = imap_perform_login(data, conn);
else {
/* Other mechanisms not supported */
- infof(conn->data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
}
@@ -601,15 +618,15 @@ static CURLcode imap_perform_authentication(struct connectdata *conn)
*
* Sends a LIST command or an alternative custom request.
*/
-static CURLcode imap_perform_list(struct connectdata *conn)
+static CURLcode imap_perform_list(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
if(imap->custom)
/* Send the custom request */
- result = imap_sendf(conn, "%s%s", imap->custom,
+ result = imap_sendf(data, conn, "%s%s", imap->custom,
imap->custom_params ? imap->custom_params : "");
else {
/* Make sure the mailbox is in the correct atom format if necessary */
@@ -619,13 +636,13 @@ static CURLcode imap_perform_list(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* Send the LIST command */
- result = imap_sendf(conn, "LIST \"%s\" *", mailbox);
+ result = imap_sendf(data, conn, "LIST \"%s\" *", mailbox);
free(mailbox);
}
if(!result)
- state(conn, IMAP_LIST);
+ state(data, IMAP_LIST);
return result;
}
@@ -636,11 +653,11 @@ static CURLcode imap_perform_list(struct connectdata *conn)
*
* Sends a SELECT command to ask the server to change the selected mailbox.
*/
-static CURLcode imap_perform_select(struct connectdata *conn)
+static CURLcode imap_perform_select(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
char *mailbox;
@@ -650,7 +667,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
/* Check we have a mailbox */
if(!imap->mailbox) {
- failf(conn->data, "Cannot SELECT without a mailbox.");
+ failf(data, "Cannot SELECT without a mailbox.");
return CURLE_URL_MALFORMAT;
}
@@ -660,12 +677,12 @@ static CURLcode imap_perform_select(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* Send the SELECT command */
- result = imap_sendf(conn, "SELECT %s", mailbox);
+ result = imap_sendf(data, conn, "SELECT %s", mailbox);
free(mailbox);
if(!result)
- state(conn, IMAP_SELECT);
+ state(data, IMAP_SELECT);
return result;
}
@@ -676,43 +693,39 @@ static CURLcode imap_perform_select(struct connectdata *conn)
*
* Sends a FETCH command to initiate the download of a message.
*/
-static CURLcode imap_perform_fetch(struct connectdata *conn)
+static CURLcode imap_perform_fetch(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = conn->data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
/* Check we have a UID */
if(imap->uid) {
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>",
- imap->uid,
- imap->section ? imap->section : "",
- imap->partial);
+ result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]<%s>",
+ imap->uid, imap->section ? imap->section : "",
+ imap->partial);
else
- result = imap_sendf(conn, "UID FETCH %s BODY[%s]",
- imap->uid,
- imap->section ? imap->section : "");
+ result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]",
+ imap->uid, imap->section ? imap->section : "");
}
else if(imap->mindex) {
-
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
- imap->mindex,
- imap->section ? imap->section : "",
- imap->partial);
+ result = imap_sendf(data, conn, "FETCH %s BODY[%s]<%s>",
+ imap->mindex, imap->section ? imap->section : "",
+ imap->partial);
else
- result = imap_sendf(conn, "FETCH %s BODY[%s]",
- imap->mindex,
- imap->section ? imap->section : "");
+ result = imap_sendf(data, conn, "FETCH %s BODY[%s]",
+ imap->mindex, imap->section ? imap->section : "");
}
else {
- failf(conn->data, "Cannot FETCH without a UID.");
- return CURLE_URL_MALFORMAT;
+ failf(data, "Cannot FETCH without a UID.");
+ return CURLE_URL_MALFORMAT;
}
if(!result)
- state(conn, IMAP_FETCH);
+ state(data, IMAP_FETCH);
return result;
}
@@ -723,11 +736,11 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
*
* Sends an APPEND command to initiate the upload of a message.
*/
-static CURLcode imap_perform_append(struct connectdata *conn)
+static CURLcode imap_perform_append(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
char *mailbox;
/* Check we have a mailbox */
@@ -747,7 +760,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
NULL, MIMESTRATEGY_MAIL);
if(!result)
- if(!Curl_checkheaders(conn, "Mime-Version"))
+ if(!Curl_checkheaders(data, "Mime-Version"))
result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
"Mime-Version: 1.0");
@@ -767,7 +780,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
/* Check we know the size of the upload */
if(data->state.infilesize < 0) {
- failf(data, "Cannot APPEND with unknown input file size\n");
+ failf(data, "Cannot APPEND with unknown input file size");
return CURLE_UPLOAD_FAILED;
}
@@ -777,13 +790,14 @@ static CURLcode imap_perform_append(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* Send the APPEND command */
- result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
+ result = imap_sendf(data, conn,
+ "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
mailbox, data->state.infilesize);
free(mailbox);
if(!result)
- state(conn, IMAP_APPEND);
+ state(data, IMAP_APPEND);
return result;
}
@@ -794,22 +808,23 @@ static CURLcode imap_perform_append(struct connectdata *conn)
*
* Sends a SEARCH command.
*/
-static CURLcode imap_perform_search(struct connectdata *conn)
+static CURLcode imap_perform_search(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = conn->data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
/* Check we have a query string */
if(!imap->query) {
- failf(conn->data, "Cannot SEARCH without a query string.");
+ failf(data, "Cannot SEARCH without a query string.");
return CURLE_URL_MALFORMAT;
}
/* Send the SEARCH command */
- result = imap_sendf(conn, "SEARCH %s", imap->query);
+ result = imap_sendf(data, conn, "SEARCH %s", imap->query);
if(!result)
- state(conn, IMAP_SEARCH);
+ state(data, IMAP_SEARCH);
return result;
}
@@ -820,23 +835,24 @@ static CURLcode imap_perform_search(struct connectdata *conn)
*
* Performs the logout action prior to sclose() being called.
*/
-static CURLcode imap_perform_logout(struct connectdata *conn)
+static CURLcode imap_perform_logout(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the LOGOUT command */
- CURLcode result = imap_sendf(conn, "LOGOUT");
+ CURLcode result = imap_sendf(data, conn, "LOGOUT");
if(!result)
- state(conn, IMAP_LOGOUT);
+ state(data, IMAP_LOGOUT);
return result;
}
/* For the initial server greeting */
-static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
+static CURLcode imap_state_servergreet_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
if(imapcode == IMAP_RESP_PREAUTH) {
@@ -850,16 +866,16 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
return CURLE_WEIRD_SERVER_REPLY;
}
- return imap_perform_capability(conn);
+ return imap_perform_capability(data, conn);
}
/* For CAPABILITY responses */
-static CURLcode imap_state_capability_resp(struct connectdata *conn,
+static CURLcode imap_state_capability_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
@@ -922,31 +938,31 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(imapc->tls_supported)
/* Switch to TLS connection now */
- result = imap_perform_starttls(conn);
+ result = imap_perform_starttls(data, conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
else {
failf(data, "STARTTLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
}
else
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
return result;
}
/* For STARTTLS responses */
-static CURLcode imap_state_starttls_resp(struct connectdata *conn,
+static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
@@ -956,36 +972,36 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
}
else
- result = imap_perform_upgrade_tls(conn);
+ result = imap_perform_upgrade_tls(data, conn);
return result;
}
/* For SASL authentication responses */
-static CURLcode imap_state_auth_resp(struct connectdata *conn,
+static CURLcode imap_state_auth_resp(struct Curl_easy *data,
+ struct connectdata *conn,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
saslprogress progress;
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress);
+ result = Curl_sasl_continue(&imapc->sasl, data, conn, imapcode, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
- state(conn, IMAP_STOP); /* Authenticated */
+ state(data, IMAP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
- result = imap_perform_login(conn);
+ result = imap_perform_login(data, conn);
else {
failf(data, "Authentication cancelled");
result = CURLE_LOGIN_DENIED;
@@ -999,13 +1015,11 @@ static CURLcode imap_state_auth_resp(struct connectdata *conn,
}
/* For LOGIN responses */
-static CURLcode imap_state_login_resp(struct connectdata *conn,
+static CURLcode imap_state_login_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(imapcode != IMAP_RESP_OK) {
@@ -1014,18 +1028,18 @@ static CURLcode imap_state_login_resp(struct connectdata *conn,
}
else
/* End of connect phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For LIST and SEARCH responses */
-static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
+static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- char *line = conn->data->state.buffer;
+ char *line = data->state.buffer;
size_t len = strlen(line);
(void)instate; /* No use for this yet */
@@ -1033,25 +1047,25 @@ static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
if(imapcode == '*') {
/* Temporarily add the LF character back and send as body to the client */
line[len] = '\n';
- result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
}
else if(imapcode != IMAP_RESP_OK)
result = CURLE_QUOTE_ERROR;
else
/* End of DO phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For SELECT responses */
-static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
+static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
@@ -1069,7 +1083,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
/* Check if the UIDVALIDITY has been specified and matches */
if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
!strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
- failf(conn->data, "Mailbox UIDVALIDITY has changed");
+ failf(data, "Mailbox UIDVALIDITY has changed");
result = CURLE_REMOTE_FILE_NOT_FOUND;
}
else {
@@ -1077,11 +1091,11 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
imapc->mailbox = strdup(imap->mailbox);
if(imap->custom)
- result = imap_perform_list(conn);
+ result = imap_perform_list(data);
else if(imap->query)
- result = imap_perform_search(conn);
+ result = imap_perform_search(data, conn);
else
- result = imap_perform_fetch(conn);
+ result = imap_perform_fetch(data, conn);
}
}
else {
@@ -1093,11 +1107,11 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
}
/* For the (first line of the) FETCH responses */
-static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
+static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
+ struct connectdata *conn, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
const char *ptr = data->state.buffer;
@@ -1108,7 +1122,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
if(imapcode != '*') {
Curl_pgrsSetDownloadSize(data, -1);
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return CURLE_REMOTE_FILE_NOT_FOUND;
}
@@ -1143,10 +1157,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
if(!chunk) {
/* no size, we're done with the data */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return CURLE_OK;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
if(result)
return result;
@@ -1176,23 +1190,26 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
else {
/* IMAP download */
data->req.maxdownload = size;
+ /* force a recv/send check of this connection, as the data might've been
+ read off the socket already */
+ data->conn->cselect_bits = CURL_CSELECT_IN;
Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
}
}
else {
/* We don't know how to parse this line */
- failf(pp->conn->data, "Failed to parse FETCH response.");
+ failf(data, "Failed to parse FETCH response.");
result = CURLE_WEIRD_SERVER_REPLY;
}
/* End of DO phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For final FETCH responses performed after the download */
-static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
+static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
@@ -1204,18 +1221,16 @@ static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For APPEND responses */
-static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
+static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* No use for this yet */
if(imapcode != '+') {
@@ -1229,14 +1244,14 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
}
return result;
}
/* For final APPEND responses performed after the upload */
-static CURLcode imap_state_append_final_resp(struct connectdata *conn,
+static CURLcode imap_state_append_final_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
@@ -1248,12 +1263,13 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn,
result = CURLE_UPLOAD_FAILED;
else
/* End of DONE phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
-static CURLcode imap_statemach_act(struct connectdata *conn)
+static CURLcode imap_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
@@ -1261,18 +1277,19 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
size_t nread = 0;
+ (void)data;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
if(imapc->state == IMAP_UPGRADETLS)
- return imap_perform_upgrade_tls(conn);
+ return imap_perform_upgrade_tls(data, conn);
/* Flush any data that needs to be sent */
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
do {
/* Read the response from the server */
- result = Curl_pp_readresp(sock, pp, &imapcode, &nread);
+ result = Curl_pp_readresp(data, sock, pp, &imapcode, &nread);
if(result)
return result;
@@ -1286,55 +1303,55 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
/* We have now received a full IMAP server response */
switch(imapc->state) {
case IMAP_SERVERGREET:
- result = imap_state_servergreet_resp(conn, imapcode, imapc->state);
+ result = imap_state_servergreet_resp(data, imapcode, imapc->state);
break;
case IMAP_CAPABILITY:
- result = imap_state_capability_resp(conn, imapcode, imapc->state);
+ result = imap_state_capability_resp(data, imapcode, imapc->state);
break;
case IMAP_STARTTLS:
- result = imap_state_starttls_resp(conn, imapcode, imapc->state);
+ result = imap_state_starttls_resp(data, imapcode, imapc->state);
break;
case IMAP_AUTHENTICATE:
- result = imap_state_auth_resp(conn, imapcode, imapc->state);
+ result = imap_state_auth_resp(data, conn, imapcode, imapc->state);
break;
case IMAP_LOGIN:
- result = imap_state_login_resp(conn, imapcode, imapc->state);
+ result = imap_state_login_resp(data, imapcode, imapc->state);
break;
case IMAP_LIST:
case IMAP_SEARCH:
- result = imap_state_listsearch_resp(conn, imapcode, imapc->state);
+ result = imap_state_listsearch_resp(data, imapcode, imapc->state);
break;
case IMAP_SELECT:
- result = imap_state_select_resp(conn, imapcode, imapc->state);
+ result = imap_state_select_resp(data, imapcode, imapc->state);
break;
case IMAP_FETCH:
- result = imap_state_fetch_resp(conn, imapcode, imapc->state);
+ result = imap_state_fetch_resp(data, conn, imapcode, imapc->state);
break;
case IMAP_FETCH_FINAL:
- result = imap_state_fetch_final_resp(conn, imapcode, imapc->state);
+ result = imap_state_fetch_final_resp(data, imapcode, imapc->state);
break;
case IMAP_APPEND:
- result = imap_state_append_resp(conn, imapcode, imapc->state);
+ result = imap_state_append_resp(data, imapcode, imapc->state);
break;
case IMAP_APPEND_FINAL:
- result = imap_state_append_final_resp(conn, imapcode, imapc->state);
+ result = imap_state_append_final_resp(data, imapcode, imapc->state);
break;
case IMAP_LOGOUT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
break;
}
} while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp));
@@ -1343,44 +1360,46 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
}
/* Called repeatedly until done from multi.c */
-static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &imapc->ssldone);
if(result || !imapc->ssldone)
return result;
}
- result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE);
+ result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE);
*done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
return result;
}
-static CURLcode imap_block_statemach(struct connectdata *conn,
+static CURLcode imap_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
bool disconnecting)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
while(imapc->state != IMAP_STOP && !result)
- result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting);
+ result = Curl_pp_statemach(data, &imapc->pp, TRUE, disconnecting);
return result;
}
/* Allocate and initialize the struct IMAP for the current Curl_easy if
required */
-static CURLcode imap_init(struct connectdata *conn)
+static CURLcode imap_init(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct IMAP *imap;
- imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
+ imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1);
if(!imap)
result = CURLE_OUT_OF_MEMORY;
@@ -1388,9 +1407,11 @@ static CURLcode imap_init(struct connectdata *conn)
}
/* For the IMAP "protocol connect" and "doing" phases only */
-static int imap_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int imap_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.imapc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.imapc.pp, socks);
}
/***********************************************************************
@@ -1403,9 +1424,10 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks)
* The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE if not.
*/
-static CURLcode imap_connect(struct connectdata *conn, bool *done)
+static CURLcode imap_connect(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
@@ -1414,18 +1436,16 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
/* We always support persistent connections in IMAP */
connkeep(conn, "IMAP default");
- /* Set the default response time-out */
- pp->response_time = RESP_TIMEOUT;
- pp->statemach_act = imap_statemach_act;
- pp->endofresp = imap_endofresp;
- pp->conn = conn;
+ PINGPONG_SETUP(pp, imap_statemachine, imap_endofresp);
/* Set the default preferred authentication type and mechanism */
imapc->preftype = IMAP_TYPE_ANY;
Curl_sasl_init(&imapc->sasl, &saslimap);
+ Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
/* Initialise the pingpong layer */
- Curl_pp_init(pp);
+ Curl_pp_setup(pp);
+ Curl_pp_init(data, pp);
/* Parse the URL options */
result = imap_parse_url_options(conn);
@@ -1433,12 +1453,12 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
return result;
/* Start off waiting for the server greeting response */
- state(conn, IMAP_SERVERGREET);
+ state(data, IMAP_SERVERGREET);
/* Start off with an response id of '*' */
strcpy(imapc->resptag, "*");
- result = imap_multi_statemach(conn, done);
+ result = imap_multi_statemach(data, done);
return result;
}
@@ -1452,12 +1472,12 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
*
* Input argument is already checked for validity.
*/
-static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
(void)premature;
@@ -1474,17 +1494,17 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
/* Handle responses after FETCH or APPEND transfer has finished */
if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
- state(conn, IMAP_FETCH_FINAL);
+ state(data, IMAP_FETCH_FINAL);
else {
/* End the APPEND command first by sending an empty line */
- result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
+ result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", "");
if(!result)
- state(conn, IMAP_APPEND_FINAL);
+ state(data, IMAP_APPEND_FINAL);
}
/* Run the state-machine */
if(!result)
- result = imap_block_statemach(conn, FALSE);
+ result = imap_block_statemach(data, conn, FALSE);
}
/* Cleanup our per-request based variables */
@@ -1511,19 +1531,19 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
* This is the actual DO function for IMAP. Fetch or append a message, or do
* other things according to the options previously setup.
*/
-static CURLcode imap_perform(struct connectdata *conn, bool *connected,
+static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
bool *dophase_done)
{
/* This is IMAP and no proxy */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
bool selected = FALSE;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
- if(conn->data->set.opt_no_body) {
+ if(data->set.opt_no_body) {
/* Requested no body means no transfer */
imap->transfer = FTPTRANSFER_INFO;
}
@@ -1539,36 +1559,36 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
selected = TRUE;
/* Start the first command in the DO phase */
- if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
+ if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
/* APPEND can be executed directly */
- result = imap_perform_append(conn);
+ result = imap_perform_append(data);
else if(imap->custom && (selected || !imap->mailbox))
/* Custom command using the same mailbox or no mailbox */
- result = imap_perform_list(conn);
+ result = imap_perform_list(data);
else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
- result = imap_perform_fetch(conn);
+ result = imap_perform_fetch(data, conn);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
- result = imap_perform_search(conn);
+ result = imap_perform_search(data, conn);
else if(imap->mailbox && !selected &&
(imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
- result = imap_perform_select(conn);
+ result = imap_perform_select(data);
else
/* LIST */
- result = imap_perform_list(conn);
+ result = imap_perform_list(data);
if(result)
return result;
/* Run the state-machine */
- result = imap_multi_statemach(conn, dophase_done);
+ result = imap_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1582,23 +1602,22 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
*
* The input argument is already checked for validity.
*/
-static CURLcode imap_do(struct connectdata *conn, bool *done)
+static CURLcode imap_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
-
*done = FALSE; /* default to false */
/* Parse the URL path */
- result = imap_parse_url_path(conn);
+ result = imap_parse_url_path(data);
if(result)
return result;
/* Parse the custom request */
- result = imap_parse_custom_request(conn);
+ result = imap_parse_custom_request(data);
if(result)
return result;
- result = imap_regular_transfer(conn, done);
+ result = imap_regular_transfer(data, done);
return result;
}
@@ -1610,9 +1629,11 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
* Disconnect from an IMAP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode imap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
struct imap_conn *imapc = &conn->proto.imapc;
+ (void)data;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
@@ -1620,12 +1641,14 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
/* The IMAP session may or may not have been allocated/setup at this
point! */
- if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
- if(!imap_perform_logout(conn))
- (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */
+ if(!dead_connection && conn->bits.protoconnstart) {
+ if(!imap_perform_logout(data, conn))
+ (void)imap_block_statemach(data, conn, TRUE); /* ignore errors */
+ }
/* Disconnect from the server */
Curl_pp_disconnect(&imapc->pp);
+ Curl_dyn_free(&imapc->dyn);
/* Cleanup the SASL module */
Curl_sasl_cleanup(conn, imapc->sasl.authused);
@@ -1638,30 +1661,30 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
}
/* Call this when the DO phase has completed */
-static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
+static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
{
- struct IMAP *imap = conn->data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
(void)connected;
if(imap->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
- Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
+ Curl_setup_transfer(data, -1, -1, FALSE, -1);
return CURLE_OK;
}
/* Called from multi.c while DOing */
-static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = imap_multi_statemach(conn, dophase_done);
+ CURLcode result = imap_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = imap_dophase_done(conn, FALSE /* not connected */);
+ result = imap_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -1676,12 +1699,11 @@ static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
-static CURLcode imap_regular_transfer(struct connectdata *conn,
+static CURLcode imap_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
@@ -1693,19 +1715,20 @@ static CURLcode imap_regular_transfer(struct connectdata *conn,
Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */
- result = imap_perform(conn, &connected, dophase_done);
+ result = imap_perform(data, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = imap_dophase_done(conn, connected);
+ result = imap_dophase_done(data, connected);
return result;
}
-static CURLcode imap_setup_connection(struct connectdata *conn)
+static CURLcode imap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Initialise the IMAP layer */
- CURLcode result = imap_init(conn);
+ CURLcode result = imap_init(data);
if(result)
return result;
@@ -1723,34 +1746,30 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
*
* Designed to never block.
*/
-static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
+static CURLcode imap_sendf(struct Curl_easy *data,
+ struct connectdata *conn, const char *fmt, ...)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
- char *taggedfmt;
- va_list ap;
DEBUGASSERT(fmt);
- /* Calculate the next command ID wrapping at 3 digits */
- imapc->cmdid = (imapc->cmdid + 1) % 1000;
-
/* Calculate the tag based on the connection ID and command ID */
msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
- 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
-
- /* Prefix the format with the tag */
- taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
- if(!taggedfmt)
- return CURLE_OUT_OF_MEMORY;
+ 'A' + curlx_sltosi(conn->connection_id % 26),
+ (++imapc->cmdid)%1000);
- /* Send the data with the tag */
- va_start(ap, fmt);
- result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
- va_end(ap);
-
- free(taggedfmt);
+ /* start with a blank buffer */
+ Curl_dyn_reset(&imapc->dyn);
+ /* append tag + space + fmt */
+ result = Curl_dyn_addf(&imapc->dyn, "%s %s", imapc->resptag, fmt);
+ if(!result) {
+ va_list ap;
+ va_start(ap, fmt);
+ result = Curl_pp_vsendf(data, &imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap);
+ va_end(ap);
+ }
return result;
}
@@ -1937,12 +1956,11 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
* Parse the URL path into separate path components.
*
*/
-static CURLcode imap_parse_url_path(struct connectdata *conn)
+static CURLcode imap_parse_url_path(struct Curl_easy *data)
{
/* The imap struct is already initialised in imap_connect() */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
const char *begin = &data->state.up.path[1]; /* skip leading slash */
const char *ptr = begin;
@@ -1997,7 +2015,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
return result;
}
- DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value));
+ DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'\n", name, value));
/* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and
PARTIAL) stripping of the trailing slash character if it is present.
@@ -2070,11 +2088,10 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
*
* Parse the custom request.
*/
-static CURLcode imap_parse_custom_request(struct connectdata *conn)
+static CURLcode imap_parse_custom_request(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
if(custom) {
diff --git a/Utilities/cmcurl/lib/imap.h b/Utilities/cmcurl/lib/imap.h
index 4786f5624..ef6515d8c 100644
--- a/Utilities/cmcurl/lib/imap.h
+++ b/Utilities/cmcurl/lib/imap.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -75,13 +75,14 @@ struct imap_conn {
bool preauth; /* Is this connection PREAUTH? */
struct SASL sasl; /* SASL-related parameters */
unsigned int preftype; /* Preferred authentication type */
- int cmdid; /* Last used command ID */
+ unsigned int cmdid; /* Last used command ID */
char resptag[5]; /* Response tag to wait for */
bool tls_supported; /* StartTLS capability supported by server */
bool login_disabled; /* LOGIN command disabled by server */
bool ir_supported; /* Initial response supported by server */
char *mailbox; /* The last selected mailbox */
char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
+ struct dynbuf dyn; /* for the IMAP commands */
};
extern const struct Curl_handler Curl_handler_imap;
diff --git a/Utilities/cmcurl/lib/inet_ntop.h b/Utilities/cmcurl/lib/inet_ntop.h
index 9d3f237f3..067632aae 100644
--- a/Utilities/cmcurl/lib/inet_ntop.h
+++ b/Utilities/cmcurl/lib/inet_ntop.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/inet_pton.c b/Utilities/cmcurl/lib/inet_pton.c
index 9c87a0562..4923cae24 100644
--- a/Utilities/cmcurl/lib/inet_pton.c
+++ b/Utilities/cmcurl/lib/inet_pton.c
@@ -1,6 +1,6 @@
/* This is from the BIND 4.9.4 release, modified to compile by itself */
-/* Copyright (c) 1996 - 2019 by Internet Software Consortium.
+/* Copyright (c) 1996 - 2020 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -112,7 +112,7 @@ inet_pton4(const char *src, unsigned char *dst)
if(val > 255)
return (0);
*tp = (unsigned char)val;
- if(! saw_digit) {
+ if(!saw_digit) {
if(++octets > 4)
return (0);
saw_digit = 1;
diff --git a/Utilities/cmcurl/lib/inet_pton.h b/Utilities/cmcurl/lib/inet_pton.h
index e695af9c6..ec1237309 100644
--- a/Utilities/cmcurl/lib/inet_pton.h
+++ b/Utilities/cmcurl/lib/inet_pton.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 5bd8e7181..46116ce59 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -2,7 +2,7 @@
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
- * Copyright (c) 2004 - 2019 Daniel Stenberg
+ * Copyright (c) 2004 - 2021 Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,14 +45,74 @@
#include "ftp.h"
#include "curl_gssapi.h"
#include "sendf.h"
-#include "curl_sec.h"
+#include "curl_krb5.h"
#include "warnless.h"
+#include "non-ascii.h"
+#include "strcase.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
+static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
+ const char *cmd)
+{
+ ssize_t bytes_written;
+#define SBUF_SIZE 1024
+ char s[SBUF_SIZE];
+ size_t write_len;
+ char *sptr = s;
+ CURLcode result = CURLE_OK;
+#ifdef HAVE_GSSAPI
+ enum protection_level data_sec = conn->data_prot;
+#endif
+
+ if(!cmd)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ write_len = strlen(cmd);
+ if(!write_len || write_len > (sizeof(s) -3))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ memcpy(&s, cmd, write_len);
+ strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
+ write_len += 2;
+ bytes_written = 0;
+
+ result = Curl_convert_to_network(data, s, write_len);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ for(;;) {
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CMD;
+#endif
+ result = Curl_write(data, conn->sock[FIRSTSOCKET], sptr, write_len,
+ &bytes_written);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
+ conn->data_prot = data_sec;
+#endif
+
+ if(result)
+ break;
+
+ Curl_debug(data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
+
+ if(bytes_written != (ssize_t)write_len) {
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ return result;
+}
+
static int
krb5_init(void *app_data)
{
@@ -143,14 +203,13 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to)
}
static int
-krb5_auth(void *app_data, struct connectdata *conn)
+krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
{
int ret = AUTH_OK;
char *p;
const char *host = conn->host.name;
ssize_t nread;
curl_socklen_t l = sizeof(conn->local_addr);
- struct Curl_easy *data = conn->data;
CURLcode result;
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
@@ -183,11 +242,11 @@ krb5_auth(void *app_data, struct connectdata *conn)
for(;;) {
/* this really shouldn't be repeated here, but can't help it */
if(service == srv_host) {
- result = Curl_ftpsend(conn, "AUTH GSSAPI");
+ result = ftpsend(data, conn, "AUTH GSSAPI");
if(result)
return -2;
- if(Curl_GetFTPResponse(&nread, conn, NULL))
+ if(Curl_GetFTPResponse(data, &nread, NULL))
return -1;
if(data->state.buffer[0] != '3')
@@ -260,7 +319,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
cmd = aprintf("ADAT %s", p);
if(cmd)
- result = Curl_ftpsend(conn, cmd);
+ result = ftpsend(data, conn, cmd);
else
result = CURLE_OUT_OF_MEMORY;
@@ -272,7 +331,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
break;
}
- if(Curl_GetFTPResponse(&nread, conn, NULL)) {
+ if(Curl_GetFTPResponse(data, &nread, NULL)) {
ret = -1;
break;
}
@@ -326,16 +385,528 @@ static void krb5_end(void *app_data)
}
}
-struct Curl_sec_client_mech Curl_krb5_client_mech = {
- "GSSAPI",
- sizeof(gss_ctx_id_t),
- krb5_init,
- krb5_auth,
- krb5_end,
- krb5_check_prot,
- krb5_overhead,
- krb5_encode,
- krb5_decode
+static struct Curl_sec_client_mech Curl_krb5_client_mech = {
+ "GSSAPI",
+ sizeof(gss_ctx_id_t),
+ krb5_init,
+ krb5_auth,
+ krb5_end,
+ krb5_check_prot,
+ krb5_overhead,
+ krb5_encode,
+ krb5_decode
+};
+
+static const struct {
+ enum protection_level level;
+ const char *name;
+} level_names[] = {
+ { PROT_CLEAR, "clear" },
+ { PROT_SAFE, "safe" },
+ { PROT_CONFIDENTIAL, "confidential" },
+ { PROT_PRIVATE, "private" }
};
+static enum protection_level
+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))
+ return level_names[i].level;
+ return PROT_NONE;
+}
+
+/* Convert a protocol |level| to its char representation.
+ We take an int to catch programming mistakes. */
+static char level_to_char(int level)
+{
+ switch(level) {
+ case PROT_CLEAR:
+ return 'C';
+ case PROT_SAFE:
+ return 'S';
+ case PROT_CONFIDENTIAL:
+ return 'E';
+ case PROT_PRIVATE:
+ return 'P';
+ case PROT_CMD:
+ /* Fall through */
+ default:
+ /* Those 2 cases should not be reached! */
+ break;
+ }
+ DEBUGASSERT(0);
+ /* Default to the most secure alternative. */
+ return 'P';
+}
+
+/* Send an FTP command defined by |message| and the optional arguments. The
+ function returns the ftp_code. If an error occurs, -1 is returned. */
+static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
+{
+ int ftp_code;
+ ssize_t nread = 0;
+ va_list args;
+ char print_buffer[50];
+
+ va_start(args, message);
+ mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
+ va_end(args);
+
+ if(ftpsend(data, data->conn, print_buffer)) {
+ ftp_code = -1;
+ }
+ else {
+ if(Curl_GetFTPResponse(data, &nread, &ftp_code))
+ ftp_code = -1;
+ }
+
+ (void)nread; /* Unused */
+ return ftp_code;
+}
+
+/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
+ saying whether an error occurred or CURLE_OK if |len| was read. */
+static CURLcode
+socket_read(curl_socket_t fd, void *to, size_t len)
+{
+ char *to_p = to;
+ CURLcode result;
+ ssize_t nread = 0;
+
+ while(len > 0) {
+ result = Curl_read_plain(fd, to_p, len, &nread);
+ if(!result) {
+ len -= nread;
+ to_p += nread;
+ }
+ else {
+ if(result == CURLE_AGAIN)
+ continue;
+ return result;
+ }
+ }
+ return CURLE_OK;
+}
+
+
+/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a
+ CURLcode saying whether an error occurred or CURLE_OK if |len| was
+ written. */
+static CURLcode
+socket_write(struct Curl_easy *data, curl_socket_t fd, const void *to,
+ size_t len)
+{
+ const char *to_p = to;
+ CURLcode result;
+ ssize_t written;
+
+ while(len > 0) {
+ result = Curl_write_plain(data, fd, to_p, len, &written);
+ if(!result) {
+ len -= written;
+ to_p += written;
+ }
+ else {
+ if(result == CURLE_AGAIN)
+ continue;
+ return result;
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode read_data(struct connectdata *conn,
+ curl_socket_t fd,
+ struct krb5buffer *buf)
+{
+ int len;
+ CURLcode result;
+
+ result = socket_read(fd, &len, sizeof(len));
+ if(result)
+ return result;
+
+ if(len) {
+ /* only realloc if there was a length */
+ len = ntohl(len);
+ buf->data = Curl_saferealloc(buf->data, len);
+ }
+ if(!len || !buf->data)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = socket_read(fd, buf->data, len);
+ if(result)
+ return result;
+ buf->size = conn->mech->decode(conn->app_data, buf->data, len,
+ conn->data_prot, conn);
+ buf->index = 0;
+ return CURLE_OK;
+}
+
+static size_t
+buffer_read(struct krb5buffer *buf, void *data, size_t len)
+{
+ if(buf->size - buf->index < len)
+ len = buf->size - buf->index;
+ memcpy(data, (char *)buf->data + buf->index, len);
+ buf->index += len;
+ return len;
+}
+
+/* Matches Curl_recv signature */
+static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
+ char *buffer, size_t len, CURLcode *err)
+{
+ size_t bytes_read;
+ size_t total_read = 0;
+ struct connectdata *conn = data->conn;
+ curl_socket_t fd = conn->sock[sockindex];
+
+ *err = CURLE_OK;
+
+ /* Handle clear text response. */
+ if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
+ return sread(fd, buffer, len);
+
+ if(conn->in_buffer.eof_flag) {
+ conn->in_buffer.eof_flag = 0;
+ return 0;
+ }
+
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+
+ while(len > 0) {
+ if(read_data(conn, fd, &conn->in_buffer))
+ return -1;
+ if(conn->in_buffer.size == 0) {
+ if(bytes_read > 0)
+ conn->in_buffer.eof_flag = 1;
+ return bytes_read;
+ }
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+ }
+ return total_read;
+}
+
+/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
+ and negotiating with the server. |from| can be NULL. */
+static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t fd, const char *from, int length)
+{
+ int bytes, htonl_bytes; /* 32-bit integers for htonl */
+ char *buffer = NULL;
+ char *cmd_buffer;
+ size_t cmd_size = 0;
+ CURLcode error;
+ enum protection_level prot_level = conn->data_prot;
+ bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
+
+ DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
+
+ if(iscmd) {
+ if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5))
+ prot_level = PROT_PRIVATE;
+ else
+ prot_level = conn->command_prot;
+ }
+ bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
+ (void **)&buffer);
+ if(!buffer || bytes <= 0)
+ return; /* error */
+
+ if(iscmd) {
+ error = Curl_base64_encode(data, buffer, curlx_sitouz(bytes),
+ &cmd_buffer, &cmd_size);
+ if(error) {
+ free(buffer);
+ return; /* error */
+ }
+ if(cmd_size > 0) {
+ static const char *enc = "ENC ";
+ static const char *mic = "MIC ";
+ if(prot_level == PROT_PRIVATE)
+ socket_write(data, fd, enc, 4);
+ else
+ socket_write(data, fd, mic, 4);
+
+ socket_write(data, fd, cmd_buffer, cmd_size);
+ socket_write(data, fd, "\r\n", 2);
+ infof(data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
+ cmd_buffer);
+ free(cmd_buffer);
+ }
+ }
+ else {
+ htonl_bytes = htonl(bytes);
+ socket_write(data, fd, &htonl_bytes, sizeof(htonl_bytes));
+ socket_write(data, fd, buffer, curlx_sitouz(bytes));
+ }
+ free(buffer);
+}
+
+static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t fd, const char *buffer, size_t length)
+{
+ 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) {
+ if(length < (size_t)len)
+ len = length;
+
+ do_sec_send(data, conn, fd, buffer, curlx_sztosi(len));
+ length -= len;
+ buffer += len;
+ tx += len;
+ }
+ return tx;
+}
+
+/* Matches Curl_send signature */
+static ssize_t sec_send(struct Curl_easy *data, int sockindex,
+ const void *buffer, size_t len, CURLcode *err)
+{
+ struct connectdata *conn = data->conn;
+ curl_socket_t fd = conn->sock[sockindex];
+ *err = CURLE_OK;
+ return sec_write(data, conn, fd, buffer, len);
+}
+
+int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn,
+ char *buffer, enum protection_level level)
+{
+ /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an
+ int */
+ int decoded_len;
+ char *buf;
+ int ret_code = 0;
+ size_t decoded_sz = 0;
+ CURLcode error;
+
+ (void) data;
+
+ if(!conn->mech)
+ /* not inititalized, return error */
+ return -1;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
+ if(error || decoded_sz == 0)
+ return -1;
+
+ if(decoded_sz > (size_t)INT_MAX) {
+ free(buf);
+ return -1;
+ }
+ decoded_len = curlx_uztosi(decoded_sz);
+
+ decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
+ level, conn);
+ if(decoded_len <= 0) {
+ free(buf);
+ return -1;
+ }
+
+ {
+ buf[decoded_len] = '\n';
+ Curl_debug(data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
+ }
+
+ buf[decoded_len] = '\0';
+ if(decoded_len <= 3)
+ /* suspiciously short */
+ return 0;
+
+ if(buf[3] != '-')
+ /* safe to ignore return code */
+ (void)sscanf(buf, "%d", &ret_code);
+
+ if(buf[decoded_len - 1] == '\n')
+ buf[decoded_len - 1] = '\0';
+ strcpy(buffer, buf);
+ free(buf);
+ return ret_code;
+}
+
+static int sec_set_protection_level(struct Curl_easy *data)
+{
+ int code;
+ struct connectdata *conn = data->conn;
+ enum protection_level level = conn->request_data_prot;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ if(!conn->sec_complete) {
+ infof(data, "Trying to change the protection level after the"
+ " completion of the data exchange.\n");
+ return -1;
+ }
+
+ /* Bail out if we try to set up the same level */
+ if(conn->data_prot == level)
+ return 0;
+
+ if(level) {
+ char *pbsz;
+ static unsigned int buffer_size = 1 << 20; /* 1048576 */
+
+ code = ftp_send_command(data, "PBSZ %u", buffer_size);
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(data, "Failed to set the protection's buffer size.");
+ return -1;
+ }
+ conn->buffer_size = buffer_size;
+
+ pbsz = strstr(data->state.buffer, "PBSZ=");
+ if(pbsz) {
+ /* ignore return code, use default value if it fails */
+ (void)sscanf(pbsz, "PBSZ=%u", &buffer_size);
+ if(buffer_size < conn->buffer_size)
+ conn->buffer_size = buffer_size;
+ }
+ }
+
+ /* Now try to negiociate the protection level. */
+ code = ftp_send_command(data, "PROT %c", level_to_char(level));
+
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(data, "Failed to set the protection level.");
+ return -1;
+ }
+
+ conn->data_prot = level;
+ if(level == PROT_PRIVATE)
+ conn->command_prot = level;
+
+ return 0;
+}
+
+int
+Curl_sec_request_prot(struct connectdata *conn, const char *level)
+{
+ enum protection_level l = name_to_level(level);
+ if(l == PROT_NONE)
+ return -1;
+ DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
+ conn->request_data_prot = l;
+ return 0;
+}
+
+static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
+{
+ int ret;
+ void *tmp_allocation;
+ const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;
+
+ tmp_allocation = realloc(conn->app_data, mech->size);
+ if(tmp_allocation == NULL) {
+ failf(data, "Failed realloc of size %zu", mech->size);
+ mech = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ conn->app_data = tmp_allocation;
+
+ if(mech->init) {
+ ret = mech->init(conn->app_data);
+ if(ret) {
+ infof(data, "Failed initialization for %s. Skipping it.\n",
+ mech->name);
+ return CURLE_FAILED_INIT;
+ }
+ }
+
+ infof(data, "Trying mechanism %s...\n", mech->name);
+ ret = ftp_send_command(data, "AUTH %s", mech->name);
+ if(ret < 0)
+ return CURLE_COULDNT_CONNECT;
+
+ if(ret/100 != 3) {
+ switch(ret) {
+ case 504:
+ infof(data, "Mechanism %s is not supported by the server (server "
+ "returned ftp code: 504).\n", mech->name);
+ break;
+ case 534:
+ infof(data, "Mechanism %s was rejected by the server (server returned "
+ "ftp code: 534).\n", mech->name);
+ break;
+ default:
+ if(ret/100 == 5) {
+ infof(data, "server does not support the security extensions\n");
+ return CURLE_USE_SSL_FAILED;
+ }
+ break;
+ }
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Authenticate */
+ ret = mech->auth(conn->app_data, data, conn);
+
+ if(ret != AUTH_CONTINUE) {
+ if(ret != AUTH_OK) {
+ /* Mechanism has dumped the error to stderr, don't error here. */
+ return CURLE_USE_SSL_FAILED;
+ }
+ DEBUGASSERT(ret == AUTH_OK);
+
+ conn->mech = mech;
+ conn->sec_complete = 1;
+ conn->recv[FIRSTSOCKET] = sec_recv;
+ conn->send[FIRSTSOCKET] = sec_send;
+ conn->recv[SECONDARYSOCKET] = sec_recv;
+ conn->send[SECONDARYSOCKET] = sec_send;
+ conn->command_prot = PROT_SAFE;
+ /* Set the requested protection level */
+ /* BLOCKING */
+ (void)sec_set_protection_level(data);
+ }
+
+ return CURLE_OK;
+}
+
+CURLcode
+Curl_sec_login(struct Curl_easy *data, struct connectdata *conn)
+{
+ return choose_mech(data, conn);
+}
+
+
+void
+Curl_sec_end(struct connectdata *conn)
+{
+ if(conn->mech != NULL && conn->mech->end)
+ conn->mech->end(conn->app_data);
+ free(conn->app_data);
+ conn->app_data = NULL;
+ if(conn->in_buffer.data) {
+ free(conn->in_buffer.data);
+ conn->in_buffer.data = NULL;
+ conn->in_buffer.size = 0;
+ conn->in_buffer.index = 0;
+ conn->in_buffer.eof_flag = 0;
+ }
+ conn->sec_complete = 0;
+ conn->data_prot = PROT_CLEAR;
+ conn->mech = NULL;
+}
+
#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 512def659..307ebebaf 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -100,7 +100,8 @@ struct ldap_urldesc {
#undef LDAPURLDesc
#define LDAPURLDesc struct ldap_urldesc
-static int _ldap_url_parse(const struct connectdata *conn,
+static int _ldap_url_parse(struct Curl_easy *data,
+ const struct connectdata *conn,
LDAPURLDesc **ludp);
static void _ldap_free_urldesc(LDAPURLDesc *ludp);
@@ -126,7 +127,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp);
#endif
-static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
+static CURLcode ldap_do(struct Curl_easy *data, bool *done);
/*
* LDAP protocol handler.
@@ -135,7 +136,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
const struct Curl_handler Curl_handler_ldap = {
"LDAP", /* scheme */
ZERO_NULL, /* setup_connection */
- Curl_ldap, /* do_it */
+ ldap_do, /* do_it */
ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
@@ -150,6 +151,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* connection_check */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_NONE /* flags */
};
@@ -161,7 +163,7 @@ const struct Curl_handler Curl_handler_ldap = {
const struct Curl_handler Curl_handler_ldaps = {
"LDAPS", /* scheme */
ZERO_NULL, /* setup_connection */
- Curl_ldap, /* do_it */
+ ldap_do, /* do_it */
ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
@@ -176,6 +178,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* connection_check */
PORT_LDAPS, /* defport */
CURLPROTO_LDAPS, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_SSL /* flags */
};
#endif
@@ -230,7 +233,7 @@ static int ldap_win_bind_auth(LDAP *server, const char *user,
}
#endif /* #if defined(USE_WINDOWS_SSPI) */
-static int ldap_win_bind(struct connectdata *conn, LDAP *server,
+static int ldap_win_bind(struct Curl_easy *data, LDAP *server,
const char *user, const char *passwd)
{
int rc = LDAP_INVALID_CREDENTIALS;
@@ -238,7 +241,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
PTCHAR inuser = NULL;
PTCHAR inpass = NULL;
- if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
+ if(user && passwd && (data->set.httpauth & CURLAUTH_BASIC)) {
inuser = curlx_convert_UTF8_to_tchar((char *) user);
inpass = curlx_convert_UTF8_to_tchar((char *) passwd);
@@ -249,7 +252,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
}
#if defined(USE_WINDOWS_SSPI)
else {
- rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth);
+ rc = ldap_win_bind_auth(server, user, passwd, data->set.httpauth);
}
#endif
@@ -257,7 +260,14 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
}
#endif /* #if defined(USE_WIN32_LDAP) */
-static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
+#if defined(USE_WIN32_LDAP)
+#define FREE_ON_WINLDAP(x) curlx_unicodefree(x)
+#else
+#define FREE_ON_WINLDAP(x)
+#endif
+
+
+static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
int rc = 0;
@@ -266,7 +276,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
LDAPMessage *ldapmsg = NULL;
LDAPMessage *entryIterator;
int num = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
int ldap_proto = LDAP_VERSION3;
int ldap_ssl = 0;
char *val_b64 = NULL;
@@ -291,7 +301,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#ifdef HAVE_LDAP_URL_PARSE
rc = ldap_url_parse(data->change.url, &ludp);
#else
- rc = _ldap_url_parse(conn, &ludp);
+ rc = _ldap_url_parse(data, conn, &ludp);
#endif
if(rc != 0) {
failf(data, "LDAP local: %s", ldap_err2string(rc));
@@ -463,10 +473,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
#ifdef USE_WIN32_LDAP
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
-#endif
-
-#ifdef USE_WIN32_LDAP
- rc = ldap_win_bind(conn, server, user, passwd);
+ rc = ldap_win_bind(data, server, user, passwd);
#else
rc = ldap_simple_bind_s(server, user, passwd);
#endif
@@ -474,7 +481,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
ldap_proto = LDAP_VERSION2;
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
#ifdef USE_WIN32_LDAP
- rc = ldap_win_bind(conn, server, user, passwd);
+ rc = ldap_win_bind(data, server, user, passwd);
#else
rc = ldap_simple_bind_s(server, user, passwd);
#endif
@@ -507,7 +514,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#if defined(USE_WIN32_LDAP)
TCHAR *attribute;
#else
- char *attribute; /*! suspicious that this isn't 'const' */
+ char *attribute;
#endif
int i;
@@ -530,32 +537,24 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#endif
name_len = strlen(name);
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(result) {
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
-
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) name,
name_len);
if(result) {
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
-
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) {
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
goto quit;
@@ -563,9 +562,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
dlsize += name_len + 5;
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
}
@@ -593,12 +590,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
vals = ldap_get_values_len(server, entryIterator, attribute);
if(vals != NULL) {
for(i = 0; (vals[i] != NULL); i++) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -606,13 +601,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *) attr, attr_len);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -620,12 +613,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -645,9 +636,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
&val_b64_sz);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -656,14 +645,12 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
if(val_b64_sz > 0) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
val_b64_sz);
free(val_b64);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -675,13 +662,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
}
else {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, vals[i]->bv_val,
vals[i]->bv_len);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -692,12 +677,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
dlsize += vals[i]->bv_len;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -713,12 +696,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
/* Free the attribute as we are done with it */
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result)
goto quit;
dlsize++;
@@ -745,9 +726,7 @@ quit:
ldapssl_client_deinit();
#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(host);
-#endif
+ FREE_ON_WINLDAP(host);
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
@@ -834,14 +813,15 @@ static bool split_str(char *str, char ***out, size_t *count)
*
* <hostname> already known from 'conn->host.name'.
* <port> already known from 'conn->remote_port'.
- * extract the rest from 'conn->data->state.path+1'. All fields are optional.
+ * extract the rest from 'data->state.path+1'. All fields are optional.
* e.g.
* ldap://<hostname>:<port>/?<attributes>?<scope>?<filter>
* yields ludp->lud_dn = "".
*
* Defined in RFC4516 section 2.
*/
-static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
+static int _ldap_url_parse2(struct Curl_easy *data,
+ const struct connectdata *conn, LDAPURLDesc *ludp)
{
int rc = LDAP_SUCCESS;
char *p;
@@ -850,10 +830,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
char *query = NULL;
size_t i;
- if(!conn->data ||
- !conn->data->state.up.path ||
- conn->data->state.up.path[0] != '/' ||
- !strncasecompare("LDAP", conn->data->state.up.scheme, 4))
+ if(!data ||
+ !data->state.up.path ||
+ data->state.up.path[0] != '/' ||
+ !strncasecompare("LDAP", data->state.up.scheme, 4))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -861,13 +841,13 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
ludp->lud_host = conn->host.name;
/* Duplicate the path */
- p = path = strdup(conn->data->state.up.path + 1);
+ p = path = strdup(data->state.up.path + 1);
if(!path)
return LDAP_NO_MEMORY;
/* Duplicate the query if present */
- if(conn->data->state.up.query) {
- q = query = strdup(conn->data->state.up.query);
+ if(data->state.up.query) {
+ q = query = strdup(data->state.up.query);
if(!query) {
free(path);
return LDAP_NO_MEMORY;
@@ -883,7 +863,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
LDAP_TRACE(("DN '%s'\n", dn));
/* Unescape the DN */
- result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO);
+ result = Curl_urldecode(data, dn, 0, &unescaped, NULL, REJECT_ZERO);
if(result) {
rc = LDAP_NO_MEMORY;
@@ -945,10 +925,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
char *unescaped;
CURLcode result;
- LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
+ LDAP_TRACE(("attr[%zu] '%s'\n", i, attributes[i]));
/* Unescape the attribute */
- result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
+ result = Curl_urldecode(data, attributes[i], 0, &unescaped, NULL,
REJECT_ZERO);
if(result) {
free(attributes);
@@ -1018,8 +998,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
LDAP_TRACE(("filter '%s'\n", filter));
/* Unescape the filter */
- result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL,
- REJECT_ZERO);
+ result = Curl_urldecode(data, filter, 0, &unescaped, NULL, REJECT_ZERO);
if(result) {
rc = LDAP_NO_MEMORY;
@@ -1057,7 +1036,8 @@ quit:
return rc;
}
-static int _ldap_url_parse(const struct connectdata *conn,
+static int _ldap_url_parse(struct Curl_easy *data,
+ const struct connectdata *conn,
LDAPURLDesc **ludpp)
{
LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
@@ -1067,7 +1047,7 @@ static int _ldap_url_parse(const struct connectdata *conn,
if(!ludp)
return LDAP_NO_MEMORY;
- rc = _ldap_url_parse2(conn, ludp);
+ rc = _ldap_url_parse2(data, conn, ludp);
if(rc != LDAP_SUCCESS) {
_ldap_free_urldesc(ludp);
ludp = NULL;
diff --git a/Utilities/cmcurl/lib/libcurl.rc b/Utilities/cmcurl/lib/libcurl.rc
index 4839d0a65..3f7ae1603 100644
--- a/Utilities/cmcurl/lib/libcurl.rc
+++ b/Utilities/cmcurl/lib/libcurl.rc
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -44,7 +44,7 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
- VALUE "CompanyName", "The curl library, https://curl.haxx.se/\0"
+ VALUE "CompanyName", "The curl library, https://curl.se/\0"
VALUE "FileDescription", "libcurl Shared Library\0"
VALUE "FileVersion", LIBCURL_VERSION "\0"
VALUE "InternalName", "libcurl\0"
@@ -52,7 +52,7 @@ BEGIN
VALUE "ProductName", "The curl library\0"
VALUE "ProductVersion", LIBCURL_VERSION "\0"
VALUE "LegalCopyright", "\xa9 " LIBCURL_COPYRIGHT "\0" /* a9: Copyright symbol */
- VALUE "License", "https://curl.haxx.se/docs/copyright.html\0"
+ VALUE "License", "https://curl.se/docs/copyright.html\0"
END
END
diff --git a/Utilities/cmcurl/lib/llist.c b/Utilities/cmcurl/lib/llist.c
index e7c6f51dc..17a7be166 100644
--- a/Utilities/cmcurl/lib/llist.c
+++ b/Utilities/cmcurl/lib/llist.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -34,7 +34,7 @@
* @unittest: 1300
*/
void
-Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
+Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor)
{
l->size = 0;
l->dtor = dtor;
@@ -54,9 +54,9 @@ Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
* @unittest: 1300
*/
void
-Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
+Curl_llist_insert_next(struct Curl_llist *list, struct Curl_llist_element *e,
const void *p,
- struct curl_llist_element *ne)
+ struct Curl_llist_element *ne)
{
ne->ptr = (void *) p;
if(list->size == 0) {
@@ -90,7 +90,7 @@ Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
* @unittest: 1300
*/
void
-Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
+Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e,
void *user)
{
void *ptr;
@@ -131,7 +131,7 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
}
void
-Curl_llist_destroy(struct curl_llist *list, void *user)
+Curl_llist_destroy(struct Curl_llist *list, void *user)
{
if(list) {
while(list->size > 0)
@@ -140,7 +140,7 @@ Curl_llist_destroy(struct curl_llist *list, void *user)
}
size_t
-Curl_llist_count(struct curl_llist *list)
+Curl_llist_count(struct Curl_llist *list)
{
return list->size;
}
diff --git a/Utilities/cmcurl/lib/llist.h b/Utilities/cmcurl/lib/llist.h
index 0178c4259..ceae2dd1b 100644
--- a/Utilities/cmcurl/lib/llist.h
+++ b/Utilities/cmcurl/lib/llist.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -25,26 +25,26 @@
#include "curl_setup.h"
#include <stddef.h>
-typedef void (*curl_llist_dtor)(void *, void *);
+typedef void (*Curl_llist_dtor)(void *, void *);
-struct curl_llist_element {
+struct Curl_llist_element {
void *ptr;
- struct curl_llist_element *prev;
- struct curl_llist_element *next;
+ struct Curl_llist_element *prev;
+ struct Curl_llist_element *next;
};
-struct curl_llist {
- struct curl_llist_element *head;
- struct curl_llist_element *tail;
- curl_llist_dtor dtor;
+struct Curl_llist {
+ struct Curl_llist_element *head;
+ struct Curl_llist_element *tail;
+ Curl_llist_dtor dtor;
size_t size;
};
-void Curl_llist_init(struct curl_llist *, curl_llist_dtor);
-void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
- const void *, struct curl_llist_element *node);
-void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
+void Curl_llist_init(struct Curl_llist *, Curl_llist_dtor);
+void Curl_llist_insert_next(struct Curl_llist *, struct Curl_llist_element *,
+ const void *, struct Curl_llist_element *node);
+void Curl_llist_remove(struct Curl_llist *, struct Curl_llist_element *,
void *);
-size_t Curl_llist_count(struct curl_llist *);
-void Curl_llist_destroy(struct curl_llist *, void *);
+size_t Curl_llist_count(struct Curl_llist *);
+void Curl_llist_destroy(struct Curl_llist *, void *);
#endif /* HEADER_CURL_LLIST_H */
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 67119cda5..8ae6ac3fa 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index d21625f6b..513ffb2fb 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c
index da75c9f5d..881ee85c3 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/lib/memdebug.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -35,52 +35,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-/*
- * Until 2011-08-17 libcurl's Memory Tracking feature also performed
- * automatic malloc and free filling operations using 0xA5 and 0x13
- * values. Our own preinitialization of dynamically allocated memory
- * might be useful when not using third party memory debuggers, but
- * on the other hand this would fool memory debuggers into thinking
- * that all dynamically allocated memory is properly initialized.
- *
- * As a default setting, libcurl's Memory Tracking feature no longer
- * performs preinitialization of dynamically allocated memory on its
- * own. If you know what you are doing, and really want to retain old
- * behavior, you can achieve this compiling with preprocessor symbols
- * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate
- * values.
- */
-
-#ifdef CURL_MT_MALLOC_FILL
-# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff)
-# error "invalid CURL_MT_MALLOC_FILL or out of range"
-# endif
-#endif
-
-#ifdef CURL_MT_FREE_FILL
-# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff)
-# error "invalid CURL_MT_FREE_FILL or out of range"
-# endif
-#endif
-
-#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL)
-# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL)
-# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL"
-# endif
-#endif
-
-#ifdef CURL_MT_MALLOC_FILL
-# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len))
-#else
-# define mt_malloc_fill(buf,len) Curl_nop_stmt
-#endif
-
-#ifdef CURL_MT_FREE_FILL
-# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len))
-#else
-# define mt_free_fill(buf,len) Curl_nop_stmt
-#endif
-
struct memdebug {
size_t size;
union {
@@ -173,8 +127,6 @@ void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
mem = (Curl_cmalloc)(size);
if(mem) {
- /* fill memory with junk */
- mt_malloc_fill(mem->mem, wantedsize);
mem->size = wantedsize;
}
@@ -321,9 +273,6 @@ void curl_dbg_free(void *ptr, int line, const char *source)
# pragma warning(pop)
#endif
- /* destroy */
- mt_free_fill(mem->mem, mem->size);
-
/* free for real */
(Curl_cfree)(mem);
}
diff --git a/Utilities/cmcurl/lib/memdebug.h b/Utilities/cmcurl/lib/memdebug.h
index 4edafdfb5..8e88cea58 100644
--- a/Utilities/cmcurl/lib/memdebug.h
+++ b/Utilities/cmcurl/lib/memdebug.h
@@ -12,7 +12,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index 6a9b64a2d..abadcb02c 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -1168,6 +1168,7 @@ static void cleanup_part_content(curl_mimepart *part)
part->kind = MIMEKIND_NONE;
part->flags &= ~MIME_FAST_READ;
part->lastreadstatus = 1; /* Successful read status. */
+ part->state.state = MIMESTATE_BEGIN;
}
static void mime_subparts_free(void *ptr)
diff --git a/Utilities/cmcurl/lib/mime.h b/Utilities/cmcurl/lib/mime.h
index 50b7ea6b0..56642ae66 100644
--- a/Utilities/cmcurl/lib/mime.h
+++ b/Utilities/cmcurl/lib/mime.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -110,6 +110,7 @@ struct curl_mimepart {
curl_mime *parent; /* Parent mime structure. */
curl_mimepart *nextpart; /* Forward linked list. */
enum mimekind kind; /* The part kind. */
+ unsigned int flags; /* Flags. */
char *data; /* Memory data or file name. */
curl_read_callback readfunc; /* Read function. */
curl_seek_callback seekfunc; /* Seek function. */
@@ -122,7 +123,6 @@ struct curl_mimepart {
char *filename; /* Remote file name. */
char *name; /* Data name. */
curl_off_t datasize; /* Expected data size. */
- unsigned int flags; /* Flags. */
struct mime_state state; /* Current readback state. */
const struct mime_encoder *encoder; /* Content data encoder. */
struct mime_encoder_state encstate; /* Data encoder state. */
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 80735be51..c681248de 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -99,12 +99,12 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
/* Upper-case digits. */
static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-#define OUTCHAR(x) \
- do{ \
+#define OUTCHAR(x) \
+ do { \
if(stream((unsigned char)(x), (FILE *)data) != -1) \
- done++; \
- else \
- return done; /* return immediately on failure */ \
+ done++; \
+ else \
+ return done; /* return immediately on failure */ \
} while(0)
/* Data type to read from the arglist */
@@ -169,7 +169,7 @@ struct nsprintf {
};
struct asprintf {
- struct dynbuf b;
+ struct dynbuf *b;
bool fail; /* if an alloc has failed and thus the output is not the complete
data */
};
@@ -878,7 +878,7 @@ static int dprintf_formatf(
OUTCHAR(' ');
for(point = strnil; *point != '\0'; ++point)
OUTCHAR(*point);
- if(! (p->flags & FLAGS_LEFT))
+ if(!(p->flags & FLAGS_LEFT))
while(width-- > 0)
OUTCHAR(' ');
}
@@ -1042,50 +1042,61 @@ static int alloc_addbyter(int output, FILE *data)
struct asprintf *infop = (struct asprintf *)data;
unsigned char outc = (unsigned char)output;
- if(Curl_dyn_addn(&infop->b, &outc, 1)) {
+ if(Curl_dyn_addn(infop->b, &outc, 1)) {
infop->fail = 1;
return -1; /* fail */
}
return outc; /* fputc() returns like this on success */
}
-char *curl_maprintf(const char *format, ...)
+extern int Curl_dyn_vprintf(struct dynbuf *dyn,
+ const char *format, va_list ap_save);
+
+/* appends the formatted string, returns 0 on success, 1 on error */
+int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
{
- va_list ap_save; /* argument pointer */
int retcode;
struct asprintf info;
- Curl_dyn_init(&info.b, DYN_APRINTF);
+ info.b = dyn;
info.fail = 0;
- va_start(ap_save, format);
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- va_end(ap_save);
if((-1 == retcode) || info.fail) {
- Curl_dyn_free(&info.b);
- return NULL;
+ Curl_dyn_free(info.b);
+ return 1;
}
- if(Curl_dyn_len(&info.b))
- return Curl_dyn_ptr(&info.b);
- return strdup("");
+ return 0;
}
char *curl_mvaprintf(const char *format, va_list ap_save)
{
int retcode;
struct asprintf info;
- Curl_dyn_init(&info.b, DYN_APRINTF);
+ struct dynbuf dyn;
+ info.b = &dyn;
+ Curl_dyn_init(info.b, DYN_APRINTF);
info.fail = 0;
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
if((-1 == retcode) || info.fail) {
- Curl_dyn_free(&info.b);
+ Curl_dyn_free(info.b);
return NULL;
}
- if(Curl_dyn_len(&info.b))
- return Curl_dyn_ptr(&info.b);
+ if(Curl_dyn_len(info.b))
+ return Curl_dyn_ptr(info.b);
return strdup("");
}
+char *curl_maprintf(const char *format, ...)
+{
+ va_list ap_save;
+ char *s;
+ va_start(ap_save, format);
+ s = curl_mvaprintf(format, ap_save);
+ va_end(ap_save);
+ return s;
+}
+
static int storebuffer(int output, FILE *data)
{
char **buffer = (char **)data;
diff --git a/Utilities/cmcurl/lib/mqtt.c b/Utilities/cmcurl/lib/mqtt.c
index f6f441614..2134409cd 100644
--- a/Utilities/cmcurl/lib/mqtt.c
+++ b/Utilities/cmcurl/lib/mqtt.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2019, Björn Stenberg, <bjorn@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
#include "curl_setup.h"
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
#include "urldata.h"
#include <curl/curl.h>
@@ -59,10 +59,12 @@
* Forward declarations.
*/
-static CURLcode mqtt_do(struct connectdata *conn, bool *done);
-static CURLcode mqtt_doing(struct connectdata *conn, bool *done);
-static int mqtt_getsock(struct connectdata *conn, curl_socket_t *sock);
-static CURLcode mqtt_setup_conn(struct connectdata *conn);
+static CURLcode mqtt_do(struct Curl_easy *data, bool *done);
+static CURLcode mqtt_doing(struct Curl_easy *data, bool *done);
+static int mqtt_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *sock);
+static CURLcode mqtt_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* MQTT protocol handler.
@@ -86,34 +88,36 @@ const struct Curl_handler Curl_handler_mqtt = {
ZERO_NULL, /* connection_check */
PORT_MQTT, /* defport */
CURLPROTO_MQTT, /* protocol */
+ CURLPROTO_MQTT, /* family */
PROTOPT_NONE /* flags */
};
-static CURLcode mqtt_setup_conn(struct connectdata *conn)
+static CURLcode mqtt_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
struct MQTT *mq;
- struct Curl_easy *data = conn->data;
- DEBUGASSERT(data->req.protop == NULL);
+ (void)conn;
+ DEBUGASSERT(data->req.p.mqtt == NULL);
mq = calloc(1, sizeof(struct MQTT));
if(!mq)
return CURLE_OUT_OF_MEMORY;
- data->req.protop = mq;
+ data->req.p.mqtt = mq;
return CURLE_OK;
}
-static CURLcode mqtt_send(struct connectdata *conn,
+static CURLcode mqtt_send(struct Curl_easy *data,
char *buf, size_t len)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
- struct MQTT *mq = data->req.protop;
+ struct MQTT *mq = data->req.p.mqtt;
ssize_t n;
- result = Curl_write(conn, sockfd, buf, len, &n);
- if(!result && data->set.verbose)
+ result = Curl_write(data, sockfd, buf, len, &n);
+ if(!result)
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
if(len != (size_t)n) {
size_t nsend = len - n;
@@ -129,20 +133,22 @@ static CURLcode mqtt_send(struct connectdata *conn,
/* Generic function called by the multi interface to figure out what socket(s)
to wait for and for what actions during the DOING and PROTOCONNECT
states */
-static int mqtt_getsock(struct connectdata *conn,
+static int mqtt_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock)
{
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(FIRSTSOCKET);
}
-static CURLcode mqtt_connect(struct connectdata *conn)
+static CURLcode mqtt_connect(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
const size_t client_id_offset = 14;
const size_t packetlen = client_id_offset + MQTT_CLIENTID_LEN;
char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
- const size_t curl_len = strlen("curl");
+ const size_t clen = strlen("curl");
char packet[32] = {
MQTT_MSG_CONNECT, /* packet type */
0x00, /* remaining length */
@@ -156,36 +162,35 @@ static CURLcode mqtt_connect(struct connectdata *conn)
packet[1] = (packetlen - 2) & 0x7f;
packet[client_id_offset - 1] = MQTT_CLIENTID_LEN;
- result = Curl_rand_hex(conn->data, (unsigned char *)&client_id[curl_len],
- MQTT_CLIENTID_LEN - curl_len + 1);
+ result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
+ MQTT_CLIENTID_LEN - clen + 1);
memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN);
- infof(conn->data, "Using client id '%s'\n", client_id);
+ infof(data, "Using client id '%s'\n", client_id);
if(!result)
- result = mqtt_send(conn, packet, packetlen);
+ result = mqtt_send(data, packet, packetlen);
return result;
}
-static CURLcode mqtt_disconnect(struct connectdata *conn)
+static CURLcode mqtt_disconnect(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- result = mqtt_send(conn, (char *)"\xe0\x00", 2);
+ result = mqtt_send(data, (char *)"\xe0\x00", 2);
return result;
}
-static CURLcode mqtt_verify_connack(struct connectdata *conn)
+static CURLcode mqtt_verify_connack(struct Curl_easy *data)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char readbuf[MQTT_CONNACK_LEN];
ssize_t nread;
- struct Curl_easy *data = conn->data;
- result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
+ result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
if(result)
goto fail;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
/* fixme */
if(nread < MQTT_CONNACK_LEN) {
@@ -204,18 +209,18 @@ fail:
return result;
}
-static CURLcode mqtt_get_topic(struct connectdata *conn,
+static CURLcode mqtt_get_topic(struct Curl_easy *data,
char **topic, size_t *topiclen)
{
CURLcode result = CURLE_OK;
- char *path = conn->data->state.up.path;
+ char *path = data->state.up.path;
if(strlen(path) > 1) {
- result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen,
+ result = Curl_urldecode(data, path + 1, 0, topic, topiclen,
REJECT_NADA);
}
else {
- failf(conn->data, "Error: No topic specified.");
+ failf(data, "Error: No topic specified.");
result = CURLE_URL_MALFORMAT;
}
return result;
@@ -238,7 +243,7 @@ static int mqtt_encode_len(char *buf, size_t len)
return i;
}
-static CURLcode mqtt_subscribe(struct connectdata *conn)
+static CURLcode mqtt_subscribe(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
char *topic = NULL;
@@ -247,8 +252,9 @@ static CURLcode mqtt_subscribe(struct connectdata *conn)
size_t packetlen;
char encodedsize[4];
size_t n;
+ struct connectdata *conn = data->conn;
- result = mqtt_get_topic(conn, &topic, &topiclen);
+ result = mqtt_get_topic(data, &topic, &topiclen);
if(result)
goto fail;
@@ -274,7 +280,7 @@ static CURLcode mqtt_subscribe(struct connectdata *conn)
memcpy(&packet[5 + n], topic, topiclen);
packet[5 + n + topiclen] = 0; /* QoS zero */
- result = mqtt_send(conn, (char *)packet, packetlen);
+ result = mqtt_send(data, (char *)packet, packetlen);
fail:
free(topic);
@@ -285,20 +291,20 @@ fail:
/*
* Called when the first byte was already read.
*/
-static CURLcode mqtt_verify_suback(struct connectdata *conn)
+static CURLcode mqtt_verify_suback(struct Curl_easy *data)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char readbuf[MQTT_SUBACK_LEN];
ssize_t nread;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
- result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
+ result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
if(result)
goto fail;
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
/* fixme */
if(nread < MQTT_SUBACK_LEN) {
@@ -316,11 +322,11 @@ fail:
return result;
}
-static CURLcode mqtt_publish(struct connectdata *conn)
+static CURLcode mqtt_publish(struct Curl_easy *data)
{
CURLcode result;
- char *payload = conn->data->set.postfields;
- size_t payloadlen = (size_t)conn->data->set.postfieldsize;
+ char *payload = data->set.postfields;
+ size_t payloadlen;
char *topic = NULL;
size_t topiclen;
unsigned char *pkt = NULL;
@@ -328,8 +334,16 @@ static CURLcode mqtt_publish(struct connectdata *conn)
size_t remaininglength;
size_t encodelen;
char encodedbytes[4];
+ curl_off_t postfieldsize = data->set.postfieldsize;
+
+ if(!payload)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(postfieldsize < 0)
+ payloadlen = strlen(payload);
+ else
+ payloadlen = (size_t)postfieldsize;
- result = mqtt_get_topic(conn, &topic, &topiclen);
+ result = mqtt_get_topic(data, &topic, &topiclen);
if(result)
goto fail;
@@ -353,7 +367,7 @@ static CURLcode mqtt_publish(struct connectdata *conn)
i += topiclen;
memcpy(&pkt[i], payload, payloadlen);
i += payloadlen;
- result = mqtt_send(conn, (char *)pkt, i);
+ result = mqtt_send(data, (char *)pkt, i);
fail:
free(pkt);
@@ -396,13 +410,14 @@ static const char *statenames[]={
#endif
/* The only way to change state */
-static void mqstate(struct connectdata *conn,
+static void mqstate(struct Curl_easy *data,
enum mqttstate state,
enum mqttstate nextstate) /* used if state == FIRST */
{
+ struct connectdata *conn = data->conn;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
#ifdef CURLDEBUG
- infof(conn->data, "%s (from %s) (next is %s)\n",
+ infof(data, "%s (from %s) (next is %s)\n",
statenames[state],
statenames[mqtt->state],
(state == MQTT_FIRST)? statenames[nextstate] : "");
@@ -416,27 +431,26 @@ static void mqstate(struct connectdata *conn,
/* for the publish packet */
#define MQTT_HEADER_LEN 5 /* max 5 bytes */
-static CURLcode mqtt_read_publish(struct connectdata *conn,
- bool *done)
+static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
ssize_t nread;
- struct Curl_easy *data = conn->data;
unsigned char *pkt = (unsigned char *)data->state.buffer;
size_t remlen;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
- struct MQTT *mq = data->req.protop;
+ struct MQTT *mq = data->req.p.mqtt;
unsigned char packet;
switch(mqtt->state) {
MQTT_SUBACK_COMING:
case MQTT_SUBACK_COMING:
- result = mqtt_verify_suback(conn);
+ result = mqtt_verify_suback(data);
if(result)
break;
- mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT);
+ mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
break;
case MQTT_SUBACK:
@@ -444,9 +458,9 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
/* we are expecting PUBLISH or SUBACK */
packet = mq->firstbyte & 0xf0;
if(packet == MQTT_MSG_PUBLISH)
- mqstate(conn, MQTT_PUB_REMAIN, MQTT_NOSTATE);
+ mqstate(data, MQTT_PUB_REMAIN, MQTT_NOSTATE);
else if(packet == MQTT_MSG_SUBACK) {
- mqstate(conn, MQTT_SUBACK_COMING, MQTT_NOSTATE);
+ mqstate(data, MQTT_SUBACK_COMING, MQTT_NOSTATE);
goto MQTT_SUBACK_COMING;
}
else if(packet == MQTT_MSG_DISCONNECT) {
@@ -473,7 +487,7 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
size_t rest = mq->npacket;
if(rest > (size_t)data->set.buffer_size)
rest = (size_t)data->set.buffer_size;
- result = Curl_read(conn, sockfd, (char *)pkt, rest, &nread);
+ result = Curl_read(data, sockfd, (char *)pkt, rest, &nread);
if(result) {
if(CURLE_AGAIN == result) {
infof(data, "EEEE AAAAGAIN\n");
@@ -485,8 +499,7 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
result = CURLE_PARTIAL_FILE;
goto end;
}
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
mq->npacket -= nread;
k->bytecount += nread;
@@ -494,13 +507,13 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
/* if QoS is set, message contains packet id */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)pkt, nread);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)pkt, nread);
if(result)
goto end;
if(!mq->npacket)
/* no more PUBLISH payload, back to subscribe wait state */
- mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT);
+ mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
break;
}
default:
@@ -512,28 +525,26 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
return result;
}
-static CURLcode mqtt_do(struct connectdata *conn, bool *done)
+static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
*done = FALSE; /* unconditionally */
- result = mqtt_connect(conn);
+ result = mqtt_connect(data);
if(result) {
failf(data, "Error %d sending MQTT CONN request", result);
return result;
}
- mqstate(conn, MQTT_FIRST, MQTT_CONNACK);
+ mqstate(data, MQTT_FIRST, MQTT_CONNACK);
return CURLE_OK;
}
-static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
+static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
- struct Curl_easy *data = conn->data;
- struct MQTT *mq = data->req.protop;
+ struct MQTT *mq = data->req.p.mqtt;
ssize_t nread;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char *pkt = (unsigned char *)data->state.buffer;
@@ -544,7 +555,7 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
if(mq->nsend) {
/* send the remainder of an outgoing packet */
char *ptr = mq->sendleftovers;
- result = mqtt_send(conn, mq->sendleftovers, mq->nsend);
+ result = mqtt_send(data, mq->sendleftovers, mq->nsend);
free(ptr);
if(result)
return result;
@@ -554,22 +565,20 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
switch(mqtt->state) {
case MQTT_FIRST:
/* Read the initial byte only */
- result = Curl_read(conn, sockfd, (char *)&mq->firstbyte, 1, &nread);
- if(result)
+ result = Curl_read(data, sockfd, (char *)&mq->firstbyte, 1, &nread);
+ if(!nread)
break;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1);
/* remember the first byte */
mq->npacket = 0;
- mqstate(conn, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
+ mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
/* FALLTHROUGH */
case MQTT_REMAINING_LENGTH:
do {
- result = Curl_read(conn, sockfd, (char *)&byte, 1, &nread);
- if(result)
+ result = Curl_read(data, sockfd, (char *)&byte, 1, &nread);
+ if(!nread)
break;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
pkt[mq->npacket++] = byte;
} while((byte & 0x80) && (mq->npacket < 4));
if(result)
@@ -577,10 +586,10 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
mq->npacket = 0;
if(mq->remaining_length) {
- mqstate(conn, mqtt->nextstate, MQTT_NOSTATE);
+ mqstate(data, mqtt->nextstate, MQTT_NOSTATE);
break;
}
- mqstate(conn, MQTT_FIRST, MQTT_FIRST);
+ mqstate(data, MQTT_FIRST, MQTT_FIRST);
if(mq->firstbyte == MQTT_MSG_DISCONNECT) {
infof(data, "Got DISCONNECT\n");
@@ -588,22 +597,22 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
}
break;
case MQTT_CONNACK:
- result = mqtt_verify_connack(conn);
+ result = mqtt_verify_connack(data);
if(result)
break;
- if(conn->data->state.httpreq == HTTPREQ_POST) {
- result = mqtt_publish(conn);
+ if(data->state.httpreq == HTTPREQ_POST) {
+ result = mqtt_publish(data);
if(!result) {
- result = mqtt_disconnect(conn);
+ result = mqtt_disconnect(data);
*done = TRUE;
}
mqtt->nextstate = MQTT_FIRST;
}
else {
- result = mqtt_subscribe(conn);
+ result = mqtt_subscribe(data);
if(!result) {
- mqstate(conn, MQTT_FIRST, MQTT_SUBACK);
+ mqstate(data, MQTT_FIRST, MQTT_SUBACK);
}
}
break;
@@ -611,11 +620,11 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
case MQTT_SUBACK:
case MQTT_PUBWAIT:
case MQTT_PUB_REMAIN:
- result = mqtt_read_publish(conn, done);
+ result = mqtt_read_publish(data, done);
break;
default:
- failf(conn->data, "State not handled yet");
+ failf(data, "State not handled yet");
*done = TRUE;
break;
}
@@ -625,4 +634,4 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
return result;
}
-#endif /* CURL_ENABLE_MQTT */
+#endif /* CURL_DISABLE_MQTT */
diff --git a/Utilities/cmcurl/lib/mqtt.h b/Utilities/cmcurl/lib/mqtt.h
index 37463d58a..fb52c7232 100644
--- a/Utilities/cmcurl/lib/mqtt.h
+++ b/Utilities/cmcurl/lib/mqtt.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
extern const struct Curl_handler Curl_handler_mqtt;
#endif
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 3c7fb85ed..85707a1af 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -69,7 +69,7 @@
#define CURL_MULTI_HANDLE 0x000bab1e
#define GOOD_MULTI_HANDLE(x) \
- ((x) && (x)->type == CURL_MULTI_HANDLE)
+ ((x) && (x)->magic == CURL_MULTI_HANDLE)
static CURLMcode singlesocket(struct Curl_multi *multi,
struct Curl_easy *data);
@@ -105,7 +105,14 @@ static const char * const statename[]={
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);
-static void Curl_init_completed(struct Curl_easy *data)
+/* called when the PERFORM state starts */
+static void init_perform(struct Curl_easy *data)
+{
+ data->req.chunk = FALSE;
+ Curl_pgrsTime(data, TIMER_PRETRANSFER);
+}
+
+static void init_completed(struct Curl_easy *data)
{
/* this is a completed transfer */
@@ -136,10 +143,10 @@ static void mstate(struct Curl_easy *data, CURLMstate state
NULL, /* DOING */
NULL, /* DO_MORE */
NULL, /* DO_DONE */
- NULL, /* PERFORM */
+ init_perform, /* PERFORM */
NULL, /* TOOFAST */
NULL, /* DONE */
- Curl_init_completed, /* COMPLETED */
+ init_completed, /* COMPLETED */
NULL /* MSGSENT */
};
@@ -190,11 +197,11 @@ static void mstate(struct Curl_easy *data, CURLMstate state
*/
struct Curl_sh_entry {
- struct curl_hash transfers; /* hash of transfers using this socket */
+ struct Curl_hash transfers; /* hash of transfers using this socket */
unsigned int action; /* what combined action READ/WRITE this socket waits
for */
- void *socketp; /* settable by users with curl_multi_assign() */
unsigned int users; /* number of transfers using this */
+ void *socketp; /* settable by users with curl_multi_assign() */
unsigned int readers; /* this many transfers want to read */
unsigned int writers; /* this many transfers want to write */
};
@@ -204,7 +211,7 @@ struct Curl_sh_entry {
#define SH_WRITE 2
/* look up a given socket in the socket hash, skip invalid sockets */
-static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh,
+static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
curl_socket_t s)
{
if(s != CURL_SOCKET_BAD) {
@@ -238,7 +245,7 @@ static void trhash_dtor(void *nada)
/* make sure this socket is present in the hash for this handle */
-static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
+static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
curl_socket_t s)
{
struct Curl_sh_entry *there = sh_getentry(sh, s);
@@ -273,7 +280,7 @@ static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
/* delete the given socket + handle from the hash */
static void sh_delentry(struct Curl_sh_entry *entry,
- struct curl_hash *sh, curl_socket_t s)
+ struct Curl_hash *sh, curl_socket_t s)
{
Curl_hash_destroy(&entry->transfers);
@@ -325,7 +332,7 @@ static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
* per call."
*
*/
-static int sh_init(struct curl_hash *hash, int hashsize)
+static int sh_init(struct Curl_hash *hash, int hashsize)
{
return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
sh_freeentry);
@@ -353,7 +360,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
if(!multi)
return NULL;
- multi->type = CURL_MULTI_HANDLE;
+ multi->magic = CURL_MULTI_HANDLE;
if(Curl_mk_dnscache(&multi->hostcache))
goto error;
@@ -558,7 +565,7 @@ static CURLcode multi_done(struct Curl_easy *data,
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(conn);
+ Curl_resolver_kill(data);
/* Cleanup possible redirect junk */
Curl_safefree(data->req.newurl);
@@ -579,14 +586,14 @@ static CURLcode multi_done(struct Curl_easy *data,
/* this calls the protocol-specific function pointer previously set */
if(conn->handler->done)
- result = conn->handler->done(conn, status, premature);
+ result = conn->handler->done(data, status, premature);
else
result = status;
if(CURLE_ABORTED_BY_CALLBACK != result) {
/* avoid this if we already aborted by callback to avoid this calling
another callback */
- CURLcode rc = Curl_pgrsDone(conn);
+ CURLcode rc = Curl_pgrsDone(data);
if(!result && rc)
result = CURLE_ABORTED_BY_CALLBACK;
}
@@ -690,17 +697,13 @@ static CURLcode multi_done(struct Curl_easy *data,
return result;
}
-static int close_connect_only(struct connectdata *conn, void *param)
+static int close_connect_only(struct Curl_easy *data,
+ struct connectdata *conn, void *param)
{
- struct Curl_easy *data = param;
-
+ (void)param;
if(data->state.lastconnect_id != conn->connection_id)
return 0;
- if(conn->data != data)
- return 1;
- conn->data = NULL;
-
if(!conn->bits.connect_only)
return 1;
@@ -716,7 +719,7 @@ 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;
+ struct Curl_llist_element *e;
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
@@ -809,7 +812,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
if(data->state.lastconnect_id != -1) {
/* Mark any connect-only connection for closure */
Curl_conncache_foreach(data, data->state.conn_cache,
- data, &close_connect_only);
+ NULL, close_connect_only);
}
#ifdef USE_LIBPSL
@@ -938,27 +941,30 @@ static int waitproxyconnect_getsock(struct connectdata *conn,
return GETSOCK_WRITESOCK(0);
}
-static int domore_getsock(struct connectdata *conn,
+static int domore_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
if(conn && conn->handler->domore_getsock)
- return conn->handler->domore_getsock(conn, socks);
+ return conn->handler->domore_getsock(data, conn, socks);
return GETSOCK_BLANK;
}
-static int doing_getsock(struct connectdata *conn,
+static int doing_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
if(conn && conn->handler->doing_getsock)
- return conn->handler->doing_getsock(conn, socks);
+ return conn->handler->doing_getsock(data, conn, socks);
return GETSOCK_BLANK;
}
-static int protocol_getsock(struct connectdata *conn,
+static int protocol_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
if(conn->handler->proto_getsock)
- return conn->handler->proto_getsock(conn, socks);
+ return conn->handler->proto_getsock(data, conn, socks);
/* Backup getsock logic. Since there is a live socket in use, we must wait
for it or it will be removed from watching when the multi_socket API is
used. */
@@ -971,10 +977,11 @@ static int protocol_getsock(struct connectdata *conn,
static int multi_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
+ struct connectdata *conn = data->conn;
/* The no connection case can happen when this is called from
curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/
- if(!data->conn)
+ if(!conn)
return 0;
if(data->mstate > CURLM_STATE_CONNECT &&
@@ -988,30 +995,30 @@ static int multi_getsock(struct Curl_easy *data,
return 0;
case CURLM_STATE_WAITRESOLVE:
- return Curl_resolv_getsock(data->conn, socks);
+ return Curl_resolv_getsock(data, socks);
case CURLM_STATE_PROTOCONNECT:
case CURLM_STATE_SENDPROTOCONNECT:
- return protocol_getsock(data->conn, socks);
+ return protocol_getsock(data, conn, socks);
case CURLM_STATE_DO:
case CURLM_STATE_DOING:
- return doing_getsock(data->conn, socks);
+ return doing_getsock(data, conn, socks);
case CURLM_STATE_WAITPROXYCONNECT:
- return waitproxyconnect_getsock(data->conn, socks);
+ return waitproxyconnect_getsock(conn, socks);
case CURLM_STATE_WAITCONNECT:
- return waitconnect_getsock(data->conn, socks);
+ return waitconnect_getsock(conn, socks);
case CURLM_STATE_DO_MORE:
- return domore_getsock(data->conn, socks);
+ 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:
- return Curl_single_getsock(data->conn, socks);
+ return Curl_single_getsock(data, conn, socks);
}
}
@@ -1067,13 +1074,13 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
#define NUM_POLLS_ON_STACK 10
-static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
- struct curl_waitfd extra_fds[],
- unsigned int extra_nfds,
- int timeout_ms,
- int *ret,
- bool extrawait, /* when no socket, wait */
- bool use_wakeup)
+static CURLMcode multi_wait(struct Curl_multi *multi,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret,
+ bool extrawait, /* when no socket, wait */
+ bool use_wakeup)
{
struct Curl_easy *data;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
@@ -1081,11 +1088,11 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
unsigned int i;
unsigned int nfds = 0;
unsigned int curlfds;
- bool ufds_malloc = FALSE;
long timeout_internal;
int retcode = 0;
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
struct pollfd *ufds = &a_few_on_stack[0];
+ bool ufds_malloc = FALSE;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -1157,7 +1164,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
while(data) {
bitmap = multi_getsock(data, sockbunch);
- for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
if(bitmap & GETSOCK_READSOCK(i)) {
@@ -1203,10 +1210,8 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
#endif
if(nfds) {
- int pollrc;
/* wait... */
- pollrc = Curl_poll(ufds, nfds, timeout_ms);
-
+ int pollrc = Curl_poll(ufds, nfds, timeout_ms);
if(pollrc > 0) {
retcode = pollrc;
/* copy revents results from the poll to the curl_multi_wait poll
@@ -1222,7 +1227,6 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
mask |= CURL_WAIT_POLLOUT;
if(r & POLLPRI)
mask |= CURL_WAIT_POLLPRI;
-
extra_fds[i].revents = mask;
}
@@ -1284,8 +1288,8 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
int timeout_ms,
int *ret)
{
- return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
- FALSE);
+ return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
+ FALSE);
}
CURLMcode curl_multi_poll(struct Curl_multi *multi,
@@ -1294,8 +1298,8 @@ CURLMcode curl_multi_poll(struct Curl_multi *multi,
int timeout_ms,
int *ret)
{
- return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
- TRUE);
+ return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
+ TRUE);
}
CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
@@ -1322,7 +1326,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
The write socket is set to non-blocking, this way this function
cannot block, making it safe to call even from the same thread
- that will call Curl_multi_wait(). If swrite() returns that it
+ that will call curl_multi_wait(). If swrite() returns that it
would block, it's considered successful because it means that
previous calls to this function will wake up the poll(). */
if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
@@ -1386,18 +1390,6 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
return rc;
}
-/*
- * do_complete is called when the DO actions are complete.
- *
- * We init chunking and trailer bits to their default values here immediately
- * before receiving any header data for the current request.
- */
-static void do_complete(struct connectdata *conn)
-{
- conn->data->req.chunk = FALSE;
- Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
-}
-
static CURLcode multi_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
@@ -1407,14 +1399,10 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
DEBUGASSERT(conn->handler);
DEBUGASSERT(conn->data == data);
- if(conn->handler->do_it) {
+ if(conn->handler->do_it)
/* generic protocol-specific function pointer set in curl_connect() */
- result = conn->handler->do_it(conn, done);
+ result = conn->handler->do_it(data, done);
- if(!result && *done)
- /* do_complete must be called after the protocol-specific DO function */
- do_complete(conn);
- }
return result;
}
@@ -1427,18 +1415,15 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
* DOING state there's more work to do!
*/
-static CURLcode multi_do_more(struct connectdata *conn, int *complete)
+static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
*complete = 0;
if(conn->handler->do_more)
- result = conn->handler->do_more(conn, complete);
-
- if(!result && (*complete == 1))
- /* do_complete must be called after the protocol-specific DO function */
- do_complete(conn);
+ result = conn->handler->do_more(data, complete);
return result;
}
@@ -1449,14 +1434,14 @@ static CURLcode multi_do_more(struct connectdata *conn, int *complete)
* protocol layer.
*/
-static CURLcode protocol_connecting(struct connectdata *conn,
- bool *done)
+static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->connecting) {
*done = FALSE;
- result = conn->handler->connecting(conn, done);
+ result = conn->handler->connecting(data, done);
}
else
*done = TRUE;
@@ -1469,13 +1454,14 @@ static CURLcode protocol_connecting(struct connectdata *conn,
* until the DOING phase is done on protocol layer.
*/
-static CURLcode protocol_doing(struct connectdata *conn, bool *done)
+static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->doing) {
*done = FALSE;
- result = conn->handler->doing(conn, done);
+ result = conn->handler->doing(data, done);
}
else
*done = TRUE;
@@ -1488,11 +1474,11 @@ static CURLcode protocol_doing(struct connectdata *conn, bool *done)
* proceed with some action.
*
*/
-static CURLcode protocol_connect(struct connectdata *conn,
+static CURLcode protocol_connect(struct Curl_easy *data,
bool *protocol_done)
{
CURLcode result = CURLE_OK;
-
+ struct connectdata *conn = data->conn;
DEBUGASSERT(conn);
DEBUGASSERT(protocol_done);
@@ -1513,7 +1499,7 @@ static CURLcode protocol_connect(struct connectdata *conn,
if(!conn->bits.protoconnstart) {
#ifndef CURL_DISABLE_PROXY
- result = Curl_proxy_connect(conn, FIRSTSOCKET);
+ result = Curl_proxy_connect(data, FIRSTSOCKET);
if(result)
return result;
@@ -1531,7 +1517,7 @@ static CURLcode protocol_connect(struct connectdata *conn,
/* is there a protocol-specific connect() procedure? */
/* Call the protocol-specific connect function */
- result = conn->handler->connect_it(conn, protocol_done);
+ result = conn->handler->connect_it(data, protocol_done);
}
else
*protocol_done = TRUE;
@@ -1562,7 +1548,7 @@ CURLcode Curl_preconnect(struct Curl_easy *data)
static CURLMcode multi_runsingle(struct Curl_multi *multi,
- struct curltime now,
+ struct curltime *nowp,
struct Curl_easy *data)
{
struct Curl_message *msg = NULL;
@@ -1592,9 +1578,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
process_pending_handles(multi); /* multiplexed */
}
- if(data->conn && data->mstate > CURLM_STATE_CONNECT &&
+ if(data->mstate > CURLM_STATE_CONNECT &&
data->mstate < CURLM_STATE_COMPLETED) {
/* Make sure we set the connection's current owner */
+ DEBUGASSERT(data->conn);
+ if(!data->conn)
+ return CURLM_INTERNAL_ERROR;
data->conn->data = data;
}
@@ -1603,7 +1592,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
(data->mstate < CURLM_STATE_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, &now,
+ timeout_ms = Curl_timeleft(data, nowp,
(data->mstate <= CURLM_STATE_DO)?
TRUE:FALSE);
@@ -1612,25 +1601,25 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->mstate == CURLM_STATE_WAITRESOLVE)
failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds",
- Curl_timediff(now, data->progress.t_startsingle));
+ Curl_timediff(*nowp, data->progress.t_startsingle));
else if(data->mstate == CURLM_STATE_WAITCONNECT)
failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds",
- Curl_timediff(now, data->progress.t_startsingle));
+ Curl_timediff(*nowp, data->progress.t_startsingle));
else {
struct SingleRequest *k = &data->req;
if(k->size != -1) {
failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
CURL_FORMAT_CURL_OFF_T " bytes received",
- Curl_timediff(now, data->progress.t_startsingle),
+ Curl_timediff(*nowp, data->progress.t_startsingle),
k->bytecount, k->size);
}
else {
failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds with %" CURL_FORMAT_CURL_OFF_T
" bytes received",
- Curl_timediff(now, data->progress.t_startsingle),
+ Curl_timediff(*nowp, data->progress.t_startsingle),
k->bytecount);
}
}
@@ -1655,7 +1644,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
/* after init, go CONNECT */
multistate(data, CURLM_STATE_CONNECT);
- Curl_pgrsTime(data, TIMER_STARTOP);
+ *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
rc = CURLM_CALL_MULTI_PERFORM;
}
break;
@@ -1672,7 +1661,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(result)
break;
- Curl_pgrsTime(data, TIMER_STARTSINGLE);
+ *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
if(data->set.timeout)
Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
@@ -1740,19 +1729,19 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
hostname = conn->host.name;
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
+ dns = Curl_fetch_addr(data, hostname, (int)conn->port);
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
result = CURLE_OK;
infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
}
if(!dns)
- result = Curl_resolv_check(data->conn, &dns);
+ result = Curl_resolv_check(data, &dns);
/* Update sockets here, because the socket(s) may have been
closed and the application thus needs to be told, even if it
@@ -1765,7 +1754,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
- result = Curl_once_resolved(data->conn, &protocol_connected);
+ result = Curl_once_resolved(data, &protocol_connected);
if(result)
/* if Curl_once_resolved() returns failure, the connection struct
@@ -1799,7 +1788,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITPROXYCONNECT:
/* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
DEBUGASSERT(data->conn);
- result = Curl_http_connect(data->conn, &protocol_connected);
+ result = Curl_http_connect(data, &protocol_connected);
#ifndef CURL_DISABLE_PROXY
if(data->conn->bits.proxy_connect_closed) {
rc = CURLM_CALL_MULTI_PERFORM;
@@ -1830,7 +1819,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITCONNECT:
/* awaiting a completion of an asynch TCP connect */
DEBUGASSERT(data->conn);
- result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected);
+ result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
if(
@@ -1863,7 +1852,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
case CURLM_STATE_SENDPROTOCONNECT:
- result = protocol_connect(data->conn, &protocol_connected);
+ result = protocol_connect(data, &protocol_connected);
if(!result && !protocol_connected)
/* switch to waiting state */
multistate(data, CURLM_STATE_PROTOCONNECT);
@@ -1882,7 +1871,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_PROTOCONNECT:
/* protocol-specific connect phase */
- result = protocol_connecting(data->conn, &protocol_connected);
+ result = protocol_connecting(data, &protocol_connected);
if(!result && protocol_connected) {
/* after the connect has completed, go WAITDO or DO */
multistate(data, CURLM_STATE_DO);
@@ -1919,7 +1908,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
/* skip some states if it is important */
multi_done(data, CURLE_OK, FALSE);
- multistate(data, CURLM_STATE_DONE);
+
+ /* if there's no connection left, skip the DONE state */
+ multistate(data, data->conn ?
+ CURLM_STATE_DONE : CURLM_STATE_COMPLETED);
rc = CURLM_CALL_MULTI_PERFORM;
break;
}
@@ -1955,7 +1947,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
followtype follow = FOLLOW_NONE;
CURLcode drc;
- drc = Curl_retry_request(data->conn, &newurl);
+ drc = Curl_retry_request(data, &newurl);
if(drc) {
/* a failure here pretty much implies an out of memory */
result = drc;
@@ -2005,7 +1997,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_DOING:
/* we continue DOING until the DO phase is complete */
DEBUGASSERT(data->conn);
- result = protocol_doing(data->conn, &dophase_done);
+ result = protocol_doing(data, &dophase_done);
if(!result) {
if(dophase_done) {
/* after DO, go DO_DONE or DO_MORE */
@@ -2028,7 +2020,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
* When we are connected, DO MORE and then go DO_DONE
*/
DEBUGASSERT(data->conn);
- result = multi_do_more(data->conn, &control);
+ result = multi_do_more(data, &control);
if(!result) {
if(control) {
@@ -2077,12 +2069,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
DEBUGASSERT(data->conn);
/* if both rates are within spec, resume transfer */
- if(Curl_pgrsUpdate(data->conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, now);
+ result = Curl_speedcheck(data, *nowp);
- if(!result) {
+ if(result) {
+ if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
+ result != CURLE_HTTP2_STREAM)
+ streamclose(data->conn, "Transfer returned error");
+
+ Curl_posttransfer(data);
+ multi_done(data, result, TRUE);
+ }
+ else {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
send_timeout_ms =
@@ -2090,7 +2090,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
- now);
+ *nowp);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
@@ -2099,11 +2099,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
- now);
+ *nowp);
if(!send_timeout_ms && !recv_timeout_ms) {
multistate(data, CURLM_STATE_PERFORM);
- Curl_ratelimit(data, now);
+ Curl_ratelimit(data, *nowp);
}
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
@@ -2125,7 +2125,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
- now);
+ *nowp);
/* check if over recv speed */
recv_timeout_ms = 0;
@@ -2134,10 +2134,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
- now);
+ *nowp);
if(send_timeout_ms || recv_timeout_ms) {
- Curl_ratelimit(data, now);
+ Curl_ratelimit(data, *nowp);
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
@@ -2154,7 +2154,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
* condition and the server closed the re-used connection exactly when
* we wanted to use it, so figure out if that is indeed the case.
*/
- CURLcode ret = Curl_retry_request(data->conn, &newurl);
+ CURLcode ret = Curl_retry_request(data, &newurl);
if(!ret)
retry = (newurl)?TRUE:FALSE;
else if(!result)
@@ -2169,7 +2169,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else if((CURLE_HTTP2_STREAM == result) &&
Curl_h2_http_1_1_error(data->conn)) {
- CURLcode ret = Curl_retry_request(data->conn, &newurl);
+ CURLcode ret = Curl_retry_request(data, &newurl);
if(!ret) {
infof(data, "Downgrades to HTTP/1.1!\n");
@@ -2206,7 +2206,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multi_done(data, result, TRUE);
}
else if(done) {
- followtype follow = FOLLOW_NONE;
/* call this even if the readwrite function returned error */
Curl_posttransfer(data);
@@ -2214,6 +2213,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* When we follow redirects or is set to retry the connection, we must
to go back to the CONNECT state */
if(data->req.newurl || retry) {
+ followtype follow = FOLLOW_NONE;
if(!retry) {
/* if the URL is a follow-location and not just a retried request
then figure out the URL here */
@@ -2283,14 +2283,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* allow a previously set error code take precedence */
if(!result)
result = res;
-
- /*
- * If there are other handles on the connection, multi_done won't set
- * conn to NULL. In such a case, curl_multi_remove_handle() can
- * access free'd data, if the connection is free'd and the handle
- * removed before we perform the processing in CURLM_STATE_COMPLETED
- */
- Curl_detach_connnection(data);
}
#ifndef CURL_DISABLE_FTP
@@ -2360,7 +2352,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
rc = CURLM_CALL_MULTI_PERFORM;
}
/* if there's still a connection to use, call the progress function */
- else if(data->conn && Curl_pgrsUpdate(data->conn)) {
+ else if(data->conn && Curl_pgrsUpdate(data)) {
/* aborted due to progress callback return code must close the
connection */
result = CURLE_ABORTED_BY_CALLBACK;
@@ -2417,7 +2409,7 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
SIGPIPE_VARIABLE(pipe_st);
sigpipe_ignore(data, &pipe_st);
- result = multi_runsingle(multi, now, data);
+ result = multi_runsingle(multi, &now, data);
sigpipe_restore(&pipe_st);
if(result)
@@ -2461,7 +2453,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- multi->type = 0; /* not good anymore */
+ multi->magic = 0; /* not good anymore */
/* Firsrt remove all remaining easy handles */
data = multi->easyp;
@@ -2531,7 +2523,7 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
!multi->in_callback &&
Curl_llist_count(&multi->msglist)) {
/* there is one or more messages in the list */
- struct curl_llist_element *e;
+ struct Curl_llist_element *e;
/* extract the head of the list to return */
e = multi->msglist.head;
@@ -2761,15 +2753,15 @@ static CURLMcode add_next_timeout(struct curltime now,
struct Curl_easy *d)
{
struct curltime *tv = &d->state.expiretime;
- struct curl_llist *list = &d->state.timeoutlist;
- struct curl_llist_element *e;
+ struct Curl_llist *list = &d->state.timeoutlist;
+ struct Curl_llist_element *e;
struct time_node *node = NULL;
/* move over the timeout list for this specific handle and remove all
timeouts that are now passed tense and store the next pending
timeout in *tv */
for(e = list->head; e;) {
- struct curl_llist_element *n = e->next;
+ struct Curl_llist_element *n = e->next;
timediff_t diff;
node = (struct time_node *)e->ptr;
diff = Curl_timediff(node->time, now);
@@ -2839,8 +2831,8 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
and just move on. */
;
else {
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
/* the socket can be shared by many transfers, iterate */
Curl_hash_start_iterate(&entry->transfers, &iter);
@@ -2887,7 +2879,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
SIGPIPE_VARIABLE(pipe_st);
sigpipe_ignore(data, &pipe_st);
- result = multi_runsingle(multi, now, data);
+ result = multi_runsingle(multi, &now, data);
sigpipe_restore(&pipe_st);
if(CURLM_OK >= result) {
@@ -3015,7 +3007,6 @@ CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
}
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
-
{
CURLMcode result;
if(multi->in_callback)
@@ -3123,8 +3114,8 @@ void Curl_update_timer(struct Curl_multi *multi)
static void
multi_deltimeout(struct Curl_easy *data, expire_id eid)
{
- struct curl_llist_element *e;
- struct curl_llist *timeoutlist = &data->state.timeoutlist;
+ struct Curl_llist_element *e;
+ struct Curl_llist *timeoutlist = &data->state.timeoutlist;
/* find and remove the specific node from the list */
for(e = timeoutlist->head; e; e = e->next) {
struct time_node *n = (struct time_node *)e->ptr;
@@ -3147,11 +3138,11 @@ multi_addtimeout(struct Curl_easy *data,
struct curltime *stamp,
expire_id eid)
{
- struct curl_llist_element *e;
+ struct Curl_llist_element *e;
struct time_node *node;
- struct curl_llist_element *prev = NULL;
+ struct Curl_llist_element *prev = NULL;
size_t n;
- struct curl_llist *timeoutlist = &data->state.timeoutlist;
+ struct Curl_llist *timeoutlist = &data->state.timeoutlist;
node = &data->state.expires[eid];
@@ -3233,9 +3224,8 @@ void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
/* Since this is an updated time, we must remove the previous entry from
the splay tree first and then re-add the new value */
- rc = Curl_splayremovebyaddr(multi->timetree,
- &data->state.timenode,
- &multi->timetree);
+ rc = Curl_splayremove(multi->timetree, &data->state.timenode,
+ &multi->timetree);
if(rc)
infof(data, "Internal error removing splay node = %d\n", rc);
}
@@ -3278,12 +3268,11 @@ void Curl_expire_clear(struct Curl_easy *data)
if(nowp->tv_sec || nowp->tv_usec) {
/* Since this is an cleared time, we must remove the previous entry from
the splay tree */
- struct curl_llist *list = &data->state.timeoutlist;
+ struct Curl_llist *list = &data->state.timeoutlist;
int rc;
- rc = Curl_splayremovebyaddr(multi->timetree,
- &data->state.timenode,
- &multi->timetree);
+ rc = Curl_splayremove(multi->timetree, &data->state.timenode,
+ &multi->timetree);
if(rc)
infof(data, "Internal error clearing splay node = %d\n", rc);
@@ -3335,21 +3324,23 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
* When information about a connection has appeared, call this!
*/
-void Curl_multiuse_state(struct connectdata *conn,
+void Curl_multiuse_state(struct Curl_easy *data,
int bundlestate) /* use BUNDLE_* defines */
{
+ struct connectdata *conn;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->multi);
+ conn = data->conn;
DEBUGASSERT(conn);
DEBUGASSERT(conn->bundle);
- DEBUGASSERT(conn->data);
- DEBUGASSERT(conn->data->multi);
conn->bundle->multiuse = bundlestate;
- process_pending_handles(conn->data->multi);
+ process_pending_handles(data->multi);
}
static void process_pending_handles(struct Curl_multi *multi)
{
- struct curl_llist_element *e = multi->pending.head;
+ struct Curl_llist_element *e = multi->pending.head;
if(e) {
struct Curl_easy *data = e->ptr;
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index 9d73df081..f28c5899b 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -22,12 +22,16 @@
*
***************************************************************************/
+#include "llist.h"
+#include "hash.h"
#include "conncache.h"
#include "psl.h"
#include "socketpair.h"
+struct connectdata;
+
struct Curl_message {
- struct curl_llist_element list;
+ struct Curl_llist_element list;
/* the 'CURLMsg' is the part that is visible to the external user */
struct CURLMsg extmsg;
};
@@ -67,11 +71,11 @@ typedef enum {
#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
-#if defined(USE_SOCKETPAIR) && !defined(USE_BLOCKING_SOCKETS)
+#if defined(USE_SOCKETPAIR) && !defined(USE_BLOCKING_SOCKETS) && \
+ !defined(CURL_DISABLE_SOCKETPAIR)
#define ENABLE_WAKEUP
#endif
-
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
@@ -79,7 +83,7 @@ typedef enum {
struct Curl_multi {
/* First a simple identifier to easier detect if a user mix up
this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
- long type;
+ unsigned int magic;
/* We have a doubly-linked list with easy handles */
struct Curl_easy *easyp;
@@ -89,9 +93,9 @@ struct Curl_multi {
int num_alive; /* amount of easy handles that are added but have not yet
reached COMPLETE state */
- struct curl_llist msglist; /* a list of messages from completed transfers */
+ struct Curl_llist msglist; /* a list of messages from completed transfers */
- struct curl_llist pending; /* Curl_easys that are in the
+ struct Curl_llist pending; /* Curl_easys that are in the
CURLM_STATE_CONNECT_PEND state */
/* callback function and user data pointer for the *socket() API */
@@ -103,7 +107,7 @@ struct Curl_multi {
void *push_userp;
/* Hostname cache */
- struct curl_hash hostcache;
+ struct Curl_hash hostcache;
#ifdef USE_LIBPSL
/* PSL cache. */
@@ -117,7 +121,7 @@ struct Curl_multi {
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
the pluralis form, there can be more than one easy handle waiting on the
same actual socket) */
- struct curl_hash sockhash;
+ struct Curl_hash sockhash;
/* Shared connection cache (bundles)*/
struct conncache conn_cache;
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index 7d574df92..2fbef53c4 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -69,7 +69,7 @@ size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
-void Curl_multiuse_state(struct connectdata *conn,
+void Curl_multiuse_state(struct Curl_easy *data,
int bundlestate); /* use BUNDLE_* defines */
/*
diff --git a/Utilities/cmcurl/lib/netrc.c b/Utilities/cmcurl/lib/netrc.c
index 1c9da3199..13610bb07 100644
--- a/Utilities/cmcurl/lib/netrc.c
+++ b/Utilities/cmcurl/lib/netrc.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/netrc.h b/Utilities/cmcurl/lib/netrc.h
index 7f56c4b4d..4938a5916 100644
--- a/Utilities/cmcurl/lib/netrc.h
+++ b/Utilities/cmcurl/lib/netrc.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index a48e67db4..30c240b63 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/lib/non-ascii.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/non-ascii.h b/Utilities/cmcurl/lib/non-ascii.h
index 5fb5771e0..458e8ef09 100644
--- a/Utilities/cmcurl/lib/non-ascii.h
+++ b/Utilities/cmcurl/lib/non-ascii.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/nonblock.c b/Utilities/cmcurl/lib/nonblock.c
index abeb6598c..4a7bde504 100644
--- a/Utilities/cmcurl/lib/nonblock.c
+++ b/Utilities/cmcurl/lib/nonblock.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/nonblock.h b/Utilities/cmcurl/lib/nonblock.h
index d50d31594..761dab4f6 100644
--- a/Utilities/cmcurl/lib/nonblock.h
+++ b/Utilities/cmcurl/lib/nonblock.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c
index beec0b388..769326892 100644
--- a/Utilities/cmcurl/lib/nwlib.c
+++ b/Utilities/cmcurl/lib/nwlib.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/nwos.c b/Utilities/cmcurl/lib/nwos.c
index c6c22ccbb..889403132 100644
--- a/Utilities/cmcurl/lib/nwos.c
+++ b/Utilities/cmcurl/lib/nwos.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/openldap.c b/Utilities/cmcurl/lib/openldap.c
index 782d6a08e..4070bbf88 100644
--- a/Utilities/cmcurl/lib/openldap.c
+++ b/Utilities/cmcurl/lib/openldap.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
- * Copyright (C) 2011 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -76,12 +76,14 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
LDAP **ld);
#endif
-static CURLcode ldap_setup_connection(struct connectdata *conn);
-static CURLcode ldap_do(struct connectdata *conn, bool *done);
-static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
-static CURLcode ldap_connect(struct connectdata *conn, bool *done);
-static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
-static CURLcode ldap_disconnect(struct connectdata *conn, bool dead);
+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 Curl_recv ldap_recv;
@@ -107,6 +109,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* connection_check */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_NONE /* flags */
};
@@ -132,7 +135,8 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_LDAPS, /* defport */
- CURLPROTO_LDAP, /* protocol */
+ CURLPROTO_LDAPS, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_SSL /* flags */
};
#endif
@@ -167,11 +171,11 @@ struct ldapreqinfo {
int nument;
};
-static CURLcode ldap_setup_connection(struct connectdata *conn)
+static CURLcode ldap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ldapconninfo *li;
LDAPURLDesc *lud;
- struct Curl_easy *data = conn->data;
int rc, proto;
CURLcode status;
@@ -184,7 +188,7 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
status = CURLE_OUT_OF_MEMORY;
msg = url_errs[rc];
}
- failf(conn->data, "LDAP local: %s", msg);
+ failf(data, "LDAP local: %s", msg);
return status;
}
proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
@@ -203,10 +207,10 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
static Sockbuf_IO ldapsb_tls;
#endif
-static CURLcode ldap_connect(struct connectdata *conn, bool *done)
+static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
- struct Curl_easy *data = conn->data;
int rc, proto = LDAP_VERSION3;
char hosturl[1024];
char *ptr;
@@ -241,7 +245,8 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
#ifdef USE_SSL
if(conn->handler->flags & PROTOPT_SSL) {
CURLcode result;
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &li->ssldone);
if(result)
return result;
}
@@ -250,10 +255,10 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
+static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
- struct Curl_easy *data = conn->data;
LDAPMessage *msg = NULL;
struct timeval tv = {0, 1}, *tvp;
int rc, err;
@@ -263,7 +268,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
if(conn->handler->flags & PROTOPT_SSL) {
/* Is the SSL handshake complete yet? */
if(!li->ssldone) {
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&li->ssldone);
if(result || !li->ssldone)
return result;
@@ -355,10 +360,12 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode ldap_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) {
@@ -371,15 +378,15 @@ static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
return CURLE_OK;
}
-static CURLcode ldap_do(struct connectdata *conn, bool *done)
+static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
struct ldapreqinfo *lr;
CURLcode status = CURLE_OK;
int rc = 0;
LDAPURLDesc *ludp = NULL;
int msgid;
- struct Curl_easy *data = conn->data;
connkeep(conn, "OpenLDAP do");
@@ -394,7 +401,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
status = CURLE_OUT_OF_MEMORY;
msg = url_errs[rc];
}
- failf(conn->data, "LDAP local: %s", msg);
+ failf(data, "LDAP local: %s", msg);
return status;
}
@@ -410,16 +417,17 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
if(!lr)
return CURLE_OUT_OF_MEMORY;
lr->msgid = msgid;
- data->req.protop = lr;
+ data->req.p.ldap = lr;
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
*done = TRUE;
return CURLE_OK;
}
-static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
+static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
bool premature)
{
- struct ldapreqinfo *lr = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct ldapreqinfo *lr = data->req.p.ldap;
(void)res;
(void)premature;
@@ -431,19 +439,19 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
lr->msgid = 0;
}
- conn->data->req.protop = NULL;
+ data->req.p.ldap = NULL;
free(lr);
}
return CURLE_OK;
}
-static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
+static ssize_t ldap_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;
- struct Curl_easy *data = conn->data;
- struct ldapreqinfo *lr = data->req.protop;
+ struct ldapreqinfo *lr = data->req.p.ldap;
int rc, ret;
LDAPMessage *msg = NULL;
LDAPMessage *ent;
@@ -510,20 +518,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
*err = CURLE_RECV_ERROR;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(writeerr) {
*err = writeerr;
return -1;
@@ -544,18 +552,18 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
binary = 0;
if(bvals == NULL) {
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":\n", 2);
if(writeerr) {
*err = writeerr;
return -1;
@@ -566,20 +574,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":", 1);
if(writeerr) {
*err = writeerr;
return -1;
@@ -617,7 +625,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
*err = error;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)": ", 2);
if(writeerr) {
*err = writeerr;
@@ -626,7 +634,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += 2;
if(val_b64_sz > 0) {
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
val_b64_sz);
if(writeerr) {
*err = writeerr;
@@ -637,13 +645,13 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
}
}
else {
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)" ", 1);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, bvals[i].bv_val,
bvals[i].bv_len);
if(writeerr) {
*err = writeerr;
@@ -652,7 +660,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += bvals[i].bv_len + 1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) {
*err = writeerr;
return -1;
@@ -661,14 +669,14 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount++;
}
ber_memfree(bvals);
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) {
*err = writeerr;
return -1;
}
data->req.bytecount++;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) {
*err = writeerr;
return -1;
@@ -722,7 +730,7 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
ber_slen_t ret;
CURLcode err = CURLE_RECV_ERROR;
- ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err);
+ ret = (li->recv)(conn->data, FIRSTSOCKET, buf, len, &err);
if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK);
}
@@ -737,7 +745,7 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
ber_slen_t ret;
CURLcode err = CURLE_SEND_ERROR;
- ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err);
+ ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err);
if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK);
}
diff --git a/Utilities/cmcurl/lib/parsedate.c b/Utilities/cmcurl/lib/parsedate.c
index 4c7a40c4c..3c38f2c4c 100644
--- a/Utilities/cmcurl/lib/parsedate.c
+++ b/Utilities/cmcurl/lib/parsedate.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -275,48 +275,21 @@ enum assume {
DATE_TIME
};
-/* this is a clone of 'struct tm' but with all fields we don't need or use
- cut out */
-struct my_tm {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year; /* full year */
-};
-
-/* struct tm to time since epoch in GMT time zone.
- * This is similar to the standard mktime function but for GMT only, and
- * doesn't suffer from the various bugs and portability problems that
- * some systems' implementations have.
- *
- * Returns 0 on success, otherwise non-zero.
+/*
+ * time2epoch: time stamp to seconds since epoch in GMT time zone. Similar to
+ * mktime but for GMT only.
*/
-static void my_timegm(struct my_tm *tm, time_t *t)
+static time_t time2epoch(int sec, int min, int hour,
+ int mday, int mon, int year)
{
static const int month_days_cumulative [12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
- int month, year, leap_days;
-
- year = tm->tm_year;
- month = tm->tm_mon;
- if(month < 0) {
- year += (11 - month) / 12;
- month = 11 - (11 - month) % 12;
- }
- else if(month >= 12) {
- year -= month / 12;
- month = month % 12;
- }
-
- leap_days = year - (tm->tm_mon <= 1);
+ int leap_days = year - (mon <= 1);
leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
- (1969 / 4) + (1969 / 100) - (1969 / 400));
-
- *t = ((((time_t) (year - 1970) * 365
- + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24
- + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+ return ((((time_t) (year - 1970) * 365
+ + leap_days + month_days_cumulative[mon] + mday - 1) * 24
+ + hour) * 60 + min) * 60 + sec;
}
/*
@@ -341,7 +314,6 @@ static int parsedate(const char *date, time_t *output)
int secnum = -1;
int yearnum = -1;
int tzoff = -1;
- struct my_tm tm;
enum assume dignext = DATE_MDAY;
const char *indate = date; /* save the original pointer */
int part = 0; /* max 6 parts */
@@ -533,18 +505,11 @@ static int parsedate(const char *date, time_t *output)
(hournum > 23) || (minnum > 59) || (secnum > 60))
return PARSEDATE_FAIL; /* clearly an illegal date */
- tm.tm_sec = secnum;
- tm.tm_min = minnum;
- tm.tm_hour = hournum;
- tm.tm_mday = mdaynum;
- tm.tm_mon = monnum;
- tm.tm_year = yearnum;
-
- /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on
+ /* time2epoch() returns a time_t. time_t is often 32 bits, sometimes even on
architectures that feature 64 bit 'long' but ultimately time_t is the
correct data type to use.
*/
- my_timegm(&tm, &t);
+ t = time2epoch(secnum, minnum, hournum, mdaynum, monnum, yearnum);
/* Add the time zone diff between local time zone and GMT. */
if(tzoff == -1)
diff --git a/Utilities/cmcurl/lib/parsedate.h b/Utilities/cmcurl/lib/parsedate.h
index 8c7ae94e4..a99faf9e3 100644
--- a/Utilities/cmcurl/lib/parsedate.h
+++ b/Utilities/cmcurl/lib/parsedate.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index 314331521..481173995 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -44,10 +44,10 @@
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
+timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
+ struct pingpong *pp, bool disconnecting)
{
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
timediff_t timeout_ms; /* in milliseconds */
timediff_t response_time = (data->set.server_response_timeout)?
data->set.server_response_timeout: pp->response_time;
@@ -77,15 +77,15 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
/*
* Curl_pp_statemach()
*/
-CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
+CURLcode Curl_pp_statemach(struct Curl_easy *data,
+ struct pingpong *pp, bool block,
bool disconnecting)
{
- struct connectdata *conn = pp->conn;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
timediff_t interval_ms;
- timediff_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting);
- struct Curl_easy *data = conn->data;
+ timediff_t timeout_ms = Curl_pp_state_timeout(data, pp, disconnecting);
CURLcode result = CURLE_OK;
if(timeout_ms <= 0) {
@@ -117,7 +117,7 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
if(block) {
/* if we didn't wait, we don't have to spend time on this now */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, Curl_now());
@@ -131,22 +131,26 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
result = CURLE_OUT_OF_MEMORY;
}
else if(rc)
- result = pp->statemach_act(conn);
+ result = pp->statemachine(data, data->conn);
return result;
}
/* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct pingpong *pp)
+void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp)
{
- struct connectdata *conn = pp->conn;
+ DEBUGASSERT(data);
pp->nread_resp = 0;
- pp->linestart_resp = conn->data->state.buffer;
+ pp->linestart_resp = data->state.buffer;
pp->pending_resp = TRUE;
pp->response = Curl_now(); /* start response time-out now! */
}
-
+/* setup for the coming transfer */
+void Curl_pp_setup(struct pingpong *pp)
+{
+ Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
+}
/***********************************************************************
*
@@ -158,17 +162,16 @@ void Curl_pp_init(struct pingpong *pp)
*
* made to never block
*/
-CURLcode Curl_pp_vsendf(struct pingpong *pp,
+CURLcode Curl_pp_vsendf(struct Curl_easy *data,
+ struct pingpong *pp,
const char *fmt,
va_list args)
{
- ssize_t bytes_written;
+ ssize_t bytes_written = 0;
size_t write_len;
- char *fmt_crlf;
char *s;
CURLcode result;
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data;
+ struct connectdata *conn = data->conn;
#ifdef HAVE_GSSAPI
enum protection_level data_sec;
@@ -182,47 +185,39 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
/* can't send without a connection! */
return CURLE_SEND_ERROR;
- data = conn->data;
-
- fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
- if(!fmt_crlf)
- return CURLE_OUT_OF_MEMORY;
-
- s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */
- free(fmt_crlf);
- if(!s)
- return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_reset(&pp->sendbuf);
+ result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args);
+ if(result)
+ return result;
- bytes_written = 0;
- write_len = strlen(s);
+ /* append CRLF */
+ result = Curl_dyn_addn(&pp->sendbuf, "\r\n", 2);
+ if(result)
+ return result;
- Curl_pp_init(pp);
+ write_len = Curl_dyn_len(&pp->sendbuf);
+ s = Curl_dyn_ptr(&pp->sendbuf);
+ Curl_pp_init(data, pp);
result = Curl_convert_to_network(data, s, write_len);
/* Curl_convert_to_network calls failf if unsuccessful */
- if(result) {
- free(s);
+ if(result)
return result;
- }
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
#endif
- result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
- &bytes_written);
+ result = Curl_write(data, conn->sock[FIRSTSOCKET], s, write_len,
+ &bytes_written);
+ if(result)
+ return result;
#ifdef HAVE_GSSAPI
data_sec = conn->data_prot;
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
conn->data_prot = data_sec;
#endif
- if(result) {
- free(s);
- return result;
- }
-
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
+ Curl_debug(data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
if(bytes_written != (ssize_t)write_len) {
/* the whole chunk was not sent, keep it around and adjust sizes */
@@ -231,7 +226,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
pp->sendleft = write_len - bytes_written;
}
else {
- free(s);
pp->sendthis = NULL;
pp->sendleft = pp->sendsize = 0;
pp->response = Curl_now();
@@ -251,14 +245,14 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
*
* made to never block
*/
-CURLcode Curl_pp_sendf(struct pingpong *pp,
+CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp,
const char *fmt, ...)
{
CURLcode result;
va_list ap;
va_start(ap, fmt);
- result = Curl_pp_vsendf(pp, fmt, ap);
+ result = Curl_pp_vsendf(data, pp, fmt, ap);
va_end(ap);
@@ -270,7 +264,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
*
* Reads a piece of a server response.
*/
-CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+CURLcode Curl_pp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *code, /* return the server code if done */
size_t *size) /* size of the response */
@@ -279,8 +274,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
bool keepon = TRUE;
ssize_t gotbytes;
char *ptr;
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
char * const buf = data->state.buffer;
CURLcode result = CURLE_OK;
@@ -320,7 +314,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#endif
DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
(buf + data->set.buffer_size + 1));
- result = Curl_read(conn, sockfd, ptr,
+ result = Curl_read(data, sockfd, ptr,
data->set.buffer_size - pp->nread_resp,
&gotbytes);
#ifdef HAVE_GSSAPI
@@ -368,21 +362,20 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#ifdef HAVE_GSSAPI
if(!conn->sec_complete)
#endif
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- pp->linestart_resp, (size_t)perline);
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ pp->linestart_resp, (size_t)perline);
/*
* We pass all response-lines to the callback function registered
* for "headers". The response lines can be seen as a kind of
* headers.
*/
- result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ result = Curl_client_write(data, CLIENTWRITE_HEADER,
pp->linestart_resp, perline);
if(result)
return result;
- if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
+ if(pp->endofresp(data, conn, pp->linestart_resp, perline, code)) {
/* This is the end of the last line, copy the last line to the
start of the buffer and null-terminate, for old times sake */
size_t n = ptr - pp->linestart_resp;
@@ -462,10 +455,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
return result;
}
-int Curl_pp_getsock(struct pingpong *pp,
- curl_socket_t *socks)
+int Curl_pp_getsock(struct Curl_easy *data,
+ struct pingpong *pp, curl_socket_t *socks)
{
- struct connectdata *conn = pp->conn;
+ struct connectdata *conn = data->conn;
socks[0] = conn->sock[FIRSTSOCKET];
if(pp->sendleft) {
@@ -477,13 +470,14 @@ int Curl_pp_getsock(struct pingpong *pp,
return GETSOCK_READSOCK(0);
}
-CURLcode Curl_pp_flushsend(struct pingpong *pp)
+CURLcode Curl_pp_flushsend(struct Curl_easy *data,
+ struct pingpong *pp)
{
/* we have a piece of a command still left to send */
- struct connectdata *conn = pp->conn;
+ struct connectdata *conn = data->conn;
ssize_t written;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize -
+ CURLcode result = Curl_write(data, sock, pp->sendthis + pp->sendsize -
pp->sendleft, pp->sendleft, &written);
if(result)
return result;
@@ -493,7 +487,6 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
pp->sendleft -= written;
}
else {
- free(pp->sendthis);
pp->sendthis = NULL;
pp->sendleft = pp->sendsize = 0;
pp->response = Curl_now();
@@ -503,15 +496,15 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
CURLcode Curl_pp_disconnect(struct pingpong *pp)
{
- free(pp->cache);
- pp->cache = NULL;
+ Curl_dyn_free(&pp->sendbuf);
+ Curl_safefree(pp->cache);
return CURLE_OK;
}
bool Curl_pp_moredata(struct pingpong *pp)
{
return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
- TRUE : FALSE;
+ TRUE : FALSE;
}
#endif
diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h
index e874799d4..4f7d7ea6b 100644
--- a/Utilities/cmcurl/lib/pingpong.h
+++ b/Utilities/cmcurl/lib/pingpong.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -62,33 +62,42 @@ struct pingpong {
off, used to time-out response reading */
timediff_t response_time; /* When no timeout is given, this is the amount of
milliseconds we await for a server response. */
- struct connectdata *conn; /* points to the connectdata struct that this
- belongs to */
+ struct dynbuf sendbuf;
/* Function pointers the protocols MUST implement and provide for the
pingpong layer to function */
- CURLcode (*statemach_act)(struct connectdata *conn);
-
- bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len,
- int *code);
+ CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn);
+ bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn,
+ char *ptr, size_t len, int *code);
};
+#define PINGPONG_SETUP(pp,s,e) \
+ do { \
+ pp->response_time = RESP_TIMEOUT; \
+ pp->statemachine = s; \
+ pp->endofresp = e; \
+ } while(0)
+
/*
* Curl_pp_statemach()
*
* called repeatedly until done. Set 'wait' to make it wait a while on the
* socket if there's no traffic.
*/
-CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
- bool disconnecting);
+CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp,
+ bool block, bool disconnecting);
/* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct pingpong *pp);
+void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp);
+
+/* setup for the transfer */
+void Curl_pp_setup(struct pingpong *pp);
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
+timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
+ struct pingpong *pp, bool disconnecting);
/***********************************************************************
@@ -101,7 +110,8 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
*
* made to never block
*/
-CURLcode Curl_pp_sendf(struct pingpong *pp,
+CURLcode Curl_pp_sendf(struct Curl_easy *data,
+ struct pingpong *pp,
const char *fmt, ...);
/***********************************************************************
@@ -114,7 +124,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
*
* made to never block
*/
-CURLcode Curl_pp_vsendf(struct pingpong *pp,
+CURLcode Curl_pp_vsendf(struct Curl_easy *data,
+ struct pingpong *pp,
const char *fmt,
va_list args);
@@ -123,18 +134,21 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
*
* Reads a piece of a server response.
*/
-CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+CURLcode Curl_pp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *code, /* return the server code if done */
size_t *size); /* size of the response */
-CURLcode Curl_pp_flushsend(struct pingpong *pp);
+CURLcode Curl_pp_flushsend(struct Curl_easy *data,
+ struct pingpong *pp);
/* call this when a pingpong connection is disconnected */
CURLcode Curl_pp_disconnect(struct pingpong *pp);
-int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks);
+int Curl_pp_getsock(struct Curl_easy *data, struct pingpong *pp,
+ curl_socket_t *socks);
/***********************************************************************
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 9ff5c78fd..0ed3d3ee1 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -88,22 +88,27 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
-static CURLcode pop3_do(struct connectdata *conn, bool *done);
-static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode pop3_do(struct Curl_easy *data, bool *done);
+static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode pop3_connect(struct connectdata *conn, bool *done);
-static CURLcode pop3_disconnect(struct connectdata *conn, bool dead);
-static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done);
-static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode pop3_setup_connection(struct connectdata *conn);
+static CURLcode pop3_connect(struct Curl_easy *data, bool *done);
+static CURLcode pop3_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done);
+static int pop3_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode pop3_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
static CURLcode pop3_parse_url_options(struct connectdata *conn);
-static CURLcode pop3_parse_url_path(struct connectdata *conn);
-static CURLcode pop3_parse_custom_request(struct connectdata *conn);
-static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech,
+static CURLcode pop3_parse_url_path(struct Curl_easy *data);
+static CURLcode pop3_parse_custom_request(struct Curl_easy *data);
+static CURLcode pop3_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *mech,
const char *initresp);
-static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp);
+static CURLcode pop3_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *resp);
static void pop3_get_message(char *buffer, char **outptr);
/*
@@ -128,6 +133,7 @@ const struct Curl_handler Curl_handler_pop3 = {
ZERO_NULL, /* connection_check */
PORT_POP3, /* defport */
CURLPROTO_POP3, /* protocol */
+ CURLPROTO_POP3, /* family */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
PROTOPT_URLOPTIONS
};
@@ -155,6 +161,7 @@ const struct Curl_handler Curl_handler_pop3s = {
ZERO_NULL, /* connection_check */
PORT_POP3S, /* defport */
CURLPROTO_POP3S, /* protocol */
+ CURLPROTO_POP3, /* family */
PROTOPT_CLOSEACTION | PROTOPT_SSL
| PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
};
@@ -193,10 +200,11 @@ static void pop3_to_pop3s(struct connectdata *conn)
* capabilities from the CAPA response including the supported authentication
* types and allowed SASL mechanisms.
*/
-static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
- int *resp)
+static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *resp)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
+ (void)data;
/* Do we have an error response? */
if(len >= 4 && !memcmp("-ERR", line, 4)) {
@@ -277,9 +285,9 @@ static void pop3_get_message(char *buffer, char **outptr)
*
* This is the ONLY way to change POP3 state!
*/
-static void state(struct connectdata *conn, pop3state newstate)
+static void state(struct Curl_easy *data, pop3state newstate)
{
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = &data->conn->proto.pop3c;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -298,7 +306,7 @@ static void state(struct connectdata *conn, pop3state newstate)
};
if(pop3c->state != newstate)
- infof(conn->data, "POP3 %p state change from %s to %s\n",
+ infof(data, "POP3 %p state change from %s to %s\n",
(void *)pop3c, names[pop3c->state], names[newstate]);
#endif
@@ -312,7 +320,8 @@ static void state(struct connectdata *conn, pop3state newstate)
* Sends the CAPA command in order to obtain a list of server side supported
* capabilities.
*/
-static CURLcode pop3_perform_capa(struct connectdata *conn)
+static CURLcode pop3_perform_capa(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -322,10 +331,10 @@ static CURLcode pop3_perform_capa(struct connectdata *conn)
pop3c->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPA command */
- result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA");
+ result = Curl_pp_sendf(data, &pop3c->pp, "%s", "CAPA");
if(!result)
- state(conn, POP3_CAPA);
+ state(data, POP3_CAPA);
return result;
}
@@ -336,13 +345,14 @@ static CURLcode pop3_perform_capa(struct connectdata *conn)
*
* Sends the STLS command to start the upgrade to TLS.
*/
-static CURLcode pop3_perform_starttls(struct connectdata *conn)
+static CURLcode pop3_perform_starttls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the STLS command */
- CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS");
if(!result)
- state(conn, POP3_STARTTLS);
+ state(data, POP3_STARTTLS);
return result;
}
@@ -353,20 +363,21 @@ static CURLcode pop3_perform_starttls(struct connectdata *conn)
*
* Performs the upgrade to TLS.
*/
-static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
+static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Start the SSL connection */
struct pop3_conn *pop3c = &conn->proto.pop3c;
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&pop3c->ssldone);
if(!result) {
if(pop3c->state != POP3_UPGRADETLS)
- state(conn, POP3_UPGRADETLS);
+ state(data, POP3_UPGRADETLS);
if(pop3c->ssldone) {
pop3_to_pop3s(conn);
- result = pop3_perform_capa(conn);
+ result = pop3_perform_capa(data, conn);
}
}
@@ -379,23 +390,24 @@ static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
*
* Sends a clear text USER command to authenticate with.
*/
-static CURLcode pop3_perform_user(struct connectdata *conn)
+static CURLcode pop3_perform_user(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!conn->bits.user_passwd) {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
/* Send the USER command */
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s",
conn->user ? conn->user : "");
if(!result)
- state(conn, POP3_USER);
+ state(data, POP3_USER);
return result;
}
@@ -407,7 +419,8 @@ static CURLcode pop3_perform_user(struct connectdata *conn)
*
* Sends an APOP command to authenticate with.
*/
-static CURLcode pop3_perform_apop(struct connectdata *conn)
+static CURLcode pop3_perform_apop(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -419,7 +432,7 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!conn->bits.user_passwd) {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
@@ -442,10 +455,10 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
for(i = 0; i < MD5_DIGEST_LEN; i++)
msnprintf(&secret[2 * i], 3, "%02x", digest[i]);
- result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
+ result = Curl_pp_sendf(data, &pop3c->pp, "APOP %s %s", conn->user, secret);
if(!result)
- state(conn, POP3_APOP);
+ state(data, POP3_APOP);
return result;
}
@@ -458,7 +471,8 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
* Sends an AUTH command allowing the client to login with the given SASL
* authentication mechanism.
*/
-static CURLcode pop3_perform_auth(struct connectdata *conn,
+static CURLcode pop3_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp)
{
@@ -467,11 +481,11 @@ static CURLcode pop3_perform_auth(struct connectdata *conn,
if(initresp) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
- result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
+ result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, initresp);
}
else {
/* Send the AUTH command */
- result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
+ result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s", mech);
}
return result;
@@ -483,12 +497,13 @@ static CURLcode pop3_perform_auth(struct connectdata *conn,
*
* Sends SASL continuation data or cancellation.
*/
-static CURLcode pop3_continue_auth(struct connectdata *conn,
+static CURLcode pop3_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *resp)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
- return Curl_pp_sendf(&pop3c->pp, "%s", resp);
+ return Curl_pp_sendf(data, &pop3c->pp, "%s", resp);
}
/***********************************************************************
@@ -499,7 +514,8 @@ static CURLcode pop3_continue_auth(struct connectdata *conn,
* authentication mechanism, falling back to APOP and clear text should a
* common mechanism not be available between the client and server.
*/
-static CURLcode pop3_perform_authentication(struct connectdata *conn)
+static CURLcode pop3_perform_authentication(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -508,32 +524,32 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
/* Check we have enough data to authenticate with and end the
connect phase if we don't */
if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) {
/* Calculate the SASL login details */
- result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress);
+ result = Curl_sasl_start(&pop3c->sasl, data, conn, FALSE, &progress);
if(!result)
if(progress == SASL_INPROGRESS)
- state(conn, POP3_AUTH);
+ state(data, POP3_AUTH);
}
if(!result && progress == SASL_IDLE) {
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */
- result = pop3_perform_apop(conn);
+ result = pop3_perform_apop(data, conn);
else
#endif
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */
- result = pop3_perform_user(conn);
+ result = pop3_perform_user(data, conn);
else {
/* Other mechanisms not supported */
- infof(conn->data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
}
@@ -547,15 +563,15 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
*
* Sends a POP3 based command.
*/
-static CURLcode pop3_perform_command(struct connectdata *conn)
+static CURLcode pop3_perform_command(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct POP3 *pop3 = data->req.p.pop3;
const char *command = NULL;
/* Calculate the default command */
- if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
+ if(pop3->id[0] == '\0' || data->set.ftp_list_only) {
command = "LIST";
if(pop3->id[0] != '\0')
@@ -567,16 +583,16 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
/* Send the command */
if(pop3->id[0] != '\0')
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s %s",
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command), pop3->id);
else
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s",
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command));
if(!result)
- state(conn, POP3_COMMAND);
+ state(data, POP3_COMMAND);
return result;
}
@@ -587,24 +603,25 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
*
* Performs the quit action prior to sclose() be called.
*/
-static CURLcode pop3_perform_quit(struct connectdata *conn)
+static CURLcode pop3_perform_quit(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the QUIT command */
- CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT");
if(!result)
- state(conn, POP3_QUIT);
+ state(data, POP3_QUIT);
return result;
}
/* For the initial server greeting */
-static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
+static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
@@ -652,18 +669,18 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
}
}
- result = pop3_perform_capa(conn);
+ result = pop3_perform_capa(data, conn);
}
return result;
}
/* For CAPA responses */
-static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
@@ -726,36 +743,35 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(pop3c->tls_supported)
/* Switch to TLS connection now */
- result = pop3_perform_starttls(conn);
+ result = pop3_perform_starttls(data, conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
else {
failf(data, "STLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
}
else {
/* Clear text is supported when CAPA isn't recognised */
pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
}
return result;
}
/* For STARTTLS responses */
-static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
+static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
+ struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -764,42 +780,42 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
}
else
- result = pop3_perform_upgrade_tls(conn);
+ result = pop3_perform_upgrade_tls(data, conn);
return result;
}
/* For SASL authentication responses */
-static CURLcode pop3_state_auth_resp(struct connectdata *conn,
+static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
saslprogress progress;
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress);
+ result = Curl_sasl_continue(&pop3c->sasl, data, conn, pop3code, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
- state(conn, POP3_STOP); /* Authenticated */
+ state(data, POP3_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */
- result = pop3_perform_apop(conn);
+ result = pop3_perform_apop(data, conn);
else
#endif
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */
- result = pop3_perform_user(conn);
+ result = pop3_perform_user(data, conn);
else {
failf(data, "Authentication cancelled");
result = CURLE_LOGIN_DENIED;
@@ -814,12 +830,10 @@ static CURLcode pop3_state_auth_resp(struct connectdata *conn,
#ifndef CURL_DISABLE_CRYPTO_AUTH
/* For APOP responses */
-static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_apop_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -828,19 +842,18 @@ static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
}
else
/* End of connect phase */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
#endif
/* For USER responses */
-static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_user_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -849,21 +862,19 @@ static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code,
}
else
/* Send the PASS command */
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "PASS %s",
conn->passwd ? conn->passwd : "");
if(!result)
- state(conn, POP3_PASS);
+ state(data, POP3_PASS);
return result;
}
/* For PASS responses */
-static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_pass_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -872,26 +883,26 @@ static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
}
else
/* End of connect phase */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
/* For command responses */
-static CURLcode pop3_state_command_resp(struct connectdata *conn,
+static CURLcode pop3_state_command_resp(struct Curl_easy *data,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct POP3 *pop3 = data->req.p.pop3;
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return CURLE_RECV_ERROR;
}
@@ -915,7 +926,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
"headers" after the body */
if(!data->set.opt_no_body) {
- result = Curl_pop3_write(conn, pp->cache, pp->cache_size);
+ result = Curl_pop3_write(data, pp->cache, pp->cache_size);
if(result)
return result;
}
@@ -929,12 +940,13 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
}
/* End of DO phase */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
-static CURLcode pop3_statemach_act(struct connectdata *conn)
+static CURLcode pop3_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
@@ -942,20 +954,21 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
size_t nread = 0;
+ (void)data;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
if(pop3c->state == POP3_UPGRADETLS)
- return pop3_perform_upgrade_tls(conn);
+ return pop3_perform_upgrade_tls(data, conn);
/* Flush any data that needs to be sent */
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
do {
/* Read the response from the server */
- result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
- if(result)
- return result;
+ result = Curl_pp_readresp(data, sock, pp, &pop3code, &nread);
+ if(result)
+ return result;
if(!pop3code)
break;
@@ -963,44 +976,44 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
/* We have now received a full POP3 server response */
switch(pop3c->state) {
case POP3_SERVERGREET:
- result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_servergreet_resp(data, pop3code, pop3c->state);
break;
case POP3_CAPA:
- result = pop3_state_capa_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_capa_resp(data, pop3code, pop3c->state);
break;
case POP3_STARTTLS:
- result = pop3_state_starttls_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_starttls_resp(data, conn, pop3code, pop3c->state);
break;
case POP3_AUTH:
- result = pop3_state_auth_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_auth_resp(data, pop3code, pop3c->state);
break;
#ifndef CURL_DISABLE_CRYPTO_AUTH
case POP3_APOP:
- result = pop3_state_apop_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_apop_resp(data, pop3code, pop3c->state);
break;
#endif
case POP3_USER:
- result = pop3_state_user_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_user_resp(data, pop3code, pop3c->state);
break;
case POP3_PASS:
- result = pop3_state_pass_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_pass_resp(data, pop3code, pop3c->state);
break;
case POP3_COMMAND:
- result = pop3_state_command_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_command_resp(data, pop3code, pop3c->state);
break;
case POP3_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
break;
}
} while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
@@ -1009,44 +1022,46 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
}
/* Called repeatedly until done from multi.c */
-static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &pop3c->ssldone);
if(result || !pop3c->ssldone)
return result;
}
- result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE);
+ result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE);
*done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
return result;
}
-static CURLcode pop3_block_statemach(struct connectdata *conn,
+static CURLcode pop3_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
bool disconnecting)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
while(pop3c->state != POP3_STOP && !result)
- result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting);
+ result = Curl_pp_statemach(data, &pop3c->pp, TRUE, disconnecting);
return result;
}
/* Allocate and initialize the POP3 struct for the current Curl_easy if
required */
-static CURLcode pop3_init(struct connectdata *conn)
+static CURLcode pop3_init(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct POP3 *pop3;
- pop3 = data->req.protop = calloc(sizeof(struct POP3), 1);
+ pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1);
if(!pop3)
result = CURLE_OUT_OF_MEMORY;
@@ -1054,9 +1069,10 @@ static CURLcode pop3_init(struct connectdata *conn)
}
/* For the POP3 "protocol connect" and "doing" phases only */
-static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int pop3_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.pop3c.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.pop3c.pp, socks);
}
/***********************************************************************
@@ -1069,9 +1085,10 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks)
* The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE if not.
*/
-static CURLcode pop3_connect(struct connectdata *conn, bool *done)
+static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
@@ -1080,18 +1097,15 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
/* We always support persistent connections in POP3 */
connkeep(conn, "POP3 default");
- /* Set the default response time-out */
- pp->response_time = RESP_TIMEOUT;
- pp->statemach_act = pop3_statemach_act;
- pp->endofresp = pop3_endofresp;
- pp->conn = conn;
+ PINGPONG_SETUP(pp, pop3_statemachine, pop3_endofresp);
/* Set the default preferred authentication type and mechanism */
pop3c->preftype = POP3_TYPE_ANY;
Curl_sasl_init(&pop3c->sasl, &saslpop3);
/* Initialise the pingpong layer */
- Curl_pp_init(pp);
+ Curl_pp_setup(pp);
+ Curl_pp_init(data, pp);
/* Parse the URL options */
result = pop3_parse_url_options(conn);
@@ -1099,9 +1113,9 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
return result;
/* Start off waiting for the server greeting response */
- state(conn, POP3_SERVERGREET);
+ state(data, POP3_SERVERGREET);
- result = pop3_multi_statemach(conn, done);
+ result = pop3_multi_statemach(data, done);
return result;
}
@@ -1115,12 +1129,11 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
*
* Input argument is already checked for validity.
*/
-static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct POP3 *pop3 = data->req.p.pop3;
(void)premature;
@@ -1128,7 +1141,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
return CURLE_OK;
if(status) {
- connclose(conn, "POP3 done with bad status");
+ connclose(data->conn, "POP3 done with bad status");
result = status; /* use the already set error code */
}
@@ -1149,16 +1162,17 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
* This is the actual DO function for POP3. Get a message/listing according to
* the options previously setup.
*/
-static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
+static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
bool *dophase_done)
{
/* This is POP3 and no proxy */
CURLcode result = CURLE_OK;
- struct POP3 *pop3 = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct POP3 *pop3 = data->req.p.pop3;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
- if(conn->data->set.opt_no_body) {
+ if(data->set.opt_no_body) {
/* Requested no body means no transfer */
pop3->transfer = FTPTRANSFER_INFO;
}
@@ -1166,17 +1180,16 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
*dophase_done = FALSE; /* not done yet */
/* Start the first command in the DO phase */
- result = pop3_perform_command(conn);
+ result = pop3_perform_command(data);
if(result)
return result;
/* Run the state-machine */
- result = pop3_multi_statemach(conn, dophase_done);
-
+ result = pop3_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1190,23 +1203,22 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
*
* The input argument is already checked for validity.
*/
-static CURLcode pop3_do(struct connectdata *conn, bool *done)
+static CURLcode pop3_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
-
*done = FALSE; /* default to false */
/* Parse the URL path */
- result = pop3_parse_url_path(conn);
+ result = pop3_parse_url_path(data);
if(result)
return result;
/* Parse the custom request */
- result = pop3_parse_custom_request(conn);
+ result = pop3_parse_custom_request(data);
if(result)
return result;
- result = pop3_regular_transfer(conn, done);
+ result = pop3_regular_transfer(data, done);
return result;
}
@@ -1218,19 +1230,20 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
* Disconnect from an POP3 server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode pop3_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
+ (void)data;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to. */
- /* The POP3 session may or may not have been allocated/setup at this
- point! */
- if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart)
- if(!pop3_perform_quit(conn))
- (void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */
+ if(!dead_connection && conn->bits.protoconnstart) {
+ if(!pop3_perform_quit(data, conn))
+ (void)pop3_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */
+ }
/* Disconnect from the server */
Curl_pp_disconnect(&pop3c->pp);
@@ -1245,25 +1258,25 @@ static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
}
/* Call this when the DO phase has completed */
-static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected)
+static CURLcode pop3_dophase_done(struct Curl_easy *data, bool connected)
{
- (void)conn;
+ (void)data;
(void)connected;
return CURLE_OK;
}
/* Called from multi.c while DOing */
-static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = pop3_multi_statemach(conn, dophase_done);
+ CURLcode result = pop3_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = pop3_dophase_done(conn, FALSE /* not connected */);
+ result = pop3_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -1278,12 +1291,11 @@ static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done)
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
-static CURLcode pop3_regular_transfer(struct connectdata *conn,
+static CURLcode pop3_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
@@ -1295,19 +1307,20 @@ static CURLcode pop3_regular_transfer(struct connectdata *conn,
Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */
- result = pop3_perform(conn, &connected, dophase_done);
+ result = pop3_perform(data, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = pop3_dophase_done(conn, connected);
+ result = pop3_dophase_done(data, connected);
return result;
}
-static CURLcode pop3_setup_connection(struct connectdata *conn)
+static CURLcode pop3_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Initialise the POP3 layer */
- CURLcode result = pop3_init(conn);
+ CURLcode result = pop3_init(data);
if(result)
return result;
@@ -1382,11 +1395,10 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
*
* Parse the URL path into separate path components.
*/
-static CURLcode pop3_parse_url_path(struct connectdata *conn)
+static CURLcode pop3_parse_url_path(struct Curl_easy *data)
{
/* The POP3 struct is already initialised in pop3_connect() */
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct POP3 *pop3 = data->req.p.pop3;
const char *path = &data->state.up.path[1]; /* skip leading path */
/* URL decode the path for the message ID */
@@ -1399,11 +1411,10 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
*
* Parse the custom request.
*/
-static CURLcode pop3_parse_custom_request(struct connectdata *conn)
+static CURLcode pop3_parse_custom_request(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct POP3 *pop3 = data->req.p.pop3;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
@@ -1420,13 +1431,12 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
* This function scans the body after the end-of-body and writes everything
* until the end is found.
*/
-CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
+CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread)
{
/* This code could be made into a special function in the handler struct */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
-
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
bool strip_dot = FALSE;
size_t last = 0;
@@ -1447,7 +1457,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
if(i) {
/* Write out the body part that didn't match */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last],
i - last);
if(result)
@@ -1505,7 +1515,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, 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(conn, CLIENTWRITE_BODY, (char *)POP3_EOB,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
strip_dot ? prev - 1 : prev);
if(result)
@@ -1521,7 +1531,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
/* We have a full match so the transfer is done, however we must transfer
the CRLF at the start of the EOB as this is considered to be part of the
message as per RFC-1939, sect. 3 */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, 2);
k->keepon &= ~KEEP_RECV;
pop3c->eob = 0;
@@ -1534,7 +1544,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
return CURLE_OK;
if(nread - last) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last],
nread - last);
}
diff --git a/Utilities/cmcurl/lib/pop3.h b/Utilities/cmcurl/lib/pop3.h
index 3ba799977..17629ee2d 100644
--- a/Utilities/cmcurl/lib/pop3.h
+++ b/Utilities/cmcurl/lib/pop3.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -61,6 +61,7 @@ struct pop3_conn {
struct pingpong pp;
pop3state state; /* Always use pop3.c:state() to change state! */
bool ssldone; /* Is connect() over SSL done? */
+ bool tls_supported; /* StartTLS capability supported by server */
size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */
size_t strip; /* Number of bytes from the start to ignore as
@@ -69,7 +70,6 @@ struct pop3_conn {
unsigned int authtypes; /* Accepted authentication types */
unsigned int preftype; /* Preferred authentication type */
char *apoptimestamp; /* APOP timestamp from the server greeting */
- bool tls_supported; /* StartTLS capability supported by server */
};
extern const struct Curl_handler Curl_handler_pop3;
@@ -90,6 +90,6 @@ extern const struct Curl_handler Curl_handler_pop3s;
/* This function scans the body after the end-of-body and writes everything
* until the end is found */
-CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread);
+CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread);
#endif /* HEADER_CURL_POP3_H */
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index 895138448..55e8ded04 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -137,12 +137,11 @@ static char *max5data(curl_off_t bytes, char *max5)
*/
-int Curl_pgrsDone(struct connectdata *conn)
+int Curl_pgrsDone(struct Curl_easy *data)
{
int rc;
- struct Curl_easy *data = conn->data;
data->progress.lastshow = 0;
- rc = Curl_pgrsUpdate(conn); /* the final (forced) update */
+ rc = Curl_pgrsUpdate(data); /* the final (forced) update */
if(rc)
return rc;
@@ -164,9 +163,13 @@ void Curl_pgrsResetTransferSizes(struct Curl_easy *data)
}
/*
+ *
+ * Curl_pgrsTime(). Store the current time at the given label. This fetches a
+ * fresh "now" and returns it.
+ *
* @unittest: 1399
*/
-void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
+struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer)
{
struct curltime now = Curl_now();
timediff_t *delta = NULL;
@@ -209,7 +212,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
* changing the t_starttransfer time.
*/
if(data->progress.is_t_startransfer_set) {
- return;
+ return now;
}
else {
data->progress.is_t_startransfer_set = true;
@@ -228,6 +231,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
us = 1; /* make sure at least one microsecond passed */
*delta += us;
}
+ return now;
}
void Curl_pgrsStartNow(struct Curl_easy *data)
@@ -235,10 +239,8 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_now();
data->progress.is_t_startransfer_set = false;
- data->progress.ul_limit_start.tv_sec = 0;
- data->progress.ul_limit_start.tv_usec = 0;
- data->progress.dl_limit_start.tv_sec = 0;
- data->progress.dl_limit_start.tv_usec = 0;
+ data->progress.ul_limit_start = data->progress.start;
+ data->progress.dl_limit_start = data->progress.start;
data->progress.downloaded = 0;
data->progress.uploaded = 0;
/* clear all bits except HIDE and HEADERS_OUT */
@@ -368,11 +370,10 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
}
/* returns TRUE if it's time to show the progress meter */
-static bool progress_calc(struct connectdata *conn, struct curltime now)
+static bool progress_calc(struct Curl_easy *data, struct curltime now)
{
curl_off_t timespent;
curl_off_t timespent_ms; /* milliseconds */
- struct Curl_easy *data = conn->data;
curl_off_t dl = data->progress.downloaded;
curl_off_t ul = data->progress.uploaded;
bool timetoshow = FALSE;
@@ -462,9 +463,8 @@ static bool progress_calc(struct connectdata *conn, struct curltime now)
}
#ifndef CURL_DISABLE_PROGRESS_METER
-static void progress_meter(struct connectdata *conn)
+static void progress_meter(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
char max5[6][10];
curl_off_t dlpercen = 0;
curl_off_t ulpercen = 0;
@@ -578,11 +578,10 @@ static void progress_meter(struct connectdata *conn)
* Curl_pgrsUpdate() returns 0 for success or the value returned by the
* progress callback!
*/
-int Curl_pgrsUpdate(struct connectdata *conn)
+int Curl_pgrsUpdate(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
struct curltime now = Curl_now(); /* what time is it */
- bool showprogress = progress_calc(conn, now);
+ bool showprogress = progress_calc(data, now);
if(!(data->progress.flags & PGRS_HIDE)) {
if(data->set.fxferinfo) {
int result;
@@ -618,7 +617,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
}
if(showprogress)
- progress_meter(conn);
+ progress_meter(data);
}
return 0;
diff --git a/Utilities/cmcurl/lib/progress.h b/Utilities/cmcurl/lib/progress.h
index 3515ac6d5..ac4ebc098 100644
--- a/Utilities/cmcurl/lib/progress.h
+++ b/Utilities/cmcurl/lib/progress.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -40,16 +40,16 @@ typedef enum {
TIMER_LAST /* must be last */
} timerid;
-int Curl_pgrsDone(struct connectdata *);
+int Curl_pgrsDone(struct Curl_easy *data);
void Curl_pgrsStartNow(struct Curl_easy *data);
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
-int Curl_pgrsUpdate(struct connectdata *);
+int Curl_pgrsUpdate(struct Curl_easy *data);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
-void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
+struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer);
timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
curl_off_t startsize,
curl_off_t limit,
diff --git a/Utilities/cmcurl/lib/psl.c b/Utilities/cmcurl/lib/psl.c
index 568baff03..e46091863 100644
--- a/Utilities/cmcurl/lib/psl.c
+++ b/Utilities/cmcurl/lib/psl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/psl.h b/Utilities/cmcurl/lib/psl.h
index e9f99d03e..c10367471 100644
--- a/Utilities/cmcurl/lib/psl.h
+++ b/Utilities/cmcurl/lib/psl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/quic.h b/Utilities/cmcurl/lib/quic.h
index 8e7df90ea..947f13edc 100644
--- a/Utilities/cmcurl/lib/quic.h
+++ b/Utilities/cmcurl/lib/quic.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -35,25 +35,28 @@
#include "urldata.h"
/* functions provided by the specific backends */
-CURLcode Curl_quic_connect(struct connectdata *conn,
+CURLcode Curl_quic_connect(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t sockfd,
int sockindex,
const struct sockaddr *addr,
socklen_t addrlen);
-CURLcode Curl_quic_is_connected(struct connectdata *conn,
- curl_socket_t sockfd,
+CURLcode Curl_quic_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
bool *connected);
int Curl_quic_ver(char *p, size_t len);
-CURLcode Curl_quic_done_sending(struct connectdata *conn);
+CURLcode Curl_quic_done_sending(struct Curl_easy *data);
void Curl_quic_done(struct Curl_easy *data, bool premature);
bool Curl_quic_data_pending(const struct Curl_easy *data);
-void Curl_quic_disconnect(struct connectdata *conn, int tempindex);
+void Curl_quic_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, int tempindex);
#else /* ENABLE_QUIC */
#define Curl_quic_done_sending(x)
#define Curl_quic_done(x,y)
#define Curl_quic_data_pending(x)
-#define Curl_quic_disconnect(x,y)
+#define Curl_quic_disconnect(x,y,z)
#endif /* !ENABLE_QUIC */
#endif /* HEADER_CURL_QUIC_H */
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
index c415048ec..951fedb0a 100644
--- a/Utilities/cmcurl/lib/rand.c
+++ b/Utilities/cmcurl/lib/rand.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h
index 3c8e2b81d..02d95d8e6 100644
--- a/Utilities/cmcurl/lib/rand.h
+++ b/Utilities/cmcurl/lib/rand.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/rename.c b/Utilities/cmcurl/lib/rename.c
index fe5f95d0d..f858d4369 100644
--- a/Utilities/cmcurl/lib/rename.c
+++ b/Utilities/cmcurl/lib/rename.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -24,8 +24,8 @@
#include "curl_setup.h"
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \
- defined(USE_ALTSVC)
+#if (!defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_COOKIES)) || \
+ !defined(CURL_DISABLE_ALTSVC)
#include "curl_multibyte.h"
#include "timeval.h"
diff --git a/Utilities/cmcurl/lib/rename.h b/Utilities/cmcurl/lib/rename.h
index d7442c844..534f7471c 100644
--- a/Utilities/cmcurl/lib/rename.h
+++ b/Utilities/cmcurl/lib/rename.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index dbd7dc6a6..55766757a 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -22,7 +22,7 @@
#include "curl_setup.h"
-#ifndef CURL_DISABLE_RTSP
+#if !defined(CURL_DISABLE_RTSP) && !defined(USE_HYPER)
#include "urldata.h"
#include <curl/curl.h>
@@ -48,11 +48,13 @@
((int)((unsigned char)((p)[3]))))
/* protocol-specific functions set up to be called by the main engine */
-static CURLcode rtsp_do(struct connectdata *conn, bool *done);
-static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature);
-static CURLcode rtsp_connect(struct connectdata *conn, bool *done);
-static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead);
-static int rtsp_getsock_do(struct connectdata *conn, curl_socket_t *socks);
+static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
+static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature);
+static CURLcode rtsp_connect(struct Curl_easy *data, bool *done);
+static CURLcode rtsp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static int rtsp_getsock_do(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/*
* Parse and write out any available RTP data.
@@ -66,23 +68,26 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
ssize_t *nread,
bool *readmore);
-static CURLcode rtsp_setup_connection(struct connectdata *conn);
-static unsigned int rtsp_conncheck(struct connectdata *check,
+static CURLcode rtsp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static unsigned int rtsp_conncheck(struct Curl_easy *data,
+ struct connectdata *check,
unsigned int checks_to_perform);
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */
-static int rtsp_getsock_do(struct connectdata *conn,
+static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks)
{
/* write mode */
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
static
-CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
+CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
/*
@@ -106,15 +111,18 @@ const struct Curl_handler Curl_handler_rtsp = {
rtsp_conncheck, /* connection_check */
PORT_RTSP, /* defport */
CURLPROTO_RTSP, /* protocol */
+ CURLPROTO_RTSP, /* family */
PROTOPT_NONE /* flags */
};
-static CURLcode rtsp_setup_connection(struct connectdata *conn)
+static CURLcode rtsp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct RTSP *rtsp;
+ (void)conn;
- conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP));
+ data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
if(!rtsp)
return CURLE_OUT_OF_MEMORY;
@@ -155,13 +163,15 @@ static bool rtsp_connisdead(struct connectdata *check)
/*
* Function to check on various aspects of a connection.
*/
-static unsigned int rtsp_conncheck(struct connectdata *check,
+static unsigned int rtsp_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
+ (void)data;
if(checks_to_perform & CONNCHECK_ISDEAD) {
- if(rtsp_connisdead(check))
+ if(rtsp_connisdead(conn))
ret_val |= CONNRESULT_DEAD;
}
@@ -169,12 +179,11 @@ static unsigned int rtsp_conncheck(struct connectdata *check,
}
-static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
+static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
{
CURLcode httpStatus;
- struct Curl_easy *data = conn->data;
- httpStatus = Curl_http_connect(conn, done);
+ httpStatus = Curl_http_connect(data, done);
/* Initialize the CSeq if not already done */
if(data->state.rtsp_next_client_CSeq == 0)
@@ -182,31 +191,32 @@ static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
if(data->state.rtsp_next_server_CSeq == 0)
data->state.rtsp_next_server_CSeq = 1;
- conn->proto.rtspc.rtp_channel = -1;
+ data->conn->proto.rtspc.rtp_channel = -1;
return httpStatus;
}
-static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead)
+static CURLcode rtsp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead)
{
(void) dead;
+ (void) data;
Curl_safefree(conn->proto.rtspc.rtp_buf);
return CURLE_OK;
}
-static CURLcode rtsp_done(struct connectdata *conn,
+static CURLcode rtsp_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct Curl_easy *data = conn->data;
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
CURLcode httpStatus;
/* Bypass HTTP empty-reply checks on receive */
if(data->set.rtspreq == RTSPREQ_RECEIVE)
premature = TRUE;
- httpStatus = Curl_http_done(conn, status, premature);
+ httpStatus = Curl_http_done(data, status, premature);
if(rtsp) {
/* Check the sequence numbers */
@@ -219,7 +229,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
return CURLE_RTSP_CSEQ_ERROR;
}
if(data->set.rtspreq == RTSPREQ_RECEIVE &&
- (conn->proto.rtspc.rtp_channel == -1)) {
+ (data->conn->proto.rtspc.rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
}
}
@@ -227,12 +237,12 @@ static CURLcode rtsp_done(struct connectdata *conn,
return httpStatus;
}
-static CURLcode rtsp_do(struct connectdata *conn, bool *done)
+static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
struct dynbuf req_buffer;
curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
@@ -329,7 +339,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* Transport Header for SETUP requests */
- p_transport = Curl_checkheaders(conn, "Transport");
+ p_transport = Curl_checkheaders(data, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
@@ -353,11 +363,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept")?
+ p_accept = Curl_checkheaders(data, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding") &&
+ if(!Curl_checkheaders(data, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(data->state.aptr.accept_encoding);
data->state.aptr.accept_encoding =
@@ -374,17 +384,18 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent") && data->state.aptr.uagent) {
+ if(Curl_checkheaders(data, "User-Agent") && data->state.aptr.uagent) {
Curl_safefree(data->state.aptr.uagent);
data->state.aptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent") &&
+ else if(!Curl_checkheaders(data, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = data->state.aptr.uagent;
}
/* setup the authentication headers */
- result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE);
+ result = Curl_http_output_auth(data, conn, p_request, HTTPREQ_GET,
+ p_stream_uri, FALSE);
if(result)
return result;
@@ -393,7 +404,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */
Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
+ if(data->change.referer && !Curl_checkheaders(data, "Referer"))
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
data->state.aptr.ref = NULL;
@@ -410,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */
- if(!Curl_checkheaders(conn, "Range") && data->state.range) {
+ if(!Curl_checkheaders(data, "Range") && data->state.range) {
Curl_safefree(data->state.aptr.rangeline);
data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = data->state.aptr.rangeline;
@@ -420,11 +431,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* Sanity check the custom headers
*/
- if(Curl_checkheaders(conn, "CSeq")) {
+ if(Curl_checkheaders(data, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
- if(Curl_checkheaders(conn, "Session")) {
+ if(Curl_checkheaders(data, "Session")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
@@ -483,12 +494,12 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
return result;
if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
- result = Curl_add_timecondition(conn, &req_buffer);
+ result = Curl_add_timecondition(data, &req_buffer);
if(result)
return result;
}
- result = Curl_add_custom_headers(conn, FALSE, &req_buffer);
+ result = Curl_add_custom_headers(data, FALSE, &req_buffer);
if(result)
return result;
@@ -511,7 +522,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
- if(!Curl_checkheaders(conn, "Content-Length")) {
+ if(!Curl_checkheaders(data, "Content-Length")) {
result =
Curl_dyn_addf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
@@ -522,7 +533,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type")) {
+ if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
@@ -531,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type")) {
+ if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
@@ -563,7 +574,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* issue the request */
- result = Curl_buffer_send(&req_buffer, conn,
+ result = Curl_buffer_send(&req_buffer, data,
&data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
@@ -579,7 +590,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* if a request-body has been sent off, we make sure this progress is
noted properly */
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
}
@@ -641,7 +652,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
* Write out the header including the leading '$' */
DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
rtspc->rtp_channel, rtp_length));
- result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
+ result = rtp_client_write(data, &rtp[0], rtp_length + 4);
if(result) {
failf(data, "Got an error writing an RTP packet");
*readmore = FALSE;
@@ -712,9 +723,8 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
}
static
-CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
+CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
{
- struct Curl_easy *data = conn->data;
size_t wrote;
curl_write_callback writeit;
void *user_ptr;
@@ -754,17 +764,15 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
return CURLE_OK;
}
-CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
- char *header)
+CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
{
- struct Curl_easy *data = conn->data;
long CSeq = 0;
if(checkprefix("CSeq:", header)) {
/* Store the received CSeq. Match is verified in rtsp_done */
int nc = sscanf(&header[4], ": %ld", &CSeq);
if(nc == 1) {
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
rtsp->CSeq_recv = CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
}
@@ -775,6 +783,8 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
}
else if(checkprefix("Session:", header)) {
char *start;
+ char *end;
+ size_t idlen;
/* Find the first non-space letter */
start = header + 8;
@@ -783,11 +793,25 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
if(!*start) {
failf(data, "Got a blank Session ID");
+ return CURLE_RTSP_SESSION_ERROR;
}
- else if(data->set.str[STRING_RTSP_SESSION_ID]) {
+
+ /* Find the end of Session ID
+ *
+ * Allow any non whitespace content, up to the field separator or end of
+ * line. RFC 2326 isn't 100% clear on the session ID and for example
+ * gstreamer does url-encoded session ID's not covered by the standard.
+ */
+ end = start;
+ while(*end && *end != ';' && !ISSPACE(*end))
+ end++;
+ idlen = end - start;
+
+ if(data->set.str[STRING_RTSP_SESSION_ID]) {
+
/* If the Session ID is set, then compare */
- if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID],
- strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) {
+ if(strlen(data->set.str[STRING_RTSP_SESSION_ID]) != idlen ||
+ strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen) != 0) {
failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
start, data->set.str[STRING_RTSP_SESSION_ID]);
return CURLE_RTSP_SESSION_ERROR;
@@ -796,24 +820,17 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
else {
/* If the Session ID is not set, and we find it in a response, then set
* it.
- *
- * Allow any non whitespace content, up to the field separator or end of
- * line. RFC 2326 isn't 100% clear on the session ID and for example
- * gstreamer does url-encoded session ID's not covered by the standard.
*/
- char *end = start;
- while(*end && *end != ';' && !ISSPACE(*end))
- end++;
/* Copy the id substring into a new buffer */
- data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1);
+ data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1);
if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
return CURLE_OUT_OF_MEMORY;
- memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start);
- (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0';
+ memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
+ (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
}
}
return CURLE_OK;
}
-#endif /* CURL_DISABLE_RTSP */
+#endif /* CURL_DISABLE_RTSP or using Hyper */
diff --git a/Utilities/cmcurl/lib/rtsp.h b/Utilities/cmcurl/lib/rtsp.h
index 1aae86456..1e9cb7d2c 100644
--- a/Utilities/cmcurl/lib/rtsp.h
+++ b/Utilities/cmcurl/lib/rtsp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -21,11 +21,15 @@
* KIND, either express or implied.
*
***************************************************************************/
+#ifdef USE_HYPER
+#define CURL_DISABLE_RTSP
+#endif
+
#ifndef CURL_DISABLE_RTSP
extern const struct Curl_handler Curl_handler_rtsp;
-CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);
+CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
#else
/* disabled */
diff --git a/Utilities/cmcurl/lib/security.c b/Utilities/cmcurl/lib/security.c
deleted file mode 100644
index 3b9c20a73..000000000
--- a/Utilities/cmcurl/lib/security.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
- * use in Curl. His latest changes were done 2000-09-18.
- *
- * It has since been patched and modified a lot by Daniel Stenberg
- * <daniel@haxx.se> to make it better applied to curl conditions, and to make
- * it not use globals, pollute name space and more. This source code awaits a
- * rewrite to work around the paragraph 2 in the BSD licenses as explained
- * below.
- *
- * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- *
- * Copyright (C) 2001 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE. */
-
-#include "curl_setup.h"
-
-#ifndef CURL_DISABLE_FTP
-#ifdef HAVE_GSSAPI
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#include <limits.h>
-
-#include "urldata.h"
-#include "curl_base64.h"
-#include "curl_memory.h"
-#include "curl_sec.h"
-#include "ftp.h"
-#include "sendf.h"
-#include "strcase.h"
-#include "warnless.h"
-#include "strdup.h"
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-static const struct {
- enum protection_level level;
- const char *name;
-} level_names[] = {
- { PROT_CLEAR, "clear" },
- { PROT_SAFE, "safe" },
- { PROT_CONFIDENTIAL, "confidential" },
- { PROT_PRIVATE, "private" }
-};
-
-static enum protection_level
-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))
- return level_names[i].level;
- return PROT_NONE;
-}
-
-/* Convert a protocol |level| to its char representation.
- We take an int to catch programming mistakes. */
-static char level_to_char(int level)
-{
- switch(level) {
- case PROT_CLEAR:
- return 'C';
- case PROT_SAFE:
- return 'S';
- case PROT_CONFIDENTIAL:
- return 'E';
- case PROT_PRIVATE:
- return 'P';
- case PROT_CMD:
- /* Fall through */
- default:
- /* Those 2 cases should not be reached! */
- break;
- }
- DEBUGASSERT(0);
- /* Default to the most secure alternative. */
- return 'P';
-}
-
-/* Send an FTP command defined by |message| and the optional arguments. The
- function returns the ftp_code. If an error occurs, -1 is returned. */
-static int ftp_send_command(struct connectdata *conn, const char *message, ...)
-{
- int ftp_code;
- ssize_t nread = 0;
- va_list args;
- char print_buffer[50];
-
- va_start(args, message);
- mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
- va_end(args);
-
- if(Curl_ftpsend(conn, print_buffer)) {
- ftp_code = -1;
- }
- else {
- if(Curl_GetFTPResponse(&nread, conn, &ftp_code))
- ftp_code = -1;
- }
-
- (void)nread; /* Unused */
- return ftp_code;
-}
-
-/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
- saying whether an error occurred or CURLE_OK if |len| was read. */
-static CURLcode
-socket_read(curl_socket_t fd, void *to, size_t len)
-{
- char *to_p = to;
- CURLcode result;
- ssize_t nread = 0;
-
- while(len > 0) {
- result = Curl_read_plain(fd, to_p, len, &nread);
- if(!result) {
- len -= nread;
- to_p += nread;
- }
- else {
- if(result == CURLE_AGAIN)
- continue;
- return result;
- }
- }
- return CURLE_OK;
-}
-
-
-/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a
- CURLcode saying whether an error occurred or CURLE_OK if |len| was
- written. */
-static CURLcode
-socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
- size_t len)
-{
- const char *to_p = to;
- CURLcode result;
- ssize_t written;
-
- while(len > 0) {
- result = Curl_write_plain(conn, fd, to_p, len, &written);
- if(!result) {
- len -= written;
- to_p += written;
- }
- else {
- if(result == CURLE_AGAIN)
- continue;
- return result;
- }
- }
- return CURLE_OK;
-}
-
-static CURLcode read_data(struct connectdata *conn,
- curl_socket_t fd,
- struct krb5buffer *buf)
-{
- int len;
- CURLcode result;
-
- result = socket_read(fd, &len, sizeof(len));
- if(result)
- return result;
-
- if(len) {
- /* only realloc if there was a length */
- len = ntohl(len);
- buf->data = Curl_saferealloc(buf->data, len);
- }
- if(!len || !buf->data)
- return CURLE_OUT_OF_MEMORY;
-
- result = socket_read(fd, buf->data, len);
- if(result)
- return result;
- buf->size = conn->mech->decode(conn->app_data, buf->data, len,
- conn->data_prot, conn);
- buf->index = 0;
- return CURLE_OK;
-}
-
-static size_t
-buffer_read(struct krb5buffer *buf, void *data, size_t len)
-{
- if(buf->size - buf->index < len)
- len = buf->size - buf->index;
- memcpy(data, (char *)buf->data + buf->index, len);
- buf->index += len;
- return len;
-}
-
-/* Matches Curl_recv signature */
-static ssize_t sec_recv(struct connectdata *conn, int sockindex,
- char *buffer, size_t len, CURLcode *err)
-{
- size_t bytes_read;
- size_t total_read = 0;
- curl_socket_t fd = conn->sock[sockindex];
-
- *err = CURLE_OK;
-
- /* Handle clear text response. */
- if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
- return sread(fd, buffer, len);
-
- if(conn->in_buffer.eof_flag) {
- conn->in_buffer.eof_flag = 0;
- return 0;
- }
-
- bytes_read = buffer_read(&conn->in_buffer, buffer, len);
- len -= bytes_read;
- total_read += bytes_read;
- buffer += bytes_read;
-
- while(len > 0) {
- if(read_data(conn, fd, &conn->in_buffer))
- return -1;
- if(conn->in_buffer.size == 0) {
- if(bytes_read > 0)
- conn->in_buffer.eof_flag = 1;
- return bytes_read;
- }
- bytes_read = buffer_read(&conn->in_buffer, buffer, len);
- len -= bytes_read;
- total_read += bytes_read;
- buffer += bytes_read;
- }
- return total_read;
-}
-
-/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
- and negotiating with the server. |from| can be NULL. */
-static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
- const char *from, int length)
-{
- int bytes, htonl_bytes; /* 32-bit integers for htonl */
- char *buffer = NULL;
- char *cmd_buffer;
- size_t cmd_size = 0;
- CURLcode error;
- enum protection_level prot_level = conn->data_prot;
- bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
-
- DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
-
- if(iscmd) {
- if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5))
- prot_level = PROT_PRIVATE;
- else
- prot_level = conn->command_prot;
- }
- bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
- (void **)&buffer);
- if(!buffer || bytes <= 0)
- return; /* error */
-
- if(iscmd) {
- error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes),
- &cmd_buffer, &cmd_size);
- if(error) {
- free(buffer);
- return; /* error */
- }
- if(cmd_size > 0) {
- static const char *enc = "ENC ";
- static const char *mic = "MIC ";
- if(prot_level == PROT_PRIVATE)
- socket_write(conn, fd, enc, 4);
- else
- socket_write(conn, fd, mic, 4);
-
- socket_write(conn, fd, cmd_buffer, cmd_size);
- socket_write(conn, fd, "\r\n", 2);
- infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
- cmd_buffer);
- free(cmd_buffer);
- }
- }
- else {
- htonl_bytes = htonl(bytes);
- socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes));
- socket_write(conn, fd, buffer, curlx_sitouz(bytes));
- }
- free(buffer);
-}
-
-static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd,
- const char *buffer, size_t length)
-{
- 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) {
- if(length < (size_t)len)
- len = length;
-
- do_sec_send(conn, fd, buffer, curlx_sztosi(len));
- length -= len;
- buffer += len;
- tx += len;
- }
- return tx;
-}
-
-/* Matches Curl_send signature */
-static ssize_t sec_send(struct connectdata *conn, int sockindex,
- const void *buffer, size_t len, CURLcode *err)
-{
- curl_socket_t fd = conn->sock[sockindex];
- *err = CURLE_OK;
- return sec_write(conn, fd, buffer, len);
-}
-
-int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
- enum protection_level level)
-{
- /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an
- int */
- int decoded_len;
- char *buf;
- int ret_code = 0;
- size_t decoded_sz = 0;
- CURLcode error;
-
- if(!conn->mech)
- /* not inititalized, return error */
- return -1;
-
- DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
-
- error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
- if(error || decoded_sz == 0)
- return -1;
-
- if(decoded_sz > (size_t)INT_MAX) {
- free(buf);
- return -1;
- }
- decoded_len = curlx_uztosi(decoded_sz);
-
- decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
- level, conn);
- if(decoded_len <= 0) {
- free(buf);
- return -1;
- }
-
- if(conn->data->set.verbose) {
- buf[decoded_len] = '\n';
- Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
- }
-
- buf[decoded_len] = '\0';
- if(decoded_len <= 3)
- /* suspiciously short */
- return 0;
-
- if(buf[3] != '-')
- /* safe to ignore return code */
- (void)sscanf(buf, "%d", &ret_code);
-
- if(buf[decoded_len - 1] == '\n')
- buf[decoded_len - 1] = '\0';
- strcpy(buffer, buf);
- free(buf);
- return ret_code;
-}
-
-static int sec_set_protection_level(struct connectdata *conn)
-{
- int code;
- enum protection_level level = conn->request_data_prot;
-
- DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
-
- if(!conn->sec_complete) {
- infof(conn->data, "Trying to change the protection level after the"
- " completion of the data exchange.\n");
- return -1;
- }
-
- /* Bail out if we try to set up the same level */
- if(conn->data_prot == level)
- return 0;
-
- if(level) {
- char *pbsz;
- static unsigned int buffer_size = 1 << 20; /* 1048576 */
-
- code = ftp_send_command(conn, "PBSZ %u", buffer_size);
- if(code < 0)
- return -1;
-
- if(code/100 != 2) {
- failf(conn->data, "Failed to set the protection's buffer size.");
- return -1;
- }
- conn->buffer_size = buffer_size;
-
- pbsz = strstr(conn->data->state.buffer, "PBSZ=");
- if(pbsz) {
- /* ignore return code, use default value if it fails */
- (void)sscanf(pbsz, "PBSZ=%u", &buffer_size);
- if(buffer_size < conn->buffer_size)
- conn->buffer_size = buffer_size;
- }
- }
-
- /* Now try to negiociate the protection level. */
- code = ftp_send_command(conn, "PROT %c", level_to_char(level));
-
- if(code < 0)
- return -1;
-
- if(code/100 != 2) {
- failf(conn->data, "Failed to set the protection level.");
- return -1;
- }
-
- conn->data_prot = level;
- if(level == PROT_PRIVATE)
- conn->command_prot = level;
-
- return 0;
-}
-
-int
-Curl_sec_request_prot(struct connectdata *conn, const char *level)
-{
- enum protection_level l = name_to_level(level);
- if(l == PROT_NONE)
- return -1;
- DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
- conn->request_data_prot = l;
- return 0;
-}
-
-static CURLcode choose_mech(struct connectdata *conn)
-{
- int ret;
- struct Curl_easy *data = conn->data;
- void *tmp_allocation;
- const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;
-
- tmp_allocation = realloc(conn->app_data, mech->size);
- if(tmp_allocation == NULL) {
- failf(data, "Failed realloc of size %zu", mech->size);
- mech = NULL;
- return CURLE_OUT_OF_MEMORY;
- }
- conn->app_data = tmp_allocation;
-
- if(mech->init) {
- ret = mech->init(conn->app_data);
- if(ret) {
- infof(data, "Failed initialization for %s. Skipping it.\n",
- mech->name);
- return CURLE_FAILED_INIT;
- }
- }
-
- infof(data, "Trying mechanism %s...\n", mech->name);
- ret = ftp_send_command(conn, "AUTH %s", mech->name);
- if(ret < 0)
- return CURLE_COULDNT_CONNECT;
-
- if(ret/100 != 3) {
- switch(ret) {
- case 504:
- infof(data, "Mechanism %s is not supported by the server (server "
- "returned ftp code: 504).\n", mech->name);
- break;
- case 534:
- infof(data, "Mechanism %s was rejected by the server (server returned "
- "ftp code: 534).\n", mech->name);
- break;
- default:
- if(ret/100 == 5) {
- infof(data, "server does not support the security extensions\n");
- return CURLE_USE_SSL_FAILED;
- }
- break;
- }
- return CURLE_LOGIN_DENIED;
- }
-
- /* Authenticate */
- ret = mech->auth(conn->app_data, conn);
-
- if(ret != AUTH_CONTINUE) {
- if(ret != AUTH_OK) {
- /* Mechanism has dumped the error to stderr, don't error here. */
- return -1;
- }
- DEBUGASSERT(ret == AUTH_OK);
-
- conn->mech = mech;
- conn->sec_complete = 1;
- conn->recv[FIRSTSOCKET] = sec_recv;
- conn->send[FIRSTSOCKET] = sec_send;
- conn->recv[SECONDARYSOCKET] = sec_recv;
- conn->send[SECONDARYSOCKET] = sec_send;
- conn->command_prot = PROT_SAFE;
- /* Set the requested protection level */
- /* BLOCKING */
- (void)sec_set_protection_level(conn);
- }
-
- return CURLE_OK;
-}
-
-CURLcode
-Curl_sec_login(struct connectdata *conn)
-{
- return choose_mech(conn);
-}
-
-
-void
-Curl_sec_end(struct connectdata *conn)
-{
- if(conn->mech != NULL && conn->mech->end)
- conn->mech->end(conn->app_data);
- free(conn->app_data);
- conn->app_data = NULL;
- if(conn->in_buffer.data) {
- free(conn->in_buffer.data);
- conn->in_buffer.data = NULL;
- conn->in_buffer.size = 0;
- conn->in_buffer.index = 0;
- conn->in_buffer.eof_flag = 0;
- }
- conn->sec_complete = 0;
- conn->data_prot = PROT_CLEAR;
- conn->mech = NULL;
-}
-
-#endif /* HAVE_GSSAPI */
-
-#endif /* CURL_DISABLE_FTP */
diff --git a/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c
index 6832b428e..44fe22924 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -130,6 +130,7 @@ int Curl_wait_ms(timediff_t timeout_ms)
return r;
}
+#ifndef HAVE_POLL_FINE
/*
* This is a wrapper around select() to aid in Windows compatibility.
* A negative timeout value makes this function wait indefinitely,
@@ -141,23 +142,22 @@ int Curl_wait_ms(timediff_t timeout_ms)
* 0 = timeout
* N = number of signalled file descriptors
*/
-int Curl_select(curl_socket_t maxfd, /* highest socket number */
- fd_set *fds_read, /* sockets ready for reading */
- fd_set *fds_write, /* sockets ready for writing */
- fd_set *fds_err, /* sockets with errors */
- timediff_t timeout_ms) /* milliseconds to wait */
+static int our_select(curl_socket_t maxfd, /* highest socket number */
+ fd_set *fds_read, /* sockets ready for reading */
+ fd_set *fds_write, /* sockets ready for writing */
+ fd_set *fds_err, /* sockets with errors */
+ timediff_t timeout_ms) /* milliseconds to wait */
{
struct timeval pending_tv;
struct timeval *ptimeout;
- int r;
#ifdef USE_WINSOCK
/* WinSock select() can't handle zero events. See the comment below. */
if((!fds_read || fds_read->fd_count == 0) &&
(!fds_write || fds_write->fd_count == 0) &&
(!fds_err || fds_err->fd_count == 0)) {
- r = Curl_wait_ms(timeout_ms);
- return r;
+ /* no sockets, just wait */
+ return Curl_wait_ms(timeout_ms);
}
#endif
@@ -209,19 +209,20 @@ int Curl_select(curl_socket_t maxfd, /* highest socket number */
descriptor set must contain at least one handle to a socket.
It is unclear why WinSock doesn't just handle this for us instead of
- calling this an error.
+ calling this an error. Luckily, with WinSock, we can _also_ ask how
+ many bits are set on an fd_set. So, let's just check it beforehand.
*/
- r = select((int)maxfd + 1,
- fds_read && fds_read->fd_count ? fds_read : NULL,
- fds_write && fds_write->fd_count ? fds_write : NULL,
- fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
+ return select((int)maxfd + 1,
+ fds_read && fds_read->fd_count ? fds_read : NULL,
+ fds_write && fds_write->fd_count ? fds_write : NULL,
+ fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
#else
- r = select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
+ return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
#endif
-
- return r;
}
+#endif
+
/*
* Wait for read or write events on a set of file descriptors. It uses poll()
* when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
@@ -247,23 +248,14 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
curl_socket_t writefd, /* socket to write to */
timediff_t timeout_ms) /* milliseconds to wait */
{
-#ifdef HAVE_POLL_FINE
struct pollfd pfd[3];
int num;
-#else
- fd_set fds_read;
- fd_set fds_write;
- fd_set fds_err;
- curl_socket_t maxfd;
-#endif
int r;
- int ret;
if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
(writefd == CURL_SOCKET_BAD)) {
/* no sockets, just wait */
- r = Curl_wait_ms(timeout_ms);
- return r;
+ return Curl_wait_ms(timeout_ms);
}
/* Avoid initial timestamp, avoid Curl_now() call, when elapsed
@@ -271,8 +263,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
when function is called with a zero timeout or a negative timeout
value indicating a blocking call should be performed. */
-#ifdef HAVE_POLL_FINE
-
num = 0;
if(readfd0 != CURL_SOCKET_BAD) {
pfd[num].fd = readfd0;
@@ -288,7 +278,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
}
if(writefd != CURL_SOCKET_BAD) {
pfd[num].fd = writefd;
- pfd[num].events = POLLWRNORM|POLLOUT;
+ pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI;
pfd[num].revents = 0;
num++;
}
@@ -297,101 +287,30 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
if(r <= 0)
return r;
- ret = 0;
+ r = 0;
num = 0;
if(readfd0 != CURL_SOCKET_BAD) {
if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
- ret |= CURL_CSELECT_IN;
+ r |= CURL_CSELECT_IN;
if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
- ret |= CURL_CSELECT_ERR;
+ r |= CURL_CSELECT_ERR;
num++;
}
if(readfd1 != CURL_SOCKET_BAD) {
if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
- ret |= CURL_CSELECT_IN2;
+ r |= CURL_CSELECT_IN2;
if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
- ret |= CURL_CSELECT_ERR;
+ r |= CURL_CSELECT_ERR;
num++;
}
if(writefd != CURL_SOCKET_BAD) {
if(pfd[num].revents & (POLLWRNORM|POLLOUT))
- ret |= CURL_CSELECT_OUT;
- if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
- ret |= CURL_CSELECT_ERR;
- }
-
- return ret;
-
-#else /* HAVE_POLL_FINE */
-
- FD_ZERO(&fds_err);
- maxfd = (curl_socket_t)-1;
-
- FD_ZERO(&fds_read);
- if(readfd0 != CURL_SOCKET_BAD) {
- VERIFY_SOCK(readfd0);
- FD_SET(readfd0, &fds_read);
- FD_SET(readfd0, &fds_err);
- maxfd = readfd0;
- }
- if(readfd1 != CURL_SOCKET_BAD) {
- VERIFY_SOCK(readfd1);
- FD_SET(readfd1, &fds_read);
- FD_SET(readfd1, &fds_err);
- if(readfd1 > maxfd)
- maxfd = readfd1;
- }
-
- FD_ZERO(&fds_write);
- if(writefd != CURL_SOCKET_BAD) {
- VERIFY_SOCK(writefd);
- FD_SET(writefd, &fds_write);
- FD_SET(writefd, &fds_err);
- if(writefd > maxfd)
- maxfd = writefd;
- }
-
- /* We know that we have at least one bit set in at least two fd_sets in
- this case, but we may have no bits set in either fds_read or fd_write,
- so check for that and handle it. Luckily, with WinSock, we can _also_
- ask how many bits are set on an fd_set.
-
- Note also that WinSock ignores the first argument, so we don't worry
- about the fact that maxfd is computed incorrectly with WinSock (since
- curl_socket_t is unsigned in such cases and thus -1 is the largest
- value).
- */
- r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
-
- if(r < 0)
- return -1;
- if(r == 0)
- return 0;
-
- ret = 0;
- if(readfd0 != CURL_SOCKET_BAD) {
- if(FD_ISSET(readfd0, &fds_read))
- ret |= CURL_CSELECT_IN;
- if(FD_ISSET(readfd0, &fds_err))
- ret |= CURL_CSELECT_ERR;
+ r |= CURL_CSELECT_OUT;
+ if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL))
+ r |= CURL_CSELECT_ERR;
}
- if(readfd1 != CURL_SOCKET_BAD) {
- if(FD_ISSET(readfd1, &fds_read))
- ret |= CURL_CSELECT_IN2;
- if(FD_ISSET(readfd1, &fds_err))
- ret |= CURL_CSELECT_ERR;
- }
- if(writefd != CURL_SOCKET_BAD) {
- if(FD_ISSET(writefd, &fds_write))
- ret |= CURL_CSELECT_OUT;
- if(FD_ISSET(writefd, &fds_err))
- ret |= CURL_CSELECT_ERR;
- }
-
- return ret;
-
-#endif /* HAVE_POLL_FINE */
+ return r;
}
/*
@@ -431,8 +350,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
}
if(fds_none) {
/* no sockets, just wait */
- r = Curl_wait_ms(timeout_ms);
- return r;
+ return Curl_wait_ms(timeout_ms);
}
/* Avoid initial timestamp, avoid Curl_now() call, when elapsed
@@ -454,11 +372,8 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
else
pending_ms = 0;
r = poll(ufds, nfds, pending_ms);
-
- if(r < 0)
- return -1;
- if(r == 0)
- return 0;
+ if(r <= 0)
+ return r;
for(i = 0; i < nfds; i++) {
if(ufds[i].fd == CURL_SOCKET_BAD)
@@ -466,7 +381,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
if(ufds[i].revents & POLLHUP)
ufds[i].revents |= POLLIN;
if(ufds[i].revents & POLLERR)
- ufds[i].revents |= (POLLIN|POLLOUT);
+ ufds[i].revents |= POLLIN|POLLOUT;
}
#else /* HAVE_POLL_FINE */
@@ -482,7 +397,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
continue;
VERIFY_SOCK(ufds[i].fd);
if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
- POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
+ POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
if(ufds[i].fd > maxfd)
maxfd = ufds[i].fd;
if(ufds[i].events & (POLLRDNORM|POLLIN))
@@ -494,24 +409,39 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
}
}
- r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
-
- if(r < 0)
- return -1;
- if(r == 0)
- return 0;
+ /*
+ Note also that WinSock ignores the first argument, so we don't worry
+ about the fact that maxfd is computed incorrectly with WinSock (since
+ curl_socket_t is unsigned in such cases and thus -1 is the largest
+ value).
+ */
+ r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
+ if(r <= 0)
+ return r;
r = 0;
for(i = 0; i < nfds; i++) {
ufds[i].revents = 0;
if(ufds[i].fd == CURL_SOCKET_BAD)
continue;
- if(FD_ISSET(ufds[i].fd, &fds_read))
- ufds[i].revents |= POLLIN;
- if(FD_ISSET(ufds[i].fd, &fds_write))
- ufds[i].revents |= POLLOUT;
- if(FD_ISSET(ufds[i].fd, &fds_err))
- ufds[i].revents |= POLLPRI;
+ if(FD_ISSET(ufds[i].fd, &fds_read)) {
+ if(ufds[i].events & POLLRDNORM)
+ ufds[i].revents |= POLLRDNORM;
+ if(ufds[i].events & POLLIN)
+ ufds[i].revents |= POLLIN;
+ }
+ if(FD_ISSET(ufds[i].fd, &fds_write)) {
+ if(ufds[i].events & POLLWRNORM)
+ ufds[i].revents |= POLLWRNORM;
+ if(ufds[i].events & POLLOUT)
+ ufds[i].revents |= POLLOUT;
+ }
+ if(FD_ISSET(ufds[i].fd, &fds_err)) {
+ if(ufds[i].events & POLLRDBAND)
+ ufds[i].revents |= POLLRDBAND;
+ if(ufds[i].events & POLLPRI)
+ ufds[i].revents |= POLLPRI;
+ }
if(ufds[i].revents != 0)
r++;
}
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index 95181f467..4db64877b 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -72,12 +72,6 @@ struct pollfd
therefore defined here */
#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1)
-int Curl_select(curl_socket_t maxfd,
- fd_set *fds_read,
- fd_set *fds_write,
- fd_set *fds_err,
- timediff_t timeout_ms);
-
int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
curl_socket_t writefd,
timediff_t timeout_ms);
@@ -94,12 +88,23 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
fd_set* excepts, struct timeval *tv);
#endif
-/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which
+/* TPF sockets are not in range [0..FD_SETSIZE-1], which
unfortunately makes it impossible for us to easily check if they're valid
+
+ With Winsock the valid range is [0..INVALID_SOCKET-1] according to
+ https://docs.microsoft.com/en-us/windows/win32/winsock/socket-data-type-2
*/
-#if defined(USE_WINSOCK) || defined(TPF)
+#if defined(TPF)
#define VALID_SOCK(x) 1
#define VERIFY_SOCK(x) Curl_nop_stmt
+#elif defined(USE_WINSOCK)
+#define VALID_SOCK(s) ((s) < INVALID_SOCKET)
+#define VERIFY_SOCK(x) do { \
+ if(!VALID_SOCK(x)) { \
+ SET_SOCKERRNO(WSAEINVAL); \
+ return -1; \
+ } \
+} while(0)
#else
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
#define VERIFY_SOCK(x) do { \
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 6943fa84e..b3c7fe33d 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -28,6 +28,8 @@
#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>
+#elif defined(HAVE_NETINET_TCP_H)
+#include <netinet/tcp.h>
#endif
#include <curl/curl.h>
@@ -140,7 +142,8 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
psnd->recv_size > psnd->recv_processed;
}
-static void pre_receive_plain(struct connectdata *conn, int num)
+static CURLcode pre_receive_plain(struct Curl_easy *data,
+ struct connectdata *conn, int num)
{
const curl_socket_t sockfd = conn->sock[num];
struct postponed_data * const psnd = &(conn->postponed[num]);
@@ -159,8 +162,10 @@ static void pre_receive_plain(struct connectdata *conn, int num)
/* Have some incoming data */
if(!psnd->buffer) {
/* Use buffer double default size for intermediate buffer */
- psnd->allocated_size = 2 * conn->data->set.buffer_size;
+ psnd->allocated_size = 2 * data->set.buffer_size;
psnd->buffer = malloc(psnd->allocated_size);
+ if(!psnd->buffer)
+ return CURLE_OUT_OF_MEMORY;
psnd->recv_size = 0;
psnd->recv_processed = 0;
#ifdef DEBUGBUILD
@@ -180,6 +185,7 @@ static void pre_receive_plain(struct connectdata *conn, int num)
psnd->allocated_size = 0;
}
}
+ return CURLE_OK;
}
static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
@@ -225,7 +231,7 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
(void)sockindex;
return false;
}
-#define pre_receive_plain(c,n) do {} while(0)
+#define pre_receive_plain(d,c,n) CURLE_OK
#define get_pre_recved(c,n,b,l) 0
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
@@ -262,6 +268,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{
+ DEBUGASSERT(!strchr(fmt, '\n'));
if(data->set.verbose || data->set.errorbuffer) {
va_list ap;
size_t len;
@@ -274,61 +281,12 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
strcpy(data->set.errorbuffer, error);
data->state.errorbuf = TRUE; /* wrote error string */
}
- if(data->set.verbose) {
- error[len] = '\n';
- error[++len] = '\0';
- Curl_debug(data, CURLINFO_TEXT, error, len);
- }
+ error[len++] = '\n';
+ Curl_debug(data, CURLINFO_TEXT, error, len);
va_end(ap);
}
}
-/* Curl_sendf() sends formatted data to the server */
-CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
- const char *fmt, ...)
-{
- struct Curl_easy *data = conn->data;
- ssize_t bytes_written;
- size_t write_len;
- CURLcode result = CURLE_OK;
- char *s;
- char *sptr;
- va_list ap;
- va_start(ap, fmt);
- s = vaprintf(fmt, ap); /* returns an allocated string */
- va_end(ap);
- if(!s)
- return CURLE_OUT_OF_MEMORY; /* failure */
-
- bytes_written = 0;
- write_len = strlen(s);
- sptr = s;
-
- for(;;) {
- /* Write the buffer to the socket */
- result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
-
- if(result)
- break;
-
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
-
- if((size_t)bytes_written != write_len) {
- /* if not all was written at once, we must advance the pointer, decrease
- the size left and try again! */
- write_len -= bytes_written;
- sptr += bytes_written;
- }
- else
- break;
- }
-
- free(s); /* free the output string */
-
- return result;
-}
-
/*
* Curl_write() is an internal write function that sends data to the
* server. Works with plain sockets, SCP, SSL or kerberos.
@@ -336,7 +294,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
* If the write would block (CURLE_AGAIN), we return CURLE_OK and
* (*written == 0). Otherwise we return regular CURLcode value.
*/
-CURLcode Curl_write(struct connectdata *conn,
+CURLcode Curl_write(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem,
size_t len,
@@ -344,9 +302,14 @@ CURLcode Curl_write(struct connectdata *conn,
{
ssize_t bytes_written;
CURLcode result = CURLE_OK;
- int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+ struct connectdata *conn;
+ int num;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ conn = data->conn;
+ num = (sockfd == conn->sock[SECONDARYSOCKET]);
- bytes_written = conn->send[num](conn, num, mem, len, &result);
+ bytes_written = conn->send[num](data, num, mem, len, &result);
*written = bytes_written;
if(bytes_written >= 0)
@@ -369,17 +332,26 @@ CURLcode Curl_write(struct connectdata *conn,
}
}
-ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ssize_t Curl_send_plain(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code)
{
- curl_socket_t sockfd = conn->sock[num];
+ struct connectdata *conn;
+ curl_socket_t sockfd;
ssize_t bytes_written;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ conn = data->conn;
+ sockfd = conn->sock[num];
/* WinSock will destroy unread received data if send() is
failed.
To avoid lossage of received data, recv() must be
performed before every send() if any incoming data is
available. */
- pre_receive_plain(conn, num);
+ if(pre_receive_plain(data, conn, num)) {
+ *code = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
if(conn->bits.tcp_fastopen) {
@@ -413,9 +385,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
}
else {
char buffer[STRERROR_LEN];
- failf(conn->data, "Send failure: %s",
+ failf(data, "Send failure: %s",
Curl_strerror(err, buffer, sizeof(buffer)));
- conn->data->state.os_errno = err;
+ data->state.os_errno = err;
*code = CURLE_SEND_ERROR;
}
}
@@ -427,28 +399,33 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
* server using plain sockets only. Otherwise meant to have the exact same
* proto as Curl_write()
*/
-CURLcode Curl_write_plain(struct connectdata *conn,
+CURLcode Curl_write_plain(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem,
size_t len,
ssize_t *written)
{
- ssize_t bytes_written;
CURLcode result;
- int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+ struct connectdata *conn = data->conn;
+ int num;
+ DEBUGASSERT(conn);
+ num = (sockfd == conn->sock[SECONDARYSOCKET]);
- bytes_written = Curl_send_plain(conn, num, mem, len, &result);
-
- *written = bytes_written;
+ *written = Curl_send_plain(data, num, mem, len, &result);
return result;
}
-ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code)
{
- curl_socket_t sockfd = conn->sock[num];
+ struct connectdata *conn;
+ curl_socket_t sockfd;
ssize_t nread;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ conn = data->conn;
+ sockfd = conn->sock[num];
/* Check and return data that already received and storied in internal
intermediate buffer */
nread = get_pre_recved(conn, num, buf, len);
@@ -479,9 +456,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
}
else {
char buffer[STRERROR_LEN];
- failf(conn->data, "Recv failure: %s",
+ failf(data, "Recv failure: %s",
Curl_strerror(err, buffer, sizeof(buffer)));
- conn->data->state.os_errno = err;
+ data->state.os_errno = err;
*code = CURLE_RECV_ERROR;
}
}
@@ -540,12 +517,12 @@ static CURLcode pausewrite(struct Curl_easy *data,
* client write callback(s) and takes care of pause requests from the
* callbacks.
*/
-static CURLcode chop_write(struct connectdata *conn,
+static CURLcode chop_write(struct Curl_easy *data,
int type,
char *optr,
size_t olen)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_write_callback writeheader = NULL;
curl_write_callback writebody = NULL;
char *ptr = optr;
@@ -635,13 +612,12 @@ static CURLcode chop_write(struct connectdata *conn,
local character encoding. This is a problem and should be changed in
the future to leave the original data alone.
*/
-CURLcode Curl_client_write(struct connectdata *conn,
+CURLcode Curl_client_write(struct Curl_easy *data,
int type,
char *ptr,
size_t len)
{
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
if(0 == len)
len = strlen(ptr);
@@ -663,7 +639,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
#endif /* CURL_DO_LINEEND_CONV */
}
- return chop_write(conn, type, ptr, len);
+ return chop_write(data, type, ptr, len);
}
CURLcode Curl_read_plain(curl_socket_t sockfd,
@@ -698,7 +674,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
*
* Returns a regular CURLcode value.
*/
-CURLcode Curl_read(struct connectdata *conn, /* connection data */
+CURLcode Curl_read(struct Curl_easy *data, /* transfer */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
size_t sizerequested, /* max amount to read */
@@ -708,7 +684,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
ssize_t nread = 0;
size_t bytesfromsocket = 0;
char *buffertofill = NULL;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets
@@ -720,7 +696,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
buffertofill = buf;
- nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
+ nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
if(nread < 0)
return result;
@@ -733,72 +709,74 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
int Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size)
{
- static const char s_infotype[CURLINFO_END][3] = {
- "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
int rc = 0;
+ if(data->set.verbose) {
+ static const char s_infotype[CURLINFO_END][3] = {
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
#ifdef CURL_DOES_CONVERSIONS
- char *buf = NULL;
- size_t conv_size = 0;
-
- switch(type) {
- case CURLINFO_HEADER_OUT:
- buf = Curl_memdup(ptr, size);
- if(!buf)
- return 1;
- conv_size = size;
-
- /* Special processing is needed for this block if it
- * contains both headers and data (separated by CRLFCRLF).
- * We want to convert just the headers, leaving the data as-is.
- */
- if(size > 4) {
- size_t i;
- for(i = 0; i < size-4; i++) {
- if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
- /* convert everything through this CRLFCRLF but no further */
- conv_size = i + 4;
- break;
+ char *buf = NULL;
+ size_t conv_size = 0;
+
+ switch(type) {
+ case CURLINFO_HEADER_OUT:
+ buf = Curl_memdup(ptr, size);
+ if(!buf)
+ return 1;
+ conv_size = size;
+
+ /* Special processing is needed for this block if it
+ * contains both headers and data (separated by CRLFCRLF).
+ * We want to convert just the headers, leaving the data as-is.
+ */
+ if(size > 4) {
+ size_t i;
+ for(i = 0; i < size-4; i++) {
+ if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
+ /* convert everything through this CRLFCRLF but no further */
+ conv_size = i + 4;
+ break;
+ }
}
}
- }
- Curl_convert_from_network(data, buf, conv_size);
- /* Curl_convert_from_network calls failf if unsuccessful */
- /* we might as well continue even if it fails... */
- ptr = buf; /* switch pointer to use my buffer instead */
- break;
- default:
- /* leave everything else as-is */
- break;
- }
+ Curl_convert_from_network(data, buf, conv_size);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* we might as well continue even if it fails... */
+ ptr = buf; /* switch pointer to use my buffer instead */
+ break;
+ default:
+ /* leave everything else as-is */
+ break;
+ }
#endif /* CURL_DOES_CONVERSIONS */
- if(data->set.fdebug) {
- Curl_set_in_callback(data, true);
- rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
- Curl_set_in_callback(data, false);
- }
- else {
- switch(type) {
- case CURLINFO_TEXT:
- case CURLINFO_HEADER_OUT:
- case CURLINFO_HEADER_IN:
- fwrite(s_infotype[type], 2, 1, data->set.err);
- fwrite(ptr, size, 1, data->set.err);
+ if(data->set.fdebug) {
+ Curl_set_in_callback(data, true);
+ rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ Curl_set_in_callback(data, false);
+ }
+ else {
+ switch(type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
+ fwrite(s_infotype[type], 2, 1, data->set.err);
+ fwrite(ptr, size, 1, data->set.err);
#ifdef CURL_DOES_CONVERSIONS
- if(size != conv_size) {
- /* we had untranslated data so we need an explicit newline */
- fwrite("\n", 1, 1, data->set.err);
- }
+ if(size != conv_size) {
+ /* we had untranslated data so we need an explicit newline */
+ fwrite("\n", 1, 1, data->set.err);
+ }
#endif
- break;
- default: /* nada */
- break;
+ break;
+ default: /* nada */
+ break;
+ }
}
- }
#ifdef CURL_DOES_CONVERSIONS
- free(buf);
+ free(buf);
#endif
+ }
return rc;
}
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index c68b017da..108a5e934 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -24,8 +24,6 @@
#include "curl_setup.h"
-CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *,
- const char *fmt, ...);
void Curl_infof(struct Curl_easy *, const char *fmt, ...);
void Curl_failf(struct Curl_easy *, const char *fmt, ...);
@@ -51,7 +49,7 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...);
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
-CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
+CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);
@@ -62,23 +60,24 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
size_t bytesfromsocket,
ssize_t *n);
-ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code);
-ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ssize_t Curl_send_plain(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code);
/* internal read-function, does plain socket, SSL and krb4 */
-CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd,
+CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
char *buf, size_t buffersize,
ssize_t *n);
+
/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
-CURLcode Curl_write(struct connectdata *conn,
+CURLcode Curl_write(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem, size_t len,
ssize_t *written);
/* internal write-function, does plain sockets ONLY */
-CURLcode Curl_write_plain(struct connectdata *conn,
+CURLcode Curl_write_plain(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem, size_t len,
ssize_t *written);
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index d6213357c..ce73a34a7 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -30,6 +30,8 @@
#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>
+#elif defined(HAVE_NETINET_TCP_H)
+#include <netinet/tcp.h>
#endif
#include "urldata.h"
@@ -45,6 +47,7 @@
#include "setopt.h"
#include "multiif.h"
#include "altsvc.h"
+#include "hsts.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -271,11 +274,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Do not include the body part in the output data stream.
*/
data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
+#ifndef CURL_DISABLE_HTTP
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
data->set.method = HTTPREQ_HEAD;
else if(data->set.method == HTTPREQ_HEAD)
data->set.method = HTTPREQ_GET;
+#endif
break;
case CURLOPT_FAILONERROR:
/*
@@ -430,104 +435,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
primary->version_max = version_max;
}
#else
- result = CURLE_UNKNOWN_OPTION;
+ result = CURLE_NOT_BUILT_IN;
#endif
break;
-#ifndef CURL_DISABLE_HTTP
- case CURLOPT_AUTOREFERER:
- /*
- * Switch on automatic referer that gets set if curl follows locations.
- */
- data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_ACCEPT_ENCODING:
- /*
- * String to use at the value of Accept-Encoding header.
- *
- * If the encoding is set to "" we use an Accept-Encoding header that
- * encompasses all the encodings we support.
- * If the encoding is set to NULL we don't send an Accept-Encoding header
- * and ignore an received Content-Encoding header.
- *
- */
- argptr = va_arg(param, char *);
- if(argptr && !*argptr) {
- argptr = Curl_all_content_encodings();
- if(!argptr)
- result = CURLE_OUT_OF_MEMORY;
- else {
- result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
- free(argptr);
- }
- }
- else
- result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
- break;
-
- case CURLOPT_TRANSFER_ENCODING:
- data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
- break;
-
- case CURLOPT_FOLLOWLOCATION:
- /*
- * Follow Location: header hints on a HTTP-server.
- */
- data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_UNRESTRICTED_AUTH:
- /*
- * Send authentication (user+password) when following locations, even when
- * hostname changed.
- */
- data->set.allow_auth_to_other_hosts =
- (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_MAXREDIRS:
- /*
- * The maximum amount of hops you allow curl to follow Location:
- * headers. This should mostly be used to detect never-ending loops.
- */
- arg = va_arg(param, long);
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.maxredirs = arg;
- break;
-
- case CURLOPT_POSTREDIR:
- /*
- * Set the behaviour of POST when redirecting
- * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
- * CURL_REDIR_POST_301 - POST is kept as POST after 301
- * CURL_REDIR_POST_302 - POST is kept as POST after 302
- * CURL_REDIR_POST_303 - POST is kept as POST after 303
- * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
- * other - POST is kept as POST after 301 and 302
- */
- arg = va_arg(param, long);
- if(arg < CURL_REDIR_GET_ALL)
- /* no return error on too high numbers since the bitmask could be
- extended in a future */
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.keep_post = arg & CURL_REDIR_POST_ALL;
- break;
-
- case CURLOPT_POST:
- /* Does this option serve a purpose anymore? Yes it does, when
- CURLOPT_POSTFIELDS isn't used and the POST data is read off the
- callback! */
- if(va_arg(param, long)) {
- data->set.method = HTTPREQ_POST;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- else
- data->set.method = HTTPREQ_GET;
- break;
-
+ /* MQTT "borrows" some of the HTTP options */
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
case CURLOPT_COPYPOSTFIELDS:
/*
* A string with POST data. Makes curl HTTP POST. Even if it is NULL.
@@ -622,6 +535,100 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.postfieldsize = bigsize;
break;
+#endif
+#ifndef CURL_DISABLE_HTTP
+ case CURLOPT_AUTOREFERER:
+ /*
+ * Switch on automatic referer that gets set if curl follows locations.
+ */
+ data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_ACCEPT_ENCODING:
+ /*
+ * String to use at the value of Accept-Encoding header.
+ *
+ * If the encoding is set to "" we use an Accept-Encoding header that
+ * encompasses all the encodings we support.
+ * If the encoding is set to NULL we don't send an Accept-Encoding header
+ * and ignore an received Content-Encoding header.
+ *
+ */
+ argptr = va_arg(param, char *);
+ if(argptr && !*argptr) {
+ argptr = Curl_all_content_encodings();
+ if(!argptr)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+ free(argptr);
+ }
+ }
+ else
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+ break;
+
+ case CURLOPT_TRANSFER_ENCODING:
+ data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+
+ case CURLOPT_FOLLOWLOCATION:
+ /*
+ * Follow Location: header hints on a HTTP-server.
+ */
+ data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_UNRESTRICTED_AUTH:
+ /*
+ * Send authentication (user+password) when following locations, even when
+ * hostname changed.
+ */
+ data->set.allow_auth_to_other_hosts =
+ (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_MAXREDIRS:
+ /*
+ * The maximum amount of hops you allow curl to follow Location:
+ * headers. This should mostly be used to detect never-ending loops.
+ */
+ arg = va_arg(param, long);
+ if(arg < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.maxredirs = arg;
+ break;
+
+ case CURLOPT_POSTREDIR:
+ /*
+ * Set the behavior of POST when redirecting
+ * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
+ * CURL_REDIR_POST_301 - POST is kept as POST after 301
+ * CURL_REDIR_POST_302 - POST is kept as POST after 302
+ * CURL_REDIR_POST_303 - POST is kept as POST after 303
+ * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
+ * other - POST is kept as POST after 301 and 302
+ */
+ arg = va_arg(param, long);
+ if(arg < CURL_REDIR_GET_ALL)
+ /* no return error on too high numbers since the bitmask could be
+ extended in a future */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.keep_post = arg & CURL_REDIR_POST_ALL;
+ break;
+
+ case CURLOPT_POST:
+ /* Does this option serve a purpose anymore? Yes it does, when
+ CURLOPT_POSTFIELDS isn't used and the POST data is read off the
+ callback! */
+ if(va_arg(param, long)) {
+ data->set.method = HTTPREQ_POST;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ data->set.method = HTTPREQ_GET;
+ break;
case CURLOPT_HTTPPOST:
/*
@@ -631,6 +638,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
+
+ case CURLOPT_AWS_SIGV4:
+ /*
+ * String that is merged to some authentication
+ * parameters are used by the algorithm.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4],
+ va_arg(param, char *));
+ /*
+ * Basic been set by default it need to be unset here
+ */
+ if(data->set.str[STRING_AWS_SIGV4])
+ data->set.httpauth = CURLAUTH_AWS_SIGV4;
+ break;
+
#endif /* CURL_DISABLE_HTTP */
case CURLOPT_MIMEPOST:
@@ -720,6 +742,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
argptr = (char *)va_arg(param, void *);
if(argptr) {
struct curl_slist *cl;
+ /* general protection against mistakes and abuse */
+ if(strlen(argptr) > CURL_MAX_INPUT_LENGTH)
+ 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);
@@ -804,6 +829,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* if cookie engine was not running, activate it */
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
+ /* general protection against mistakes and abuse */
+ if(strlen(argptr) > CURL_MAX_INPUT_LENGTH)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
argptr = strdup(argptr);
if(!argptr || !data->cookies) {
result = CURLE_OUT_OF_MEMORY;
@@ -854,7 +882,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
;
else
#endif
-#ifndef USE_NGHTTP2
+#if !defined(USE_NGHTTP2) && !defined(USE_HYPER)
if(arg >= CURL_HTTP_VERSION_2)
return CURLE_UNSUPPORTED_PROTOCOL;
#else
@@ -1069,7 +1097,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
default:
/* reserve other values for future use */
- result = CURLE_UNKNOWN_OPTION;
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
break;
@@ -1222,21 +1250,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* An FTP/SFTP option that modifies an upload to create missing
* directories on the server.
*/
- switch(va_arg(param, long)) {
- case 0:
- data->set.ftp_create_missing_dirs = 0;
- break;
- case 1:
- data->set.ftp_create_missing_dirs = 1;
- break;
- case 2:
- data->set.ftp_create_missing_dirs = 2;
- break;
- default:
- /* reserve other values for future use */
- result = CURLE_UNKNOWN_OPTION;
- break;
- }
+ arg = va_arg(param, long);
+ /* reserve other values for future use */
+ if((arg < CURLFTP_CREATE_DIR_NONE) ||
+ (arg > CURLFTP_CREATE_DIR_RETRY))
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ else
+ data->set.ftp_create_missing_dirs = (int)arg;
break;
case CURLOPT_READDATA:
/*
@@ -1441,13 +1461,16 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_RESOLVE:
/*
- * List of NAME:[address] names to populate the DNS cache with
- * Prefix the NAME with dash (-) to _remove_ the name from the cache.
- *
- * Names added with this API will remain in the cache until explicitly
+ * List of HOST:PORT:[addresses] strings to populate the DNS cache with
+ * Entries added this way will remain in the cache until explicitly
* removed or the handle is cleaned up.
*
- * This API can remove any name from the DNS cache, but only entries
+ * Prefix the HOST with plus sign (+) to have the entry expire just like
+ * automatically added entries.
+ *
+ * Prefix the HOST with dash (-) to _remove_ the entry from the cache.
+ *
+ * This API can remove any entry from the DNS cache, but only entries
* that aren't actually in use right now will be pruned immediately.
*/
data->set.resolve = va_arg(param, struct curl_slist *);
@@ -2075,6 +2098,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* The application kindly asks for a differently sized receive buffer.
* If it seems reasonable, we'll use it.
*/
+ if(data->state.buffer)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
arg = va_arg(param, long);
if(arg > READBUFFER_MAX)
@@ -2084,18 +2110,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else if(arg < READBUFFER_MIN)
arg = READBUFFER_MIN;
- /* Resize if new size */
- if((arg != data->set.buffer_size) && data->state.buffer) {
- char *newbuff = realloc(data->state.buffer, arg + 1);
- if(!newbuff) {
- DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
- result = CURLE_OUT_OF_MEMORY;
- }
- else
- data->state.buffer = newbuff;
- }
data->set.buffer_size = arg;
-
break;
case CURLOPT_UPLOAD_BUFFERSIZE:
@@ -2155,8 +2170,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->share = NULL;
}
- /* use new share if it set */
- data->share = set;
+ if(GOOD_SHARE_HANDLE(set))
+ /* use new share if it set */
+ data->share = set;
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
@@ -2243,12 +2259,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
+ case CURLOPT_SSL_EC_CURVES:
+ /*
+ * Set accepted curves in SSL connection setup.
+ * Specify colon-delimited list of curve algorithm names.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES],
+ va_arg(param, char *));
+ break;
#endif
case CURLOPT_IPRESOLVE:
arg = va_arg(param, long);
if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ipver = arg;
+ data->set.ipver = (unsigned char) arg;
break;
case CURLOPT_MAXFILESIZE_LARGE:
@@ -2513,9 +2537,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
* Would this be better if the RTSPREQ_* were just moved into here?
*/
- long curl_rtspreq = va_arg(param, long);
+ long in_rtspreq = va_arg(param, long);
Curl_RtspReq rtspreq = RTSPREQ_NONE;
- switch(curl_rtspreq) {
+ switch(in_rtspreq) {
case CURL_RTSPREQ_OPTIONS:
rtspreq = RTSPREQ_OPTIONS;
break;
@@ -2839,7 +2863,46 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.trailer_data = va_arg(param, void *);
#endif
break;
-#ifdef USE_ALTSVC
+#ifdef USE_HSTS
+ case CURLOPT_HSTSREADFUNCTION:
+ data->set.hsts_read = va_arg(param, curl_hstsread_callback);
+ break;
+ case CURLOPT_HSTSREADDATA:
+ data->set.hsts_read_userp = va_arg(param, void *);
+ break;
+ case CURLOPT_HSTSWRITEFUNCTION:
+ data->set.hsts_write = va_arg(param, curl_hstswrite_callback);
+ break;
+ case CURLOPT_HSTSWRITEDATA:
+ data->set.hsts_write_userp = va_arg(param, void *);
+ break;
+ case CURLOPT_HSTS:
+ if(!data->hsts) {
+ data->hsts = Curl_hsts_init();
+ if(!data->hsts)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ argptr = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr);
+ if(result)
+ return result;
+ if(argptr)
+ (void)Curl_hsts_loadfile(data, data->hsts, argptr);
+ break;
+ case CURLOPT_HSTS_CTRL:
+ arg = va_arg(param, long);
+ if(arg & CURLHSTS_ENABLE) {
+ if(!data->hsts) {
+ data->hsts = Curl_hsts_init();
+ if(!data->hsts)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else
+ Curl_hsts_cleanup(&data->hsts);
+ break;
+#endif
+#ifndef CURL_DISABLE_ALTSVC
case CURLOPT_ALTSVC:
if(!data->asi) {
data->asi = Curl_altsvc_init();
diff --git a/Utilities/cmcurl/lib/setopt.h b/Utilities/cmcurl/lib/setopt.h
index 5fc4368dc..affbfd996 100644
--- a/Utilities/cmcurl/lib/setopt.h
+++ b/Utilities/cmcurl/lib/setopt.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/setup-os400.h b/Utilities/cmcurl/lib/setup-os400.h
index b693cb3b3..8c97371e4 100644
--- a/Utilities/cmcurl/lib/setup-os400.h
+++ b/Utilities/cmcurl/lib/setup-os400.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/setup-vms.h b/Utilities/cmcurl/lib/setup-vms.h
index 0e39c9f6b..ba75dc295 100644
--- a/Utilities/cmcurl/lib/setup-vms.h
+++ b/Utilities/cmcurl/lib/setup-vms.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/setup-win32.h b/Utilities/cmcurl/lib/setup-win32.h
index 45b584766..c35dec88c 100644
--- a/Utilities/cmcurl/lib/setup-win32.h
+++ b/Utilities/cmcurl/lib/setup-win32.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -60,7 +60,6 @@
/*
* Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
- * define USE_WINSOCK to 1 if we have and use WINSOCK API, else
* undefine USE_WINSOCK.
*/
@@ -70,7 +69,7 @@
# define USE_WINSOCK 2
#else
# ifdef HAVE_WINSOCK_H
-# define USE_WINSOCK 1
+# error "WinSock version 1 is no longer supported, version 2 is required!"
# endif
#endif
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index ee5d273c4..d91511791 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -10,7 +10,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -27,6 +27,7 @@
#include "warnless.h"
#include "curl_sha256.h"
+#include "curl_hmac.h"
#if defined(USE_OPENSSL)
@@ -343,11 +344,14 @@ static int sha256_compress(struct sha256_state *md,
}
/* Compress */
-#define RND(a,b,c,d,e,f,g,h,i) \
- unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
- unsigned long t1 = Sigma0(a) + Maj(a, b, c); \
- d += t0; \
- h = t0 + t1;
+#define RND(a,b,c,d,e,f,g,h,i) \
+ do { \
+ unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ unsigned long t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1; \
+ } while(0)
+
for(i = 0; i < 64; ++i) {
unsigned long t;
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
@@ -491,4 +495,23 @@ void Curl_sha256it(unsigned char *output, const unsigned char *input,
SHA256_Final(output, &ctx);
}
+
+const struct HMAC_params Curl_HMAC_SHA256[] = {
+ {
+ /* Hash initialization function. */
+ CURLX_FUNCTION_CAST(HMAC_hinit_func, SHA256_Init),
+ /* Hash update function. */
+ CURLX_FUNCTION_CAST(HMAC_hupdate_func, SHA256_Update),
+ /* Hash computation end function. */
+ CURLX_FUNCTION_CAST(HMAC_hfinal_func, SHA256_Final),
+ /* Size of hash context structure. */
+ sizeof(SHA256_CTX),
+ /* Maximum key length. */
+ 64,
+ /* Result size. */
+ 32
+ }
+};
+
+
#endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/Utilities/cmcurl/lib/share.c b/Utilities/cmcurl/lib/share.c
index a2d896042..4f1804dbd 100644
--- a/Utilities/cmcurl/lib/share.c
+++ b/Utilities/cmcurl/lib/share.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -37,6 +37,7 @@ curl_share_init(void)
{
struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
if(share) {
+ share->magic = CURL_GOOD_SHARE;
share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
if(Curl_mk_dnscache(&share->hostcache)) {
@@ -59,6 +60,9 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
void *ptr;
CURLSHcode res = CURLSHE_OK;
+ if(!GOOD_SHARE_HANDLE(share))
+ return CURLSHE_INVALID;
+
if(share->dirty)
/* don't allow setting options while one or more handles are already
using this share */
@@ -92,7 +96,7 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
if(!share->sslsession) {
share->max_ssl_sessions = 8;
share->sslsession = calloc(share->max_ssl_sessions,
- sizeof(struct curl_ssl_session));
+ sizeof(struct Curl_ssl_session));
share->sessionage = 0;
if(!share->sslsession)
res = CURLSHE_NOMEM;
@@ -184,7 +188,7 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
CURLSHcode
curl_share_cleanup(struct Curl_share *share)
{
- if(share == NULL)
+ if(!GOOD_SHARE_HANDLE(share))
return CURLSHE_INVALID;
if(share->lockfunc)
@@ -218,6 +222,7 @@ curl_share_cleanup(struct Curl_share *share)
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
+ share->magic = 0;
free(share);
return CURLSHE_OK;
diff --git a/Utilities/cmcurl/lib/share.h b/Utilities/cmcurl/lib/share.h
index a7dea41ad..222e34ba6 100644
--- a/Utilities/cmcurl/lib/share.h
+++ b/Utilities/cmcurl/lib/share.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -37,8 +37,12 @@
#define CURL_VOLATILE volatile
#endif
+#define CURL_GOOD_SHARE 0x7e117a1e
+#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
+
/* this struct is libcurl-private, don't export details */
struct Curl_share {
+ unsigned int magic; /* CURL_GOOD_SHARE */
unsigned int specifier;
CURL_VOLATILE unsigned int dirty;
@@ -46,7 +50,7 @@ struct Curl_share {
curl_unlock_function unlockfunc;
void *clientdata;
struct conncache conn_cache;
- struct curl_hash hostcache;
+ struct Curl_hash hostcache;
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies;
#endif
@@ -54,7 +58,7 @@ struct Curl_share {
struct PslCache psl;
#endif
- struct curl_ssl_session *sslsession;
+ struct Curl_ssl_session *sslsession;
size_t max_ssl_sessions;
long sessionage;
};
diff --git a/Utilities/cmcurl/lib/sigpipe.h b/Utilities/cmcurl/lib/sigpipe.h
index 3960a139d..430cfc648 100644
--- a/Utilities/cmcurl/lib/sigpipe.h
+++ b/Utilities/cmcurl/lib/sigpipe.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/slist.c b/Utilities/cmcurl/lib/slist.c
index d27fbe19b..907c203f3 100644
--- a/Utilities/cmcurl/lib/slist.c
+++ b/Utilities/cmcurl/lib/slist.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/slist.h b/Utilities/cmcurl/lib/slist.h
index 799b3c060..3114259cf 100644
--- a/Utilities/cmcurl/lib/slist.h
+++ b/Utilities/cmcurl/lib/slist.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index d493adcc0..dd4e4fdbf 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2016 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2016-2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -23,11 +23,9 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
(CURL_SIZEOF_CURL_OFF_T > 4)
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
#define BUILDING_CURL_SMB_C
#ifdef HAVE_PROCESS_H
@@ -56,16 +54,20 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode smb_setup_connection(struct connectdata *conn);
-static CURLcode smb_connect(struct connectdata *conn, bool *done);
-static CURLcode smb_connection_state(struct connectdata *conn, bool *done);
-static CURLcode smb_do(struct connectdata *conn, bool *done);
-static CURLcode smb_request_state(struct connectdata *conn, bool *done);
-static CURLcode smb_done(struct connectdata *conn, CURLcode status,
+static CURLcode smb_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode smb_connect(struct Curl_easy *data, bool *done);
+static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
+static CURLcode smb_do(struct Curl_easy *data, bool *done);
+static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
+static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode smb_disconnect(struct connectdata *conn, bool dead);
-static int smb_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode smb_parse_url_path(struct connectdata *conn);
+static CURLcode smb_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
+static CURLcode smb_parse_url_path(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* SMB handler interface
@@ -88,6 +90,7 @@ const struct Curl_handler Curl_handler_smb = {
ZERO_NULL, /* connection_check */
PORT_SMB, /* defport */
CURLPROTO_SMB, /* protocol */
+ CURLPROTO_SMB, /* family */
PROTOPT_NONE /* flags */
};
@@ -113,6 +116,7 @@ const struct Curl_handler Curl_handler_smbs = {
ZERO_NULL, /* connection_check */
PORT_SMBS, /* defport */
CURLPROTO_SMBS, /* protocol */
+ CURLPROTO_SMB, /* family */
PROTOPT_SSL /* flags */
};
#endif
@@ -124,13 +128,17 @@ const struct Curl_handler Curl_handler_smbs = {
/* Append a string to an SMB message */
#define MSGCAT(str) \
- strcpy(p, (str)); \
- p += strlen(str);
+ do { \
+ strcpy(p, (str)); \
+ p += strlen(str); \
+ } while(0)
/* Append a null-terminated string to an SMB message */
#define MSGCATNULL(str) \
- strcpy(p, (str)); \
- p += strlen(str) + 1;
+ do { \
+ strcpy(p, (str)); \
+ p += strlen(str) + 1; \
+ } while(0)
/* SMB is mostly little endian */
#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
@@ -179,9 +187,9 @@ struct smb_request {
CURLcode result;
};
-static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
+static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
{
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = &data->conn->proto.smbc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
@@ -194,17 +202,17 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
};
if(smbc->state != newstate)
- infof(conn->data, "SMB conn %p state change from %s to %s\n",
+ infof(data, "SMB conn %p state change from %s to %s\n",
(void *)smbc, names[smbc->state], names[newstate]);
#endif
smbc->state = newstate;
}
-static void request_state(struct connectdata *conn,
+static void request_state(struct Curl_easy *data,
enum smb_req_state newstate)
{
- struct smb_request *req = conn->data->req.protop;
+ struct smb_request *req = data->req.p.smb;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
@@ -220,7 +228,7 @@ static void request_state(struct connectdata *conn,
};
if(req->state != newstate)
- infof(conn->data, "SMB request %p state change from %s to %s\n",
+ infof(data, "SMB request %p state change from %s to %s\n",
(void *)req, names[req->state], names[newstate]);
#endif
@@ -229,21 +237,23 @@ static void request_state(struct connectdata *conn,
/* this should setup things in the connection, not in the easy
handle */
-static CURLcode smb_setup_connection(struct connectdata *conn)
+static CURLcode smb_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct smb_request *req;
/* Initialize the request state */
- conn->data->req.protop = req = calloc(1, sizeof(struct smb_request));
+ data->req.p.smb = req = calloc(1, sizeof(struct smb_request));
if(!req)
return CURLE_OUT_OF_MEMORY;
/* Parse the URL path */
- return smb_parse_url_path(conn);
+ return smb_parse_url_path(data, conn);
}
-static CURLcode smb_connect(struct connectdata *conn, bool *done)
+static CURLcode smb_connect(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
char *slash;
@@ -284,8 +294,9 @@ static CURLcode smb_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
+static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
char *buf = smbc->recv_buf;
ssize_t bytes_read;
@@ -294,7 +305,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
size_t len = MAX_MESSAGE_SIZE - smbc->got;
CURLcode result;
- result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read);
+ result = Curl_read(data, FIRSTSOCKET, buf + smbc->got, len, &bytes_read);
if(result)
return result;
@@ -338,11 +349,12 @@ static void smb_pop_message(struct connectdata *conn)
smbc->got = 0;
}
-static void smb_format_message(struct connectdata *conn, struct smb_header *h,
+static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
unsigned char cmd, size_t len)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
- struct smb_request *req = conn->data->req.protop;
+ struct smb_request *req = data->req.p.smb;
unsigned int pid;
memset(h, 0, sizeof(*h));
@@ -359,14 +371,15 @@ static void smb_format_message(struct connectdata *conn, struct smb_header *h,
h->pid = smb_swap16((unsigned short) pid);
}
-static CURLcode smb_send(struct connectdata *conn, ssize_t len,
+static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
size_t upload_size)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written;
CURLcode result;
- result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf,
+ result = Curl_write(data, FIRSTSOCKET, data->state.ulbuf,
len, &bytes_written);
if(result)
return result;
@@ -381,8 +394,9 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len,
return CURLE_OK;
}
-static CURLcode smb_flush(struct connectdata *conn)
+static CURLcode smb_flush(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written;
ssize_t len = smbc->send_size - smbc->sent;
@@ -391,8 +405,8 @@ static CURLcode smb_flush(struct connectdata *conn)
if(!smbc->send_size)
return CURLE_OK;
- result = Curl_write(conn, FIRSTSOCKET,
- conn->data->state.ulbuf + smbc->sent,
+ result = Curl_write(data, FIRSTSOCKET,
+ data->state.ulbuf + smbc->sent,
len, &bytes_written);
if(result)
return result;
@@ -405,29 +419,30 @@ static CURLcode smb_flush(struct connectdata *conn)
return CURLE_OK;
}
-static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd,
+static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd,
const void *msg, size_t msg_len)
{
- CURLcode result = Curl_get_upload_buffer(conn->data);
+ CURLcode result = Curl_get_upload_buffer(data);
if(result)
return result;
- smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf,
+ smb_format_message(data, (struct smb_header *)data->state.ulbuf,
cmd, msg_len);
- memcpy(conn->data->state.ulbuf + sizeof(struct smb_header),
+ memcpy(data->state.ulbuf + sizeof(struct smb_header),
msg, msg_len);
- return smb_send(conn, sizeof(struct smb_header) + msg_len, 0);
+ return smb_send(data, sizeof(struct smb_header) + msg_len, 0);
}
-static CURLcode smb_send_negotiate(struct connectdata *conn)
+static CURLcode smb_send_negotiate(struct Curl_easy *data)
{
const char *msg = "\x00\x0c\x00\x02NT LM 0.12";
- return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15);
+ return smb_send_message(data, SMB_COM_NEGOTIATE, msg, 15);
}
-static CURLcode smb_send_setup(struct connectdata *conn)
+static CURLcode smb_send_setup(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
struct smb_setup msg;
char *p = msg.bytes;
@@ -442,10 +457,10 @@ static CURLcode smb_send_setup(struct connectdata *conn)
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;
- Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash);
+ Curl_ntlm_core_mk_lm_hash(data, conn->passwd, lm_hash);
Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm);
#ifdef USE_NTRESPONSES
- Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash);
+ Curl_ntlm_core_mk_nt_hash(data, conn->passwd, nt_hash);
Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt);
#else
memset(nt, 0, sizeof(nt));
@@ -472,13 +487,14 @@ static CURLcode smb_send_setup(struct connectdata *conn)
byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg,
+ return smb_send_message(data, SMB_COM_SETUP_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_tree_connect(struct connectdata *conn)
+static CURLcode smb_send_tree_connect(struct Curl_easy *data)
{
struct smb_tree_connect msg;
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
char *p = msg.bytes;
@@ -499,13 +515,13 @@ static CURLcode smb_send_tree_connect(struct connectdata *conn)
byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg,
+ return smb_send_message(data, SMB_COM_TREE_CONNECT_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_open(struct connectdata *conn)
+static CURLcode smb_send_open(struct Curl_easy *data)
{
- struct smb_request *req = conn->data->req.protop;
+ struct smb_request *req = data->req.p.smb;
struct smb_nt_create msg;
size_t byte_count;
@@ -518,7 +534,7 @@ static CURLcode smb_send_open(struct connectdata *conn)
byte_count = strlen(req->path);
msg.name_length = smb_swap16((unsigned short)byte_count);
msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
- if(conn->data->set.upload) {
+ if(data->set.upload) {
msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
}
@@ -529,35 +545,35 @@ static CURLcode smb_send_open(struct connectdata *conn)
msg.byte_count = smb_swap16((unsigned short) ++byte_count);
strcpy(msg.bytes, req->path);
- return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg,
+ return smb_send_message(data, SMB_COM_NT_CREATE_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_close(struct connectdata *conn)
+static CURLcode smb_send_close(struct Curl_easy *data)
{
- struct smb_request *req = conn->data->req.protop;
+ struct smb_request *req = data->req.p.smb;
struct smb_close msg;
memset(&msg, 0, sizeof(msg));
msg.word_count = SMB_WC_CLOSE;
msg.fid = smb_swap16(req->fid);
- return smb_send_message(conn, SMB_COM_CLOSE, &msg, sizeof(msg));
+ return smb_send_message(data, SMB_COM_CLOSE, &msg, sizeof(msg));
}
-static CURLcode smb_send_tree_disconnect(struct connectdata *conn)
+static CURLcode smb_send_tree_disconnect(struct Curl_easy *data)
{
struct smb_tree_disconnect msg;
memset(&msg, 0, sizeof(msg));
- return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
+ return smb_send_message(data, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
}
-static CURLcode smb_send_read(struct connectdata *conn)
+static CURLcode smb_send_read(struct Curl_easy *data)
{
- struct smb_request *req = conn->data->req.protop;
- curl_off_t offset = conn->data->req.offset;
+ struct smb_request *req = data->req.p.smb;
+ curl_off_t offset = data->req.offset;
struct smb_read msg;
memset(&msg, 0, sizeof(msg));
@@ -569,19 +585,19 @@ static CURLcode smb_send_read(struct connectdata *conn)
msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
- return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg));
+ return smb_send_message(data, SMB_COM_READ_ANDX, &msg, sizeof(msg));
}
-static CURLcode smb_send_write(struct connectdata *conn)
+static CURLcode smb_send_write(struct Curl_easy *data)
{
struct smb_write *msg;
- struct smb_request *req = conn->data->req.protop;
- curl_off_t offset = conn->data->req.offset;
- curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
- CURLcode result = Curl_get_upload_buffer(conn->data);
+ struct smb_request *req = data->req.p.smb;
+ curl_off_t offset = data->req.offset;
+ curl_off_t upload_size = data->req.size - data->req.bytecount;
+ CURLcode result = Curl_get_upload_buffer(data);
if(result)
return result;
- msg = (struct smb_write *)conn->data->state.ulbuf;
+ msg = (struct smb_write *)data->state.ulbuf;
if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
upload_size = MAX_PAYLOAD_SIZE - 1;
@@ -596,25 +612,26 @@ static CURLcode smb_send_write(struct connectdata *conn)
msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int));
msg->byte_count = smb_swap16((unsigned short) (upload_size + 1));
- smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX,
+ smb_format_message(data, &msg->h, SMB_COM_WRITE_ANDX,
sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size);
- return smb_send(conn, sizeof(*msg), (size_t) upload_size);
+ return smb_send(data, sizeof(*msg), (size_t) upload_size);
}
-static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
+static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
CURLcode result;
*msg = NULL; /* if it returns early */
/* Check if there is data in the transfer buffer */
if(!smbc->send_size && smbc->upload_size) {
- size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ?
- conn->data->set.upload_buffer_size :
+ size_t nread = smbc->upload_size > data->set.upload_buffer_size ?
+ data->set.upload_buffer_size :
smbc->upload_size;
- conn->data->req.upload_fromhere = conn->data->state.ulbuf;
- result = Curl_fillreadbuffer(conn, nread, &nread);
+ data->req.upload_fromhere = data->state.ulbuf;
+ result = Curl_fillreadbuffer(data, nread, &nread);
if(result && result != CURLE_AGAIN)
return result;
if(!nread)
@@ -627,7 +644,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
/* Check if there is data to send */
if(smbc->send_size) {
- result = smb_flush(conn);
+ result = smb_flush(data);
if(result)
return result;
}
@@ -636,11 +653,12 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
if(smbc->send_size || smbc->upload_size)
return CURLE_AGAIN;
- return smb_recv_message(conn, msg);
+ return smb_recv_message(data, msg);
}
-static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
+static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
struct smb_negotiate_response *nrsp;
struct smb_header *h;
@@ -651,7 +669,8 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
#ifdef USE_SSL
if((conn->handler->flags & PROTOPT_SSL)) {
bool ssl_done = FALSE;
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &ssl_done);
if(result && result != CURLE_AGAIN)
return result;
if(!ssl_done)
@@ -659,17 +678,17 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
}
#endif
- result = smb_send_negotiate(conn);
+ result = smb_send_negotiate(data);
if(result) {
connclose(conn, "SMB: failed to send negotiate message");
return result;
}
- conn_state(conn, SMB_NEGOTIATE);
+ conn_state(data, SMB_NEGOTIATE);
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(conn, &msg);
+ result = smb_send_and_recv(data, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -690,12 +709,12 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
nrsp = msg;
memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge));
smbc->session_key = smb_swap32(nrsp->session_key);
- result = smb_send_setup(conn);
+ result = smb_send_setup(data);
if(result) {
connclose(conn, "SMB: failed to send setup message");
return result;
}
- conn_state(conn, SMB_SETUP);
+ conn_state(data, SMB_SETUP);
break;
case SMB_SETUP:
@@ -704,7 +723,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
return CURLE_LOGIN_DENIED;
}
smbc->uid = smb_swap16(h->uid);
- conn_state(conn, SMB_CONNECTED);
+ conn_state(data, SMB_CONNECTED);
*done = true;
break;
@@ -736,9 +755,10 @@ static void get_posix_time(time_t *out, curl_off_t timestamp)
*out = (time_t) timestamp;
}
-static CURLcode smb_request_state(struct connectdata *conn, bool *done)
+static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
{
- struct smb_request *req = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct smb_request *req = data->req.p.smb;
struct smb_header *h;
struct smb_conn *smbc = &conn->proto.smbc;
enum smb_req_state next_state = SMB_DONE;
@@ -750,17 +770,17 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
/* Start the request */
if(req->state == SMB_REQUESTING) {
- result = smb_send_tree_connect(conn);
+ result = smb_send_tree_connect(data);
if(result) {
connclose(conn, "SMB: failed to send tree connect message");
return result;
}
- request_state(conn, SMB_TREE_CONNECT);
+ request_state(data, SMB_TREE_CONNECT);
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(conn, &msg);
+ result = smb_send_and_recv(data, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -793,23 +813,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
}
smb_m = (const struct smb_nt_create_response*) msg;
req->fid = smb_swap16(smb_m->fid);
- conn->data->req.offset = 0;
- if(conn->data->set.upload) {
- conn->data->req.size = conn->data->state.infilesize;
- Curl_pgrsSetUploadSize(conn->data, conn->data->req.size);
+ data->req.offset = 0;
+ if(data->set.upload) {
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->req.size);
next_state = SMB_UPLOAD;
}
else {
smb_m = (const struct smb_nt_create_response*) msg;
- conn->data->req.size = smb_swap64(smb_m->end_of_file);
- if(conn->data->req.size < 0) {
+ data->req.size = smb_swap64(smb_m->end_of_file);
+ if(data->req.size < 0) {
req->result = CURLE_WEIRD_SERVER_REPLY;
next_state = SMB_CLOSE;
}
else {
- Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
- if(conn->data->set.get_filetime)
- get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
+ Curl_pgrsSetDownloadSize(data, data->req.size);
+ if(data->set.get_filetime)
+ get_posix_time(&data->info.filetime, smb_m->last_change_time);
next_state = SMB_DOWNLOAD;
}
}
@@ -827,11 +847,11 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
sizeof(struct smb_header) + 13);
if(len > 0) {
if(off + sizeof(unsigned int) + len > smbc->got) {
- failf(conn->data, "Invalid input packet");
+ failf(data, "Invalid input packet");
result = CURLE_RECV_ERROR;
}
else
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)msg + off + sizeof(unsigned int),
len);
if(result) {
@@ -840,9 +860,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
}
}
- conn->data->req.bytecount += len;
- conn->data->req.offset += len;
- Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount);
+ data->req.bytecount += len;
+ data->req.offset += len;
+ Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break;
@@ -854,10 +874,10 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
}
len = Curl_read16_le(((const unsigned char *) msg) +
sizeof(struct smb_header) + 5);
- conn->data->req.bytecount += len;
- conn->data->req.offset += len;
- Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount);
- if(conn->data->req.bytecount >= conn->data->req.size)
+ data->req.bytecount += len;
+ data->req.offset += len;
+ Curl_pgrsSetUploadCounter(data, data->req.bytecount);
+ if(data->req.bytecount >= data->req.size)
next_state = SMB_CLOSE;
else
next_state = SMB_UPLOAD;
@@ -881,23 +901,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
switch(next_state) {
case SMB_OPEN:
- result = smb_send_open(conn);
+ result = smb_send_open(data);
break;
case SMB_DOWNLOAD:
- result = smb_send_read(conn);
+ result = smb_send_read(data);
break;
case SMB_UPLOAD:
- result = smb_send_write(conn);
+ result = smb_send_write(data);
break;
case SMB_CLOSE:
- result = smb_send_close(conn);
+ result = smb_send_close(data);
break;
case SMB_TREE_DISCONNECT:
- result = smb_send_tree_disconnect(conn);
+ result = smb_send_tree_disconnect(data);
break;
case SMB_DONE:
@@ -914,37 +934,42 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
return result;
}
- request_state(conn, next_state);
+ request_state(data, next_state);
return CURLE_OK;
}
-static CURLcode smb_done(struct connectdata *conn, CURLcode status,
+static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void) premature;
- Curl_safefree(conn->data->req.protop);
+ Curl_safefree(data->req.p.smb);
return status;
}
-static CURLcode smb_disconnect(struct connectdata *conn, bool dead)
+static CURLcode smb_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead)
{
struct smb_conn *smbc = &conn->proto.smbc;
(void) dead;
+ (void) data;
Curl_safefree(smbc->share);
Curl_safefree(smbc->domain);
Curl_safefree(smbc->recv_buf);
return CURLE_OK;
}
-static int smb_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int smb_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}
-static CURLcode smb_do(struct connectdata *conn, bool *done)
+static CURLcode smb_do(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
*done = FALSE;
@@ -954,10 +979,10 @@ static CURLcode smb_do(struct connectdata *conn, bool *done)
return CURLE_URL_MALFORMAT;
}
-static CURLcode smb_parse_url_path(struct connectdata *conn)
+static CURLcode smb_parse_url_path(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
- struct smb_request *req = data->req.protop;
+ struct smb_request *req = data->req.p.smb;
struct smb_conn *smbc = &conn->proto.smbc;
char *path;
char *slash;
@@ -996,6 +1021,5 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
return CURLE_OK;
}
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */
+#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
+ CURL_SIZEOF_CURL_OFF_T > 4 */
diff --git a/Utilities/cmcurl/lib/smb.h b/Utilities/cmcurl/lib/smb.h
index 136a89ce9..907cf0c8e 100644
--- a/Utilities/cmcurl/lib/smb.h
+++ b/Utilities/cmcurl/lib/smb.h
@@ -12,7 +12,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -243,16 +243,13 @@ struct smb_tree_disconnect {
#endif /* BUILDING_CURL_SMB_C */
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
(CURL_SIZEOF_CURL_OFF_T > 4)
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
extern const struct Curl_handler Curl_handler_smb;
extern const struct Curl_handler Curl_handler_smbs;
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */
+#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
+ CURL_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 aea41bb4e..1fc880065 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -91,24 +91,29 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done);
-static CURLcode smtp_do(struct connectdata *conn, bool *done);
-static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode smtp_do(struct Curl_easy *data, bool *done);
+static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode smtp_connect(struct connectdata *conn, bool *done);
-static CURLcode smtp_disconnect(struct connectdata *conn, bool dead);
-static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done);
-static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode smtp_setup_connection(struct connectdata *conn);
+static CURLcode smtp_connect(struct Curl_easy *data, bool *done);
+static CURLcode smtp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done);
+static int smtp_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode smtp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
static CURLcode smtp_parse_url_options(struct connectdata *conn);
-static CURLcode smtp_parse_url_path(struct connectdata *conn);
-static CURLcode smtp_parse_custom_request(struct connectdata *conn);
-static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
+static CURLcode smtp_parse_url_path(struct Curl_easy *data);
+static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
+static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
char **address, struct hostname *host);
-static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech,
+static CURLcode smtp_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *mech,
const char *initresp);
-static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp);
+static CURLcode smtp_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *resp);
static void smtp_get_message(char *buffer, char **outptr);
/*
@@ -133,6 +138,7 @@ const struct Curl_handler Curl_handler_smtp = {
ZERO_NULL, /* connection_check */
PORT_SMTP, /* defport */
CURLPROTO_SMTP, /* protocol */
+ CURLPROTO_SMTP, /* family */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
PROTOPT_URLOPTIONS
};
@@ -160,6 +166,7 @@ const struct Curl_handler Curl_handler_smtps = {
ZERO_NULL, /* connection_check */
PORT_SMTPS, /* defport */
CURLPROTO_SMTPS, /* protocol */
+ CURLPROTO_SMTP, /* family */
PROTOPT_CLOSEACTION | PROTOPT_SSL
| PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
};
@@ -197,11 +204,12 @@ static void smtp_to_smtps(struct connectdata *conn)
* also detects various capabilities from the EHLO response including the
* supported authentication mechanisms.
*/
-static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
- int *resp)
+static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *resp)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
bool result = FALSE;
+ (void)data;
/* Nothing for us */
if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
@@ -275,9 +283,9 @@ static void smtp_get_message(char *buffer, char **outptr)
*
* This is the ONLY way to change SMTP state!
*/
-static void state(struct connectdata *conn, smtpstate newstate)
+static void state(struct Curl_easy *data, smtpstate newstate)
{
- struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct smtp_conn *smtpc = &data->conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -298,7 +306,7 @@ static void state(struct connectdata *conn, smtpstate newstate)
};
if(smtpc->state != newstate)
- infof(conn->data, "SMTP %p state change from %s to %s\n",
+ infof(data, "SMTP %p state change from %s to %s\n",
(void *)smtpc, names[smtpc->state], names[newstate]);
#endif
@@ -312,9 +320,10 @@ static void state(struct connectdata *conn, smtpstate newstate)
* Sends the EHLO command to not only initialise communication with the ESMTP
* server but to also obtain a list of server side supported capabilities.
*/
-static CURLcode smtp_perform_ehlo(struct connectdata *conn)
+static CURLcode smtp_perform_ehlo(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */
@@ -324,10 +333,10 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn)
smtpc->auth_supported = FALSE; /* Clear the AUTH capability */
/* Send the EHLO command */
- result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain);
+ result = Curl_pp_sendf(data, &smtpc->pp, "EHLO %s", smtpc->domain);
if(!result)
- state(conn, SMTP_EHLO);
+ state(data, SMTP_EHLO);
return result;
}
@@ -338,7 +347,8 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn)
*
* Sends the HELO command to initialise communication with the SMTP server.
*/
-static CURLcode smtp_perform_helo(struct connectdata *conn)
+static CURLcode smtp_perform_helo(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
@@ -347,10 +357,10 @@ static CURLcode smtp_perform_helo(struct connectdata *conn)
in smtp connections */
/* Send the HELO command */
- result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain);
+ result = Curl_pp_sendf(data, &smtpc->pp, "HELO %s", smtpc->domain);
if(!result)
- state(conn, SMTP_HELO);
+ state(data, SMTP_HELO);
return result;
}
@@ -361,13 +371,15 @@ static CURLcode smtp_perform_helo(struct connectdata *conn)
*
* Sends the STLS command to start the upgrade to TLS.
*/
-static CURLcode smtp_perform_starttls(struct connectdata *conn)
+static CURLcode smtp_perform_starttls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the STARTTLS command */
- CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
+ "%s", "STARTTLS");
if(!result)
- state(conn, SMTP_STARTTLS);
+ state(data, SMTP_STARTTLS);
return result;
}
@@ -378,20 +390,21 @@ static CURLcode smtp_perform_starttls(struct connectdata *conn)
*
* Performs the upgrade to TLS.
*/
-static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
+static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
{
/* Start the SSL connection */
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&smtpc->ssldone);
if(!result) {
if(smtpc->state != SMTP_UPGRADETLS)
- state(conn, SMTP_UPGRADETLS);
+ state(data, SMTP_UPGRADETLS);
if(smtpc->ssldone) {
smtp_to_smtps(conn);
- result = smtp_perform_ehlo(conn);
+ result = smtp_perform_ehlo(data);
}
}
@@ -405,7 +418,8 @@ static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
* Sends an AUTH command allowing the client to login with the given SASL
* authentication mechanism.
*/
-static CURLcode smtp_perform_auth(struct connectdata *conn,
+static CURLcode smtp_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp)
{
@@ -414,11 +428,11 @@ static CURLcode smtp_perform_auth(struct connectdata *conn,
if(initresp) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
- result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
+ result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, initresp);
}
else {
/* Send the AUTH command */
- result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
+ result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s", mech);
}
return result;
@@ -430,11 +444,12 @@ static CURLcode smtp_perform_auth(struct connectdata *conn,
*
* Sends SASL continuation data or cancellation.
*/
-static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp)
+static CURLcode smtp_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *resp)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
- return Curl_pp_sendf(&smtpc->pp, "%s", resp);
+ return Curl_pp_sendf(data, &smtpc->pp, "%s", resp);
}
/***********************************************************************
@@ -444,9 +459,10 @@ static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp)
* Initiates the authentication sequence, with the appropriate SASL
* authentication mechanism.
*/
-static CURLcode smtp_perform_authentication(struct connectdata *conn)
+static CURLcode smtp_perform_authentication(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
saslprogress progress;
@@ -454,19 +470,19 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn)
server supports authentiation, and end the connect phase if not */
if(!smtpc->auth_supported ||
!Curl_sasl_can_authenticate(&smtpc->sasl, conn)) {
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
return result;
}
/* Calculate the SASL login details */
- result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress);
+ result = Curl_sasl_start(&smtpc->sasl, data, conn, FALSE, &progress);
if(!result) {
if(progress == SASL_INPROGRESS)
- state(conn, SMTP_AUTH);
+ state(data, SMTP_AUTH);
else {
/* Other mechanisms not supported */
- infof(conn->data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
}
@@ -480,11 +496,11 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn)
*
* Sends a SMTP based command.
*/
-static CURLcode smtp_perform_command(struct connectdata *conn)
+static CURLcode smtp_perform_command(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SMTP *smtp = data->req.p.smtp;
if(smtp->rcpt) {
/* We notify the server we are sending UTF-8 data if a) it supports the
@@ -499,7 +515,7 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
/* Parse the mailbox to verify into the local address and host name
parts, converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, smtp->rcpt->data,
+ result = smtp_parse_address(data, smtp->rcpt->data,
&address, &host);
if(result)
return result;
@@ -512,7 +528,7 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
/* Send the VRFY command (Note: The host name part may be absent when the
host is a local system) */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "VRFY %s%s%s%s",
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "VRFY %s%s%s%s",
address,
host.name ? "@" : "",
host.name ? host.name : "",
@@ -528,19 +544,20 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
(!strcmp(smtp->custom, "EXPN"));
/* Send the custom recipient based command such as the EXPN command */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s%s", smtp->custom,
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
+ "%s %s%s", smtp->custom,
smtp->rcpt->data,
utf8 ? " SMTPUTF8" : "");
}
}
else
/* Send the non-recipient based command such as HELP */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s",
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s",
smtp->custom && smtp->custom[0] != '\0' ?
smtp->custom : "HELP");
if(!result)
- state(conn, SMTP_COMMAND);
+ state(data, SMTP_COMMAND);
return result;
}
@@ -551,13 +568,13 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
*
* Sends an MAIL command to initiate the upload of a message.
*/
-static CURLcode smtp_perform_mail(struct connectdata *conn)
+static CURLcode smtp_perform_mail(struct Curl_easy *data)
{
char *from = NULL;
char *auth = NULL;
char *size = NULL;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
/* We notify the server we are sending UTF-8 data if a) it supports the
SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in
@@ -572,7 +589,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
/* Parse the FROM mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, data->set.str[STRING_MAIL_FROM],
+ result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM],
&address, &host);
if(result)
return result;
@@ -610,7 +627,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
/* Parse the AUTH mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, data->set.str[STRING_MAIL_AUTH],
+ result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH],
&address, &host);
if(result) {
free(from);
@@ -658,7 +675,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
NULL, MIMESTRATEGY_MAIL);
if(!result)
- if(!Curl_checkheaders(conn, "Mime-Version"))
+ if(!Curl_checkheaders(data, "Mime-Version"))
result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
"Mime-Version: 1.0");
@@ -697,7 +714,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
any there do, as we need to correctly identify our support for SMTPUTF8
in the envelope, as per RFC-6531 sect. 3.4 */
if(conn->proto.smtpc.utf8_supported && !utf8) {
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
struct curl_slist *rcpt = smtp->rcpt;
while(rcpt && !utf8) {
@@ -710,7 +727,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
}
/* Send the MAIL command */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
"MAIL FROM:%s%s%s%s%s%s",
from, /* Mandatory */
auth ? " AUTH=" : "", /* Optional on AUTH support */
@@ -725,7 +742,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
free(size);
if(!result)
- state(conn, SMTP_MAIL);
+ state(data, SMTP_MAIL);
return result;
}
@@ -737,35 +754,36 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
* Sends a RCPT TO command for a given recipient as part of the message upload
* process.
*/
-static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
+static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SMTP *smtp = data->req.p.smtp;
char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL };
/* Parse the recipient mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, smtp->rcpt->data,
+ result = smtp_parse_address(data, smtp->rcpt->data,
&address, &host);
if(result)
return result;
/* Send the RCPT TO command */
if(host.name)
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", address,
- host.name);
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s@%s>",
+ address, host.name);
else
/* An invalid mailbox was provided but we'll simply let the server worry
about that and reply with a 501 error */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", address);
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s>",
+ address);
Curl_free_idnconverted_hostname(&host);
free(address);
if(!result)
- state(conn, SMTP_RCPT);
+ state(data, SMTP_RCPT);
return result;
}
@@ -776,25 +794,24 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
*
* Performs the quit action prior to sclose() being called.
*/
-static CURLcode smtp_perform_quit(struct connectdata *conn)
+static CURLcode smtp_perform_quit(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the QUIT command */
- CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT");
if(!result)
- state(conn, SMTP_QUIT);
+ state(data, SMTP_QUIT);
return result;
}
/* For the initial server greeting */
-static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
+static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
@@ -802,19 +819,17 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
result = CURLE_WEIRD_SERVER_REPLY;
}
else
- result = smtp_perform_ehlo(conn);
+ result = smtp_perform_ehlo(data);
return result;
}
/* For STARTTLS responses */
-static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
+static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode != 220) {
@@ -823,20 +838,20 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
- result = smtp_perform_authentication(conn);
+ result = smtp_perform_authentication(data);
}
else
- result = smtp_perform_upgrade_tls(conn);
+ result = smtp_perform_upgrade_tls(data);
return result;
}
/* For EHLO responses */
-static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
+ struct connectdata *conn, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *line = data->state.buffer;
size_t len = strlen(line);
@@ -845,7 +860,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
if(smtpcode/100 != 2 && smtpcode != 1) {
if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use)
- result = smtp_perform_helo(conn);
+ result = smtp_perform_helo(data, conn);
else {
failf(data, "Remote access denied: %d", smtpcode);
result = CURLE_REMOTE_ACCESS_DENIED;
@@ -913,17 +928,17 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(smtpc->tls_supported)
/* Switch to TLS connection now */
- result = smtp_perform_starttls(conn);
+ result = smtp_perform_starttls(data, conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
- result = smtp_perform_authentication(conn);
+ result = smtp_perform_authentication(data);
else {
failf(data, "STARTTLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = smtp_perform_authentication(conn);
+ result = smtp_perform_authentication(data);
}
}
else {
@@ -935,12 +950,10 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
}
/* For HELO responses */
-static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
@@ -949,28 +962,28 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode,
}
else
/* End of connect phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
return result;
}
/* For SASL authentication responses */
-static CURLcode smtp_state_auth_resp(struct connectdata *conn,
+static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
saslprogress progress;
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress);
+ result = Curl_sasl_continue(&smtpc->sasl, data, conn, smtpcode, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
- state(conn, SMTP_STOP); /* Authenticated */
+ state(data, SMTP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
failf(data, "Authentication cancelled");
@@ -984,12 +997,11 @@ static CURLcode smtp_state_auth_resp(struct connectdata *conn,
}
/* For command responses */
-static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
char *line = data->state.buffer;
size_t len = strlen(line);
@@ -1004,7 +1016,7 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
/* Temporarily add the LF character back and send as body to the client */
if(!data->set.opt_no_body) {
line[len] = '\n';
- result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
}
@@ -1014,15 +1026,15 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
if(smtp->rcpt) {
/* Send the next command */
- result = smtp_perform_command(conn);
+ result = smtp_perform_command(data);
}
else
/* End of DO phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
}
else
/* End of DO phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
}
}
@@ -1030,12 +1042,10 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
}
/* For MAIL responses */
-static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_mail_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
@@ -1044,18 +1054,18 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
}
else
/* Start the RCPT TO command */
- result = smtp_perform_rcpt_to(conn);
+ result = smtp_perform_rcpt_to(data);
return result;
}
/* For RCPT responses */
-static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
+ struct connectdata *conn, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
bool is_smtp_err = FALSE;
bool is_smtp_blocking_err = FALSE;
@@ -1088,7 +1098,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
if(smtp->rcpt)
/* Send the next RCPT TO command */
- result = smtp_perform_rcpt_to(conn);
+ result = smtp_perform_rcpt_to(data);
else {
/* We weren't able to issue a successful RCPT TO command while going
over recipients (potentially multiple). Sending back last error. */
@@ -1098,10 +1108,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
}
else {
/* Send the DATA command */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA");
if(!result)
- state(conn, SMTP_DATA);
+ state(data, SMTP_DATA);
}
}
}
@@ -1110,12 +1120,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
}
/* For DATA response */
-static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode != 354) {
@@ -1130,7 +1138,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
}
return result;
@@ -1138,7 +1146,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
/* For POSTDATA responses, which are received after the entire DATA
part has been sent to the server */
-static CURLcode smtp_state_postdata_resp(struct connectdata *conn,
+static CURLcode smtp_state_postdata_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
@@ -1150,16 +1158,16 @@ static CURLcode smtp_state_postdata_resp(struct connectdata *conn,
result = CURLE_RECV_ERROR;
/* End of DONE phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
return result;
}
-static CURLcode smtp_statemach_act(struct connectdata *conn)
+static CURLcode smtp_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
int smtpcode;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
@@ -1167,15 +1175,15 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
if(smtpc->state == SMTP_UPGRADETLS)
- return smtp_perform_upgrade_tls(conn);
+ return smtp_perform_upgrade_tls(data);
/* Flush any data that needs to be sent */
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
do {
/* Read the response from the server */
- result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
+ result = Curl_pp_readresp(data, sock, pp, &smtpcode, &nread);
if(result)
return result;
@@ -1189,50 +1197,50 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
/* We have now received a full SMTP server response */
switch(smtpc->state) {
case SMTP_SERVERGREET:
- result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_servergreet_resp(data, smtpcode, smtpc->state);
break;
case SMTP_EHLO:
- result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_ehlo_resp(data, conn, smtpcode, smtpc->state);
break;
case SMTP_HELO:
- result = smtp_state_helo_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_helo_resp(data, smtpcode, smtpc->state);
break;
case SMTP_STARTTLS:
- result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_starttls_resp(data, smtpcode, smtpc->state);
break;
case SMTP_AUTH:
- result = smtp_state_auth_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_auth_resp(data, smtpcode, smtpc->state);
break;
case SMTP_COMMAND:
- result = smtp_state_command_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_command_resp(data, smtpcode, smtpc->state);
break;
case SMTP_MAIL:
- result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_mail_resp(data, smtpcode, smtpc->state);
break;
case SMTP_RCPT:
- result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_rcpt_resp(data, conn, smtpcode, smtpc->state);
break;
case SMTP_DATA:
- result = smtp_state_data_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_data_resp(data, smtpcode, smtpc->state);
break;
case SMTP_POSTDATA:
- result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_postdata_resp(data, smtpcode, smtpc->state);
break;
case SMTP_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
break;
}
} while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
@@ -1241,44 +1249,46 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
}
/* Called repeatedly until done from multi.c */
-static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &smtpc->ssldone);
if(result || !smtpc->ssldone)
return result;
}
- result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE);
+ result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE);
*done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
return result;
}
-static CURLcode smtp_block_statemach(struct connectdata *conn,
+static CURLcode smtp_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
bool disconnecting)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
while(smtpc->state != SMTP_STOP && !result)
- result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting);
+ result = Curl_pp_statemach(data, &smtpc->pp, TRUE, disconnecting);
return result;
}
/* Allocate and initialize the SMTP struct for the current Curl_easy if
required */
-static CURLcode smtp_init(struct connectdata *conn)
+static CURLcode smtp_init(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct SMTP *smtp;
- smtp = data->req.protop = calloc(sizeof(struct SMTP), 1);
+ smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1);
if(!smtp)
result = CURLE_OUT_OF_MEMORY;
@@ -1286,9 +1296,10 @@ static CURLcode smtp_init(struct connectdata *conn)
}
/* For the SMTP "protocol connect" and "doing" phases only */
-static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int smtp_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.smtpc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.smtpc.pp, socks);
}
/***********************************************************************
@@ -1301,9 +1312,10 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks)
* The variable pointed to by 'done' will be TRUE if the protocol-layer
* connect phase is done when this function returns, or FALSE if not.
*/
-static CURLcode smtp_connect(struct connectdata *conn, bool *done)
+static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
@@ -1312,17 +1324,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
/* We always support persistent connections in SMTP */
connkeep(conn, "SMTP default");
- /* Set the default response time-out */
- pp->response_time = RESP_TIMEOUT;
- pp->statemach_act = smtp_statemach_act;
- pp->endofresp = smtp_endofresp;
- pp->conn = conn;
+ PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp);
/* Initialize the SASL storage */
Curl_sasl_init(&smtpc->sasl, &saslsmtp);
/* Initialise the pingpong layer */
- Curl_pp_init(pp);
+ Curl_pp_setup(pp);
+ Curl_pp_init(data, pp);
/* Parse the URL options */
result = smtp_parse_url_options(conn);
@@ -1330,14 +1339,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
return result;
/* Parse the URL path */
- result = smtp_parse_url_path(conn);
+ result = smtp_parse_url_path(data);
if(result)
return result;
/* Start off waiting for the server greeting response */
- state(conn, SMTP_SERVERGREET);
+ state(data, SMTP_SERVERGREET);
- result = smtp_multi_statemach(conn, done);
+ result = smtp_multi_statemach(data, done);
return result;
}
@@ -1351,12 +1360,12 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
*
* Input argument is already checked for validity.
*/
-static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SMTP *smtp = data->req.p.smtp;
struct pingpong *pp = &conn->proto.smtpc.pp;
char *eob;
ssize_t len;
@@ -1364,7 +1373,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
(void)premature;
- if(!smtp || !pp->conn)
+ if(!smtp)
return CURLE_OK;
/* Cleanup our per-request based variables */
@@ -1384,7 +1393,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
fail when using a different pointer following a previous write, that
returned CURLE_AGAIN, we duplicate the EOB now rather than when the
bytes written doesn't equal len. */
- if(smtp->trailing_crlf || !conn->data->state.infilesize) {
+ if(smtp->trailing_crlf || !data->state.infilesize) {
eob = strdup(&SMTP_EOB[2]);
len = SMTP_EOB_LEN - 2;
}
@@ -1397,7 +1406,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
return CURLE_OUT_OF_MEMORY;
/* Send the end of block data */
- result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
+ result = Curl_write(data, conn->writesockfd, eob, len, &bytes_written);
if(result) {
free(eob);
return result;
@@ -1417,10 +1426,10 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
free(eob);
}
- state(conn, SMTP_POSTDATA);
+ state(data, SMTP_POSTDATA);
/* Run the state-machine */
- result = smtp_block_statemach(conn, FALSE);
+ result = smtp_block_statemach(data, conn, FALSE);
}
/* Clear the transfer mode for the next request */
@@ -1436,15 +1445,15 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
* This is the actual DO function for SMTP. Transfer a mail, send a command
* or get some data according to the options previously setup.
*/
-static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
+static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
bool *dophase_done)
{
/* This is SMTP and no proxy */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SMTP *smtp = data->req.p.smtp;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
@@ -1470,21 +1479,21 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
/* Start the first command in the DO phase */
if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
- result = smtp_perform_mail(conn);
+ result = smtp_perform_mail(data);
else
/* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */
- result = smtp_perform_command(conn);
+ result = smtp_perform_command(data);
if(result)
return result;
/* Run the state-machine */
- result = smtp_multi_statemach(conn, dophase_done);
+ result = smtp_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1498,18 +1507,17 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
*
* The input argument is already checked for validity.
*/
-static CURLcode smtp_do(struct connectdata *conn, bool *done)
+static CURLcode smtp_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
-
*done = FALSE; /* default to false */
/* Parse the custom request */
- result = smtp_parse_custom_request(conn);
+ result = smtp_parse_custom_request(data);
if(result)
return result;
- result = smtp_regular_transfer(conn, done);
+ result = smtp_regular_transfer(data, done);
return result;
}
@@ -1521,19 +1529,21 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
* Disconnect from an SMTP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode smtp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
+ (void)data;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to. */
- /* The SMTP session may or may not have been allocated/setup at this
- point! */
- if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart)
- if(!smtp_perform_quit(conn))
- (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */
+ if(!dead_connection && conn->bits.protoconnstart) {
+ if(!smtp_perform_quit(data, conn))
+ (void)smtp_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */
+ }
/* Disconnect from the server */
Curl_pp_disconnect(&smtpc->pp);
@@ -1548,30 +1558,30 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
}
/* Call this when the DO phase has completed */
-static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected)
+static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
{
- struct SMTP *smtp = conn->data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
(void)connected;
if(smtp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
- Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
+ Curl_setup_transfer(data, -1, -1, FALSE, -1);
return CURLE_OK;
}
/* Called from multi.c while DOing */
-static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = smtp_multi_statemach(conn, dophase_done);
+ CURLcode result = smtp_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = smtp_dophase_done(conn, FALSE /* not connected */);
+ result = smtp_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -1586,12 +1596,11 @@ static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done)
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
-static CURLcode smtp_regular_transfer(struct connectdata *conn,
+static CURLcode smtp_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
@@ -1603,16 +1612,17 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn,
Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */
- result = smtp_perform(conn, &connected, dophase_done);
+ result = smtp_perform(data, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = smtp_dophase_done(conn, connected);
+ result = smtp_dophase_done(data, connected);
return result;
}
-static CURLcode smtp_setup_connection(struct connectdata *conn)
+static CURLcode smtp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result;
@@ -1620,7 +1630,7 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
conn->bits.tls_upgraded = FALSE;
/* Initialise the SMTP layer */
- result = smtp_init(conn);
+ result = smtp_init(data);
if(result)
return result;
@@ -1672,10 +1682,10 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn)
*
* Parse the URL path into separate path components.
*/
-static CURLcode smtp_parse_url_path(struct connectdata *conn)
+static CURLcode smtp_parse_url_path(struct Curl_easy *data)
{
/* The SMTP struct is already initialised in smtp_connect() */
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *path = &data->state.up.path[1]; /* skip leading path */
char localhost[HOSTNAME_MAX + 1];
@@ -1689,7 +1699,7 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
}
/* URL decode the path and use it as the domain in our EHLO */
- return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL,
+ return Curl_urldecode(data, path, 0, &smtpc->domain, NULL,
REJECT_CTRL);
}
@@ -1699,11 +1709,10 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
*
* Parse the custom request.
*/
-static CURLcode smtp_parse_custom_request(struct connectdata *conn)
+static CURLcode smtp_parse_custom_request(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
@@ -1747,7 +1756,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn)
* calling function deems it to be) then the input will simply be returned in
* the address part with the host name being NULL.
*/
-static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
+static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
char **address, struct hostname *host)
{
CURLcode result = CURLE_OK;
@@ -1772,7 +1781,7 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
host->name = host->name + 1;
/* Attempt to convert the host name to IDN ACE */
- (void) Curl_idnconvert_hostname(conn, host);
+ (void) Curl_idnconvert_hostname(data, host);
/* If Curl_idnconvert_hostname() fails then we shall attempt to continue
and send the host name using UTF-8 rather than as 7-bit ACE (which is
@@ -1785,7 +1794,7 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
return result;
}
-CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
+CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread)
{
/* When sending a SMTP payload we must detect CRLF. sequences making sure
they are sent as CRLF.. instead, as a . on the beginning of a line will
@@ -1795,8 +1804,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
*/
ssize_t i;
ssize_t si;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
char *scratch = data->state.scratch;
char *newscratch = NULL;
char *oldscratch = NULL;
diff --git a/Utilities/cmcurl/lib/smtp.h b/Utilities/cmcurl/lib/smtp.h
index 164a175d7..1fe45346e 100644
--- a/Utilities/cmcurl/lib/smtp.h
+++ b/Utilities/cmcurl/lib/smtp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -57,10 +57,10 @@ struct SMTP {
struct curl_slist *rcpt; /* Recipient list */
bool rcpt_had_ok; /* Whether any of RCPT TO commands (depends on
total number of recipients) succeeded so far */
+ bool trailing_crlf; /* Specifies if the trailing CRLF is present */
int rcpt_last_error; /* The last error received for RCPT TO command */
size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */
- bool trailing_crlf; /* Specifies if the tailing CRLF is present */
};
/* smtp_conn is used for struct connection-oriented data in the connectdata
@@ -91,6 +91,6 @@ extern const struct Curl_handler Curl_handler_smtps;
#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
#define SMTP_EOB_REPL_LEN 4
-CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread);
+CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread);
#endif /* HEADER_CURL_SMTP_H */
diff --git a/Utilities/cmcurl/lib/sockaddr.h b/Utilities/cmcurl/lib/sockaddr.h
index b037ee06c..84c08d9bb 100644
--- a/Utilities/cmcurl/lib/sockaddr.h
+++ b/Utilities/cmcurl/lib/sockaddr.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/socketpair.c b/Utilities/cmcurl/lib/socketpair.c
index 1ec0d75a4..2c580ad2d 100644
--- a/Utilities/cmcurl/lib/socketpair.c
+++ b/Utilities/cmcurl/lib/socketpair.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
#include "curl_setup.h"
#include "socketpair.h"
-#ifndef HAVE_SOCKETPAIR
+#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
#ifdef WIN32
/*
* This is a socketpair() implementation for Windows.
diff --git a/Utilities/cmcurl/lib/socketpair.h b/Utilities/cmcurl/lib/socketpair.h
index be9fb24f9..033a235aa 100644
--- a/Utilities/cmcurl/lib/socketpair.h
+++ b/Utilities/cmcurl/lib/socketpair.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index 44783d015..d1c2a2ed1 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -51,7 +51,7 @@
*
* This is STUPID BLOCKING behavior. Only used by the SOCKS GSSAPI functions.
*/
-int Curl_blockread_all(struct connectdata *conn, /* connection data */
+int Curl_blockread_all(struct Curl_easy *data, /* transfer */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
ssize_t buffersize, /* max amount to read */
@@ -62,7 +62,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
int result;
*n = 0;
for(;;) {
- timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, TRUE);
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* we already got the timeout */
result = CURLE_OPERATION_TIMEDOUT;
@@ -107,13 +107,14 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
/* always use this function to change state, to make debugging easier */
-static void socksstate(struct connectdata *conn,
+static void socksstate(struct Curl_easy *data,
enum connect_t state
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
+ struct connectdata *conn = data->conn;
enum connect_t oldstate = conn->cnnct.state;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* synced with the state list in urldata.h */
@@ -146,7 +147,7 @@ static void socksstate(struct connectdata *conn,
conn->cnnct.state = state;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- infof(conn->data,
+ infof(data,
"SXSTATE: %s => %s conn %p; line %d\n",
statename[oldstate], statename[conn->cnnct.state], conn,
lineno);
@@ -184,33 +185,36 @@ int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
* Nonsupport "Identification Protocol (RFC1413)"
*/
-CURLcode Curl_SOCKS4(const char *proxy_user,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done)
+CURLproxycode Curl_SOCKS4(const char *proxy_user,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done)
{
+ struct connectdata *conn = data->conn;
const bool protocol4a =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
- unsigned char *socksreq = &conn->cnnct.socksreq[0];
+ unsigned char *socksreq = (unsigned char *)data->state.buffer;
CURLcode result;
curl_socket_t sockfd = conn->sock[sockindex];
- struct Curl_easy *data = conn->data;
struct connstate *sx = &conn->cnnct;
struct Curl_dns_entry *dns = NULL;
ssize_t actualread;
ssize_t written;
+ /* make sure that the buffer is at least 600 bytes */
+ DEBUGASSERT(READBUFFER_MIN >= 600);
+
if(!SOCKS_STATE(sx->state) && !*done)
- sxstate(conn, CONNECT_SOCKS_INIT);
+ sxstate(data, CONNECT_SOCKS_INIT);
switch(sx->state) {
case CONNECT_SOCKS_INIT:
/* SOCKS4 can only do IPv4, insist! */
conn->ip_version = CURL_IPRESOLVE_V4;
if(conn->bits.httpproxy)
- infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+ infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
protocol4a ? "a" : "", hostname, remote_port);
infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
@@ -234,39 +238,42 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
enum resolve_t rc =
- Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
+ Curl_resolv(data, hostname, remote_port, FALSE, &dns);
if(rc == CURLRESOLV_ERROR)
- return CURLE_COULDNT_RESOLVE_PROXY;
+ return CURLPX_RESOLVE_HOST;
else if(rc == CURLRESOLV_PENDING) {
- sxstate(conn, CONNECT_RESOLVING);
+ sxstate(data, CONNECT_RESOLVING);
infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_RESOLVED);
+ sxstate(data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
/* socks4a doesn't resolve anything locally */
- sxstate(conn, CONNECT_REQ_INIT);
+ sxstate(data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
+ dns = Curl_fetch_addr(data, hostname, (int)conn->port);
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
infof(data, "Hostname '%s' was found\n", hostname);
- sxstate(conn, CONNECT_RESOLVED);
+ sxstate(data, CONNECT_RESOLVED);
}
else {
- result = Curl_resolv_check(data->conn, &dns);
- if(!dns)
- return result;
+ result = Curl_resolv_check(data, &dns);
+ if(!dns) {
+ if(result)
+ return CURLPX_RESOLVE_HOST;
+ return CURLPX_OK;
+ }
}
/* FALLTHROUGH */
CONNECT_RESOLVED:
@@ -295,7 +302,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
}
else {
hp = NULL; /* fail! */
- failf(data, "SOCKS4 connection to %s not supported\n", buf);
+ failf(data, "SOCKS4 connection to %s not supported", buf);
}
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
@@ -303,7 +310,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
hostname);
- return CURLE_COULDNT_RESOLVE_HOST;
+ return CURLPX_RESOLVE_HOST;
}
}
/* FALLTHROUGH */
@@ -315,9 +322,9 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
if(proxy_user) {
size_t plen = strlen(proxy_user);
- if(plen >= sizeof(sx->socksreq) - 8) {
- failf(data, "Too long SOCKS proxy name, can't use!\n");
- return CURLE_COULDNT_CONNECT;
+ if(plen >= (size_t)data->set.buffer_size - 8) {
+ failf(data, "Too long SOCKS proxy user name, can't use!");
+ return CURLPX_LONG_USER;
}
/* copy the proxy name WITH trailing zero */
memcpy(socksreq + 8, proxy_user, plen + 1);
@@ -343,34 +350,34 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
strcpy((char *)socksreq + packetsize, hostname);
else {
failf(data, "SOCKS4: too long host name");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_LONG_HOSTNAME;
}
packetsize += hostnamelen;
}
sx->outp = socksreq;
sx->outstanding = packetsize;
- sxstate(conn, CONNECT_REQ_SENDING);
+ sxstate(data, CONNECT_REQ_SENDING);
}
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
/* Send request */
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS4 connect request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_CONNECT;
}
if(written != sx->outstanding) {
/* not done, remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
/* done sending! */
sx->outstanding = 8; /* receive data size */
sx->outp = socksreq;
- sxstate(conn, CONNECT_SOCKS_READ);
+ sxstate(data, CONNECT_SOCKS_READ);
/* FALLTHROUGH */
case CONNECT_SOCKS_READ:
@@ -380,20 +387,20 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
if(result && (CURLE_AGAIN != result)) {
failf(data, "SOCKS4: Failed receiving connect request ack: %s",
curl_easy_strerror(result));
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_CONNECT;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in reading state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_DONE);
+ sxstate(data, CONNECT_DONE);
break;
default: /* lots of unused states in SOCKS4 */
break;
@@ -422,7 +429,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
if(socksreq[0] != 0) {
failf(data,
"SOCKS4 reply has wrong version, version should be 0.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_VERSION;
}
/* Result */
@@ -434,57 +441,53 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected or failed.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_REQUEST_FAILED;
case 92:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected because SOCKS server cannot connect to "
"identd on the client.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_IDENTD;
case 93:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected because the client program and identd "
"report different user-ids.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_IDENTD_DIFFER;
default:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", Unknown.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_UNKNOWN_FAIL;
}
*done = TRUE;
- return CURLE_OK; /* Proxy was successful! */
+ return CURLPX_OK; /* Proxy was successful! */
}
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
*/
-CURLcode Curl_SOCKS5(const char *proxy_user,
- const char *proxy_password,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done)
+CURLproxycode Curl_SOCKS5(const char *proxy_user,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done)
{
/*
According to the RFC1928, section "6. Replies". This is what a SOCK5
@@ -502,14 +505,14 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
o REP Reply field:
o X'00' succeeded
*/
- unsigned char *socksreq = &conn->cnnct.socksreq[0];
+ struct connectdata *conn = data->conn;
+ unsigned char *socksreq = (unsigned char *)data->state.buffer;
char dest[256] = "unknown"; /* printable hostname:port */
int idx;
ssize_t actualread;
ssize_t written;
CURLcode result;
curl_socket_t sockfd = conn->sock[sockindex];
- struct Curl_easy *data = conn->data;
bool socks5_resolve_local =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
const size_t hostname_len = strlen(hostname);
@@ -520,23 +523,23 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
struct Curl_dns_entry *dns = NULL;
if(!SOCKS_STATE(sx->state) && !*done)
- sxstate(conn, CONNECT_SOCKS_INIT);
+ sxstate(data, CONNECT_SOCKS_INIT);
switch(sx->state) {
case CONNECT_SOCKS_INIT:
if(conn->bits.httpproxy)
- infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+ infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
hostname, remote_port);
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
- infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
+ infof(data, "SOCKS5: server resolving disabled for hostnames of "
"length > 255 [actual len=%zu]\n", hostname_len);
socks5_resolve_local = TRUE;
}
if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
- infof(conn->data,
+ infof(data,
"warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
auth);
if(!(auth & CURLAUTH_BASIC))
@@ -558,31 +561,31 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* write the number of authentication methods */
socksreq[1] = (unsigned char) (idx - 2);
- result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written);
+ result = Curl_write_plain(data, sockfd, (char *)socksreq, idx, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to send initial SOCKS5 request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_CONNECT;
}
if(written != idx) {
- sxstate(conn, CONNECT_SOCKS_SEND);
+ sxstate(data, CONNECT_SOCKS_SEND);
sx->outstanding = idx - written;
sx->outp = &socksreq[written];
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_SOCKS_READ);
+ sxstate(data, CONNECT_SOCKS_READ);
goto CONNECT_SOCKS_READ_INIT;
case CONNECT_SOCKS_SEND:
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to send initial SOCKS5 request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_CONNECT;
}
if(written != sx->outstanding) {
/* not done, remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
/* FALLTHROUGH */
CONNECT_SOCKS_READ_INIT:
@@ -595,40 +598,40 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to receive initial SOCKS5 response.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_CONNECT;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "Connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in reading state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
else if(socksreq[0] != 5) {
failf(data, "Received invalid version in initial SOCKS5 response.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_VERSION;
}
else if(socksreq[1] == 0) {
/* DONE! No authentication needed. Send request. */
- sxstate(conn, CONNECT_REQ_INIT);
+ sxstate(data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
}
else if(socksreq[1] == 2) {
/* regular name + password authentication */
- sxstate(conn, CONNECT_AUTH_INIT);
+ sxstate(data, CONNECT_AUTH_INIT);
goto CONNECT_AUTH_INIT;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else if(allow_gssapi && (socksreq[1] == 1)) {
- sxstate(conn, CONNECT_GSSAPI_INIT);
- result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
+ sxstate(data, CONNECT_GSSAPI_INIT);
+ result = Curl_SOCKS5_gssapi_negotiate(sockindex, data);
if(result) {
failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI;
}
}
#endif
@@ -637,16 +640,16 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
if(!allow_gssapi && (socksreq[1] == 1)) {
failf(data,
"SOCKS5 GSSAPI per-message authentication is not supported.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI_PERMSG;
}
else if(socksreq[1] == 255) {
failf(data, "No authentication method was acceptable.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_NO_AUTH;
}
}
failf(data,
"Undocumented SOCKS5 mode attempted to be used by server.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_UNKNOWN_MODE;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
case CONNECT_GSSAPI_INIT:
/* GSSAPI stuff done non-blocking */
@@ -683,7 +686,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* the length must fit in a single byte */
if(proxy_user_len >= 255) {
failf(data, "Excessive user name length for proxy auth");
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLPX_LONG_USER;
}
memcpy(socksreq + len, proxy_user, proxy_user_len);
}
@@ -693,95 +696,98 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* the length must fit in a single byte */
if(proxy_password_len > 255) {
failf(data, "Excessive password length for proxy auth");
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLPX_LONG_PASSWD;
}
memcpy(socksreq + len, proxy_password, proxy_password_len);
}
len += proxy_password_len;
- sxstate(conn, CONNECT_AUTH_SEND);
+ sxstate(data, CONNECT_AUTH_SEND);
sx->outstanding = len;
sx->outp = socksreq;
}
/* FALLTHROUGH */
case CONNECT_AUTH_SEND:
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS5 sub-negotiation request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_AUTH;
}
if(sx->outstanding != written) {
/* remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
sx->outp = socksreq;
sx->outstanding = 2;
- sxstate(conn, CONNECT_AUTH_READ);
+ sxstate(data, CONNECT_AUTH_READ);
/* FALLTHROUGH */
case CONNECT_AUTH_READ:
result = Curl_read_plain(sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_AUTH;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
/* ignore the first (VER) byte */
else if(socksreq[1] != 0) { /* status */
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
socksreq[0], socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_USER_REJECTED;
}
/* Everything is good so far, user was authenticated! */
- sxstate(conn, CONNECT_REQ_INIT);
+ sxstate(data, CONNECT_REQ_INIT);
/* FALLTHROUGH */
CONNECT_REQ_INIT:
case CONNECT_REQ_INIT:
if(socks5_resolve_local) {
- enum resolve_t rc = Curl_resolv(conn, hostname, remote_port,
+ enum resolve_t rc = Curl_resolv(data, hostname, remote_port,
FALSE, &dns);
if(rc == CURLRESOLV_ERROR)
- return CURLE_COULDNT_RESOLVE_HOST;
+ return CURLPX_RESOLVE_HOST;
if(rc == CURLRESOLV_PENDING) {
- sxstate(conn, CONNECT_RESOLVING);
- return CURLE_OK;
+ sxstate(data, CONNECT_RESOLVING);
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_RESOLVED);
+ sxstate(data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
goto CONNECT_RESOLVE_REMOTE;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
+ dns = Curl_fetch_addr(data, hostname, remote_port);
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
infof(data, "SOCKS5: hostname '%s' found\n", hostname);
}
if(!dns) {
- result = Curl_resolv_check(data->conn, &dns);
- if(!dns)
- return result;
+ result = Curl_resolv_check(data, &dns);
+ if(!dns) {
+ if(result)
+ return CURLPX_RESOLVE_HOST;
+ return CURLPX_OK;
+ }
}
/* FALLTHROUGH */
CONNECT_RESOLVED:
@@ -793,7 +799,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
hostname);
- return CURLE_COULDNT_RESOLVE_HOST;
+ return CURLPX_RESOLVE_HOST;
}
Curl_printable_address(hp, dest, sizeof(dest));
@@ -833,7 +839,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
#endif
else {
hp = NULL; /* fail! */
- failf(data, "SOCKS5 connection to %s not supported\n", dest);
+ failf(data, "SOCKS5 connection to %s not supported", dest);
}
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
@@ -867,64 +873,81 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
failf(data, "SOCKS5 GSS-API protection not yet implemented.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI_PROTECTION;
}
#endif
sx->outp = socksreq;
sx->outstanding = len;
- sxstate(conn, CONNECT_REQ_SENDING);
+ sxstate(data, CONNECT_REQ_SENDING);
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS5 connect request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_REQUEST;
}
if(sx->outstanding != written) {
/* remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
failf(data, "SOCKS5 GSS-API protection not yet implemented.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI_PROTECTION;
}
#endif
sx->outstanding = 10; /* minimum packet size is 10 */
sx->outp = socksreq;
- sxstate(conn, CONNECT_REQ_READ);
+ sxstate(data, CONNECT_REQ_READ);
/* FALLTHROUGH */
case CONNECT_REQ_READ:
result = Curl_read_plain(sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_REQACK;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
if(socksreq[0] != 5) { /* version */
failf(data,
"SOCKS5 reply has wrong version, version should be 5.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_VERSION;
}
else if(socksreq[1] != 0) { /* 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)",
hostname, (unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ if(code < 9) {
+ /* RFC 1928 section 6 lists: */
+ static const CURLproxycode lookup[] = {
+ CURLPX_OK,
+ CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+ CURLPX_REPLY_NOT_ALLOWED,
+ CURLPX_REPLY_NETWORK_UNREACHABLE,
+ CURLPX_REPLY_HOST_UNREACHABLE,
+ CURLPX_REPLY_CONNECTION_REFUSED,
+ CURLPX_REPLY_TTL_EXPIRED,
+ CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+ CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+ };
+ rc = lookup[code];
+ }
+ return rc;
}
/* Fix: in general, returned BND.ADDR is variable length parameter by RFC
@@ -958,7 +981,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
}
else {
failf(data, "SOCKS5 reply has wrong address type.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_ADDRESS_TYPE;
}
/* At this point we already read first 10 bytes */
@@ -969,10 +992,10 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
if(len > 10) {
sx->outstanding = len - 10; /* get the rest */
sx->outp = &socksreq[10];
- sxstate(conn, CONNECT_REQ_READ_MORE);
+ sxstate(data, CONNECT_REQ_READ_MORE);
}
else {
- sxstate(conn, CONNECT_DONE);
+ sxstate(data, CONNECT_DONE);
break;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
@@ -984,25 +1007,25 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_ADDRESS;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_DONE);
+ sxstate(data, CONNECT_DONE);
}
infof(data, "SOCKS5 request granted.\n");
*done = TRUE;
- return CURLE_OK; /* Proxy was successful! */
+ return CURLPX_OK; /* Proxy was successful! */
}
#endif /* CURL_DISABLE_PROXY */
diff --git a/Utilities/cmcurl/lib/socks.h b/Utilities/cmcurl/lib/socks.h
index 64a756337..b0c7f9b26 100644
--- a/Utilities/cmcurl/lib/socks.h
+++ b/Utilities/cmcurl/lib/socks.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -35,7 +35,7 @@
*
* This is STUPID BLOCKING behavior
*/
-int Curl_blockread_all(struct connectdata *conn,
+int Curl_blockread_all(struct Curl_easy *data,
curl_socket_t sockfd,
char *buf,
ssize_t buffersize,
@@ -48,31 +48,31 @@ int Curl_SOCKS_getsock(struct connectdata *conn,
* This function logs in to a SOCKS4(a) proxy and sends the specifics to the
* final destination server.
*/
-CURLcode Curl_SOCKS4(const char *proxy_name,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done);
+CURLproxycode Curl_SOCKS4(const char *proxy_name,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done);
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the
* final destination server.
*/
-CURLcode Curl_SOCKS5(const char *proxy_name,
- const char *proxy_password,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done);
+CURLproxycode Curl_SOCKS5(const char *proxy_name,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
* This function handles the SOCKS5 GSS-API negotiation and initialisation
*/
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
- struct connectdata *conn);
+ struct Curl_easy *data);
#endif
#endif /* CURL_DISABLE_PROXY */
diff --git a/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c
index 2e36b9940..3ab786d0b 100644
--- a/Utilities/cmcurl/lib/socks_gssapi.c
+++ b/Utilities/cmcurl/lib/socks_gssapi.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -92,7 +92,7 @@ static int check_gss_err(struct Curl_easy *data,
}
gss_release_buffer(&min_stat, &status_string);
}
- failf(data, "GSS-API error: %s failed:\n%s", function, buf);
+ failf(data, "GSS-API error: %s failed: %s", function, buf);
return 1;
}
@@ -100,9 +100,9 @@ static int check_gss_err(struct Curl_easy *data,
}
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[sockindex];
CURLcode code;
ssize_t actualread;
@@ -201,7 +201,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
us_length = htons((short)gss_send_token.length);
memcpy(socksreq + 2, &us_length, sizeof(short));
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send GSS-API authentication request.");
gss_release_name(&gss_status, &server);
@@ -211,7 +211,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- code = Curl_write_plain(conn, sock, (char *)gss_send_token.value,
+ code = Curl_write_plain(data, sock, (char *)gss_send_token.value,
gss_send_token.length, &written);
if(code || ((ssize_t)gss_send_token.length != written)) {
@@ -240,7 +240,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
* +----+------+-----+----------------+
*/
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API authentication response.");
gss_release_name(&gss_status, &server);
@@ -279,7 +279,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value,
gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
@@ -408,7 +408,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send GSS-API encryption request.");
gss_release_buffer(&gss_status, &gss_w_token);
@@ -418,7 +418,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- code = Curl_write_plain(conn, sock, socksreq, 1, &written);
+ code = Curl_write_plain(data, sock, socksreq, 1, &written);
if(code || ( 1 != written)) {
failf(data, "Failed to send GSS-API encryption type.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -426,7 +426,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
}
else {
- code = Curl_write_plain(conn, sock, (char *)gss_w_token.value,
+ code = Curl_write_plain(data, sock, (char *)gss_w_token.value,
gss_w_token.length, &written);
if(code || ((ssize_t)gss_w_token.length != written)) {
failf(data, "Failed to send GSS-API encryption type.");
@@ -437,7 +437,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_w_token);
}
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API encryption response.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -468,7 +468,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_delete_sec_context(&gss_status, &gss_context, NULL);
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value,
gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
@@ -493,7 +493,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_recv_token);
if(gss_w_token.length != 1) {
- failf(data, "Invalid GSS-API encryption response length (%d).",
+ failf(data, "Invalid GSS-API encryption response length (%zu).",
gss_w_token.length);
gss_release_buffer(&gss_status, &gss_w_token);
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -505,7 +505,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
else {
if(gss_recv_token.length != 1) {
- failf(data, "Invalid GSS-API encryption response length (%d).",
+ failf(data, "Invalid GSS-API encryption response length (%zu).",
gss_recv_token.length);
gss_release_buffer(&gss_status, &gss_recv_token);
gss_delete_sec_context(&gss_status, &gss_context, NULL);
diff --git a/Utilities/cmcurl/lib/socks_sspi.c b/Utilities/cmcurl/lib/socks_sspi.c
index 2f1fd36fa..b343538f0 100644
--- a/Utilities/cmcurl/lib/socks_sspi.c
+++ b/Utilities/cmcurl/lib/socks_sspi.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -43,7 +43,7 @@
/*
* Helper sspi error functions.
*/
-static int check_sspi_err(struct connectdata *conn,
+static int check_sspi_err(struct Curl_easy *data,
SECURITY_STATUS status,
const char *function)
{
@@ -52,7 +52,7 @@ static int check_sspi_err(struct connectdata *conn,
status != SEC_I_COMPLETE_NEEDED &&
status != SEC_I_CONTINUE_NEEDED) {
char buffer[STRERROR_LEN];
- failf(conn->data, "SSPI error: %s failed: %s", function,
+ failf(data, "SSPI error: %s failed: %s", function,
Curl_sspi_strerror(status, buffer, sizeof(buffer)));
return 1;
}
@@ -61,9 +61,9 @@ static int check_sspi_err(struct connectdata *conn,
/* This is the SSPI-using version of this function */
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[sockindex];
CURLcode code;
ssize_t actualread;
@@ -86,7 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
unsigned long qop;
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
- data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
+ data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
const size_t service_length = strlen(service);
/* GSS-API request looks like
@@ -146,7 +146,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
&cred_handle,
&expiry);
- if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) {
+ if(check_sspi_err(data, status, "AcquireCredentialsHandle")) {
failf(data, "Failed to acquire credentials.");
free(service_name);
s_pSecFn->FreeCredentialsHandle(&cred_handle);
@@ -188,7 +188,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
sspi_recv_token.cbBuffer = 0;
}
- if(check_sspi_err(conn, status, "InitializeSecurityContext")) {
+ if(check_sspi_err(data, status, "InitializeSecurityContext")) {
free(service_name);
s_pSecFn->FreeCredentialsHandle(&cred_handle);
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -204,7 +204,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
us_length = htons((short)sspi_send_token.cbBuffer);
memcpy(socksreq + 2, &us_length, sizeof(short));
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI authentication request.");
free(service_name);
@@ -217,7 +217,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
sspi_send_token.cbBuffer, &written);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI authentication token.");
@@ -258,7 +258,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
* +----+------+-----+----------------+
*/
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI authentication response.");
free(service_name);
@@ -298,7 +298,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
s_pSecFn->DeleteSecurityContext(&sspi_context);
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
+ result = Curl_blockread_all(data, sock, (char *)sspi_recv_token.pvBuffer,
sspi_recv_token.cbBuffer, &actualread);
if(result || (actualread != us_length)) {
@@ -321,7 +321,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
SECPKG_CRED_ATTR_NAMES,
&names);
s_pSecFn->FreeCredentialsHandle(&cred_handle);
- if(check_sspi_err(conn, status, "QueryCredentialAttributes")) {
+ if(check_sspi_err(data, status, "QueryCredentialAttributes")) {
s_pSecFn->DeleteSecurityContext(&sspi_context);
s_pSecFn->FreeContextBuffer(names.sUserName);
failf(data, "Failed to determine user name.");
@@ -386,7 +386,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
status = s_pSecFn->QueryContextAttributes(&sspi_context,
SECPKG_ATTR_SIZES,
&sspi_sizes);
- if(check_sspi_err(conn, status, "QueryContextAttributes")) {
+ if(check_sspi_err(data, status, "QueryContextAttributes")) {
s_pSecFn->DeleteSecurityContext(&sspi_context);
failf(data, "Failed to query security context attributes.");
return CURLE_COULDNT_CONNECT;
@@ -423,7 +423,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
KERB_WRAP_NO_ENCRYPT,
&wrap_desc,
0);
- if(check_sspi_err(conn, status, "EncryptMessage")) {
+ if(check_sspi_err(data, status, "EncryptMessage")) {
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
@@ -466,7 +466,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI encryption request.");
if(sspi_send_token.pvBuffer)
@@ -477,7 +477,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 1, &written);
if(code || (1 != written)) {
failf(data, "Failed to send SSPI encryption type.");
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -485,7 +485,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
}
else {
- code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
sspi_send_token.cbBuffer, &written);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI encryption type.");
@@ -498,7 +498,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
}
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI encryption response.");
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -530,7 +530,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
+ result = Curl_blockread_all(data, sock, (char *)sspi_w_token[0].pvBuffer,
sspi_w_token[0].cbBuffer, &actualread);
if(result || (actualread != us_length)) {
@@ -553,7 +553,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
0,
&qop);
- if(check_sspi_err(conn, status, "DecryptMessage")) {
+ if(check_sspi_err(data, status, "DecryptMessage")) {
if(sspi_w_token[0].pvBuffer)
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
if(sspi_w_token[1].pvBuffer)
diff --git a/Utilities/cmcurl/lib/speedcheck.c b/Utilities/cmcurl/lib/speedcheck.c
index 3aeea9111..841d256b4 100644
--- a/Utilities/cmcurl/lib/speedcheck.c
+++ b/Utilities/cmcurl/lib/speedcheck.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -39,6 +39,10 @@ void Curl_speedinit(struct Curl_easy *data)
CURLcode Curl_speedcheck(struct Curl_easy *data,
struct curltime now)
{
+ if(data->req.keepon & KEEP_RECV_PAUSE)
+ /* A paused transfer is not qualified for speed checks */
+ return CURLE_OK;
+
if((data->progress.current_speed >= 0) && data->set.low_speed_time) {
if(data->progress.current_speed < data->set.low_speed_limit) {
if(!data->state.keeps_speed.tv_sec)
diff --git a/Utilities/cmcurl/lib/speedcheck.h b/Utilities/cmcurl/lib/speedcheck.h
index 5c2dc9a22..1d4c7bfef 100644
--- a/Utilities/cmcurl/lib/speedcheck.h
+++ b/Utilities/cmcurl/lib/speedcheck.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/splay.c b/Utilities/cmcurl/lib/splay.c
index 0f5fcd1e8..98baf5d87 100644
--- a/Utilities/cmcurl/lib/splay.c
+++ b/Utilities/cmcurl/lib/splay.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -206,9 +206,9 @@ struct Curl_tree *Curl_splaygetbest(struct curltime i,
*
* @unittest: 1309
*/
-int Curl_splayremovebyaddr(struct Curl_tree *t,
- struct Curl_tree *removenode,
- struct Curl_tree **newroot)
+int Curl_splayremove(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot)
{
static const struct curltime KEY_NOTUSED = {
(time_t)-1, (unsigned int)-1
diff --git a/Utilities/cmcurl/lib/splay.h b/Utilities/cmcurl/lib/splay.h
index 9292f349b..eb9f65f1e 100644
--- a/Utilities/cmcurl/lib/splay.h
+++ b/Utilities/cmcurl/lib/splay.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -40,19 +40,13 @@ struct Curl_tree *Curl_splayinsert(struct curltime key,
struct Curl_tree *t,
struct Curl_tree *newnode);
-#if 0
-struct Curl_tree *Curl_splayremove(struct curltime key,
- struct Curl_tree *t,
- struct Curl_tree **removed);
-#endif
-
struct Curl_tree *Curl_splaygetbest(struct curltime key,
struct Curl_tree *t,
struct Curl_tree **removed);
-int Curl_splayremovebyaddr(struct Curl_tree *t,
- struct Curl_tree *removenode,
- struct Curl_tree **newroot);
+int Curl_splayremove(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot);
#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \
( ((i.tv_sec) > (j.tv_sec)) ? 1 : \
diff --git a/Utilities/cmcurl/lib/strcase.c b/Utilities/cmcurl/lib/strcase.c
index a309e3529..955e3c79e 100644
--- a/Utilities/cmcurl/lib/strcase.c
+++ b/Utilities/cmcurl/lib/strcase.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strcase.h b/Utilities/cmcurl/lib/strcase.h
index cd4c4191a..10dc69881 100644
--- a/Utilities/cmcurl/lib/strcase.h
+++ b/Utilities/cmcurl/lib/strcase.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c
index 7732802b0..9af47ea47 100644
--- a/Utilities/cmcurl/lib/strdup.c
+++ b/Utilities/cmcurl/lib/strdup.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strdup.h b/Utilities/cmcurl/lib/strdup.h
index ae3d5d011..0936956f8 100644
--- a/Utilities/cmcurl/lib/strdup.h
+++ b/Utilities/cmcurl/lib/strdup.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 015e588cf..3862aabd6 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2004 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2004 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -320,6 +320,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_QUIC_CONNECT_ERROR:
return "QUIC connection error";
+ case CURLE_PROXY:
+ return "proxy handshake error";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
@@ -652,34 +655,27 @@ static const char *
get_winapi_error(int err, char *buf, size_t buflen)
{
char *p;
+ wchar_t wbuf[256];
if(!buflen)
return NULL;
*buf = '\0';
-
-#ifdef _WIN32_WCE
- {
- wchar_t wbuf[256];
- wbuf[0] = L'\0';
-
- if(FormatMessage((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
- LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
- size_t written = wcstombs(buf, wbuf, buflen - 1);
- if(written != (size_t)-1)
- buf[written] = '\0';
- else
- *buf = '\0';
- }
- }
-#else
- if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
- LANG_NEUTRAL, buf, (DWORD)buflen, NULL)) {
- *buf = '\0';
+ *wbuf = L'\0';
+
+ /* We return the local codepage version of the error string because if it is
+ output to the user's terminal it will likely be with functions which
+ expect the local codepage (eg fprintf, failf, infof).
+ FormatMessageW -> wcstombs is used for Windows CE compatibility. */
+ if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
+ LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
+ size_t written = wcstombs(buf, wbuf, buflen - 1);
+ if(written != (size_t)-1)
+ buf[written] = '\0';
+ else
+ *buf = '\0';
}
-#endif
/* Truncate multiple lines */
p = strchr(buf, '\n');
@@ -725,7 +721,9 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
if(!buflen)
return NULL;
+#ifndef WIN32
DEBUGASSERT(err >= 0);
+#endif
max = buflen - 1;
*buf = '\0';
@@ -785,7 +783,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
}
#else
{
- char *msg = strerror(err);
+ const char *msg = strerror(err);
if(msg)
strncpy(buf, msg, max);
else
diff --git a/Utilities/cmcurl/lib/strerror.h b/Utilities/cmcurl/lib/strerror.h
index bae8f8974..96a7e27c5 100644
--- a/Utilities/cmcurl/lib/strerror.h
+++ b/Utilities/cmcurl/lib/strerror.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strtok.c b/Utilities/cmcurl/lib/strtok.c
index ba6e0258a..d53e587ab 100644
--- a/Utilities/cmcurl/lib/strtok.c
+++ b/Utilities/cmcurl/lib/strtok.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strtok.h b/Utilities/cmcurl/lib/strtok.h
index e221fa680..831ef0c00 100644
--- a/Utilities/cmcurl/lib/strtok.h
+++ b/Utilities/cmcurl/lib/strtok.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c
index 96e382060..ac87cfc5b 100644
--- a/Utilities/cmcurl/lib/strtoofft.c
+++ b/Utilities/cmcurl/lib/strtoofft.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strtoofft.h b/Utilities/cmcurl/lib/strtoofft.h
index be19cd716..4d22ba36c 100644
--- a/Utilities/cmcurl/lib/strtoofft.h
+++ b/Utilities/cmcurl/lib/strtoofft.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c
index 2e59e032e..2132f43ef 100644
--- a/Utilities/cmcurl/lib/system_win32.c
+++ b/Utilities/cmcurl/lib/system_win32.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -55,12 +55,7 @@ CURLcode Curl_win32_init(long flags)
WSADATA wsaData;
int res;
-#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
-#error IPV6_requires_winsock2
-#endif
-
- wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
-
+ wVersionRequested = MAKEWORD(2, 2);
res = WSAStartup(wVersionRequested, &wsaData);
if(res != 0)
@@ -83,9 +78,9 @@ CURLcode Curl_win32_init(long flags)
return CURLE_FAILED_INIT;
}
/* The Windows Sockets DLL is acceptable. Proceed. */
- #elif defined(USE_LWIPSOCK)
+#elif defined(USE_LWIPSOCK)
lwip_init();
- #endif
+#endif
} /* CURL_GLOBAL_WIN32 */
#ifdef USE_WINDOWS_SSPI
@@ -201,7 +196,7 @@ HMODULE Curl_load_library(LPCTSTR filename)
pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
LoadLibrary(filename);
}
- /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
+ /* Detect if KB2533623 is installed, as LOAD_LIBRARY_SEARCH_SYSTEM32 is only
supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
Server 2008 R2 with this patch or natively on Windows 8 and above */
else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
diff --git a/Utilities/cmcurl/lib/system_win32.h b/Utilities/cmcurl/lib/system_win32.h
index 2547bda95..69e0c812c 100644
--- a/Utilities/cmcurl/lib/system_win32.h
+++ b/Utilities/cmcurl/lib/system_win32.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index c3b58e54c..f96a4cb4c 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -87,14 +87,8 @@
#define printoption(a,b,c,d) Curl_nop_stmt
#endif
-#ifdef USE_WINSOCK
-typedef WSAEVENT (WINAPI *WSOCK2_EVENT)(void);
-typedef FARPROC WSOCK2_FUNC;
-static CURLcode check_wsock2(struct Curl_easy *data);
-#endif
-
static
-CURLcode telrcv(struct connectdata *,
+CURLcode telrcv(struct Curl_easy *data,
const unsigned char *inbuf, /* Data received from socket */
ssize_t count); /* Number of bytes received */
@@ -104,23 +98,23 @@ static void printoption(struct Curl_easy *data,
int cmd, int option);
#endif
-static void negotiate(struct connectdata *);
-static void send_negotiation(struct connectdata *, int cmd, int option);
-static void set_local_option(struct connectdata *conn,
+static void negotiate(struct Curl_easy *data);
+static void send_negotiation(struct Curl_easy *data, int cmd, int option);
+static void set_local_option(struct Curl_easy *data,
int option, int newstate);
-static void set_remote_option(struct connectdata *conn,
+static void set_remote_option(struct Curl_easy *data,
int option, int newstate);
static void printsub(struct Curl_easy *data,
int direction, unsigned char *pointer,
size_t length);
-static void suboption(struct connectdata *);
-static void sendsuboption(struct connectdata *conn, int option);
+static void suboption(struct Curl_easy *data);
+static void sendsuboption(struct Curl_easy *data, int option);
-static CURLcode telnet_do(struct connectdata *conn, bool *done);
-static CURLcode telnet_done(struct connectdata *conn,
+static CURLcode telnet_do(struct Curl_easy *data, bool *done);
+static CURLcode telnet_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode send_telnet_data(struct connectdata *conn,
+static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread);
/* For negotiation compliant to RFC 1143 */
@@ -162,13 +156,12 @@ struct TELNET {
char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */
unsigned short subopt_wsx; /* Set with suboption NAWS */
unsigned short subopt_wsy; /* Set with suboption NAWS */
+ TelnetReceive telrcv_state;
struct curl_slist *telnet_vars; /* Environment variables */
/* suboptions */
unsigned char subbuffer[SUBBUFSIZE];
unsigned char *subpointer, *subend; /* buffer for sub-options */
-
- TelnetReceive telrcv_state;
};
@@ -194,52 +187,13 @@ const struct Curl_handler Curl_handler_telnet = {
ZERO_NULL, /* connection_check */
PORT_TELNET, /* defport */
CURLPROTO_TELNET, /* protocol */
+ CURLPROTO_TELNET, /* family */
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
-#ifdef USE_WINSOCK
-static CURLcode
-check_wsock2(struct Curl_easy *data)
-{
- int err;
- WORD wVersionRequested;
- WSADATA wsaData;
-
- DEBUGASSERT(data);
-
- /* telnet requires at least WinSock 2.0 so ask for it. */
- wVersionRequested = MAKEWORD(2, 0);
-
- err = WSAStartup(wVersionRequested, &wsaData);
-
- /* We must've called this once already, so this call */
- /* should always succeed. But, just in case... */
- if(err != 0) {
- failf(data,"WSAStartup failed (%d)",err);
- return CURLE_FAILED_INIT;
- }
-
- /* We have to have a WSACleanup call for every successful */
- /* WSAStartup call. */
- WSACleanup();
-
- /* Check that our version is supported */
- if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
- HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
- /* Our version isn't supported */
- failf(data, "insufficient winsock version to support "
- "telnet");
- return CURLE_FAILED_INIT;
- }
-
- /* Our version is supported */
- return CURLE_OK;
-}
-#endif
-
static
-CURLcode init_telnet(struct connectdata *conn)
+CURLcode init_telnet(struct Curl_easy *data)
{
struct TELNET *tn;
@@ -247,7 +201,7 @@ CURLcode init_telnet(struct connectdata *conn)
if(!tn)
return CURLE_OUT_OF_MEMORY;
- conn->data->req.protop = tn; /* make us known */
+ data->req.p.telnet = tn; /* make us known */
tn->telrcv_state = CURL_TS_DATA;
@@ -259,7 +213,7 @@ CURLcode init_telnet(struct connectdata *conn)
tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES;
/* To be compliant with previous releases of libcurl
- we enable this option by default. This behaviour
+ we enable this option by default. This behavior
can be changed thanks to the "BINARY" option in
CURLOPT_TELNETOPTIONS
*/
@@ -289,20 +243,20 @@ CURLcode init_telnet(struct connectdata *conn)
return CURLE_OK;
}
-static void negotiate(struct connectdata *conn)
+static void negotiate(struct Curl_easy *data)
{
int i;
- struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
for(i = 0; i < CURL_NTELOPTS; i++) {
if(i == CURL_TELOPT_ECHO)
continue;
if(tn->us_preferred[i] == CURL_YES)
- set_local_option(conn, i, CURL_YES);
+ set_local_option(data, i, CURL_YES);
if(tn->him_preferred[i] == CURL_YES)
- set_remote_option(conn, i, CURL_YES);
+ set_remote_option(data, i, CURL_YES);
}
}
@@ -343,34 +297,34 @@ static void printoption(struct Curl_easy *data,
}
#endif
-static void send_negotiation(struct connectdata *conn, int cmd, int option)
+static void send_negotiation(struct Curl_easy *data, int cmd, int option)
{
- unsigned char buf[3];
- ssize_t bytes_written;
- struct Curl_easy *data = conn->data;
+ unsigned char buf[3];
+ ssize_t bytes_written;
+ struct connectdata *conn = data->conn;
- buf[0] = CURL_IAC;
- buf[1] = (unsigned char)cmd;
- buf[2] = (unsigned char)option;
+ buf[0] = CURL_IAC;
+ buf[1] = (unsigned char)cmd;
+ buf[2] = (unsigned char)option;
- bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
- if(bytes_written < 0) {
- int err = SOCKERRNO;
- failf(data,"Sending data failed (%d)",err);
- }
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
+ if(bytes_written < 0) {
+ int err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
- printoption(conn->data, "SENT", cmd, option);
+ printoption(data, "SENT", cmd, option);
}
static
-void set_remote_option(struct connectdata *conn, int option, int newstate)
+void set_remote_option(struct Curl_easy *data, int option, int newstate)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->him[option]) {
case CURL_NO:
tn->him[option] = CURL_WANTYES;
- send_negotiation(conn, CURL_DO, option);
+ send_negotiation(data, CURL_DO, option);
break;
case CURL_YES:
@@ -409,7 +363,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
case CURL_YES:
tn->him[option] = CURL_WANTNO;
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
case CURL_WANTNO:
@@ -437,17 +391,17 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
}
static
-void rec_will(struct connectdata *conn, int option)
+void rec_will(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
if(tn->him_preferred[option] == CURL_YES) {
tn->him[option] = CURL_YES;
- send_negotiation(conn, CURL_DO, option);
+ send_negotiation(data, CURL_DO, option);
}
else
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
@@ -477,7 +431,7 @@ void rec_will(struct connectdata *conn, int option)
case CURL_OPPOSITE:
tn->him[option] = CURL_WANTNO;
tn->himq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
}
break;
@@ -485,9 +439,9 @@ void rec_will(struct connectdata *conn, int option)
}
static
-void rec_wont(struct connectdata *conn, int option)
+void rec_wont(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
/* Already disabled */
@@ -495,7 +449,7 @@ void rec_wont(struct connectdata *conn, int option)
case CURL_YES:
tn->him[option] = CURL_NO;
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
case CURL_WANTNO:
@@ -507,7 +461,7 @@ void rec_wont(struct connectdata *conn, int option)
case CURL_OPPOSITE:
tn->him[option] = CURL_WANTYES;
tn->himq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_DO, option);
+ send_negotiation(data, CURL_DO, option);
break;
}
break;
@@ -527,14 +481,14 @@ void rec_wont(struct connectdata *conn, int option)
}
static void
-set_local_option(struct connectdata *conn, int option, int newstate)
+set_local_option(struct Curl_easy *data, int option, int newstate)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->us[option]) {
case CURL_NO:
tn->us[option] = CURL_WANTYES;
- send_negotiation(conn, CURL_WILL, option);
+ send_negotiation(data, CURL_WILL, option);
break;
case CURL_YES:
@@ -573,7 +527,7 @@ set_local_option(struct connectdata *conn, int option, int newstate)
case CURL_YES:
tn->us[option] = CURL_WANTNO;
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
case CURL_WANTNO:
@@ -601,26 +555,26 @@ set_local_option(struct connectdata *conn, int option, int newstate)
}
static
-void rec_do(struct connectdata *conn, int option)
+void rec_do(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
if(tn->us_preferred[option] == CURL_YES) {
tn->us[option] = CURL_YES;
- send_negotiation(conn, CURL_WILL, option);
+ send_negotiation(data, CURL_WILL, option);
if(tn->subnegotiation[option] == CURL_YES)
/* transmission of data option */
- sendsuboption(conn, option);
+ sendsuboption(data, option);
}
else if(tn->subnegotiation[option] == CURL_YES) {
/* send information to achieve this option*/
tn->us[option] = CURL_YES;
- send_negotiation(conn, CURL_WILL, option);
- sendsuboption(conn, option);
+ send_negotiation(data, CURL_WILL, option);
+ sendsuboption(data, option);
}
else
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
case CURL_YES:
@@ -647,13 +601,13 @@ void rec_do(struct connectdata *conn, int option)
tn->us[option] = CURL_YES;
if(tn->subnegotiation[option] == CURL_YES) {
/* transmission of data option */
- sendsuboption(conn, option);
+ sendsuboption(data, option);
}
break;
case CURL_OPPOSITE:
tn->us[option] = CURL_WANTNO;
tn->himq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
}
break;
@@ -661,9 +615,9 @@ void rec_do(struct connectdata *conn, int option)
}
static
-void rec_dont(struct connectdata *conn, int option)
+void rec_dont(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
/* Already disabled */
@@ -671,7 +625,7 @@ void rec_dont(struct connectdata *conn, int option)
case CURL_YES:
tn->us[option] = CURL_NO;
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
case CURL_WANTNO:
@@ -683,7 +637,7 @@ void rec_dont(struct connectdata *conn, int option)
case CURL_OPPOSITE:
tn->us[option] = CURL_WANTYES;
tn->usq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_WILL, option);
+ send_negotiation(data, CURL_WILL, option);
break;
}
break;
@@ -815,14 +769,14 @@ static void printsub(struct Curl_easy *data,
}
}
-static CURLcode check_telnet_options(struct connectdata *conn)
+static CURLcode check_telnet_options(struct Curl_easy *data)
{
struct curl_slist *head;
struct curl_slist *beg;
char option_keyword[128] = "";
char option_arg[256] = "";
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
int binary_option;
@@ -919,7 +873,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
* side.
*/
-static void suboption(struct connectdata *conn)
+static void suboption(struct Curl_easy *data)
{
struct curl_slist *v;
unsigned char temp[2048];
@@ -928,8 +882,8 @@ static void suboption(struct connectdata *conn)
int err;
char varname[128] = "";
char varval[128] = "";
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
+ struct connectdata *conn = data->conn;
printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2);
switch(CURL_SB_GET(tn)) {
@@ -996,15 +950,14 @@ static void suboption(struct connectdata *conn)
* Send suboption information to the server side.
*/
-static void sendsuboption(struct connectdata *conn, int option)
+static void sendsuboption(struct Curl_easy *data, int option)
{
ssize_t bytes_written;
int err;
unsigned short x, y;
unsigned char *uc1, *uc2;
-
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
+ struct connectdata *conn = data->conn;
switch(option) {
case CURL_TELOPT_NAWS:
@@ -1040,7 +993,7 @@ static void sendsuboption(struct connectdata *conn, int option)
}
/* ... then the window size with the send_telnet_data() function
to deal with 0xFF cases ... */
- send_telnet_data(conn, (char *)tn->subbuffer + 3, 4);
+ send_telnet_data(data, (char *)tn->subbuffer + 3, 4);
/* ... and the footer */
bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2);
if(bytes_written < 0) {
@@ -1053,7 +1006,7 @@ static void sendsuboption(struct connectdata *conn, int option)
static
-CURLcode telrcv(struct connectdata *conn,
+CURLcode telrcv(struct Curl_easy *data,
const unsigned char *inbuf, /* Data received from socket */
ssize_t count) /* Number of bytes received */
{
@@ -1061,12 +1014,11 @@ CURLcode telrcv(struct connectdata *conn,
CURLcode result;
int in = 0;
int startwrite = -1;
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
#define startskipping() \
if(startwrite >= 0) { \
- result = Curl_client_write(conn, \
+ result = Curl_client_write(data, \
CLIENTWRITE_BODY, \
(char *)&inbuf[startwrite], \
in-startwrite); \
@@ -1142,28 +1094,28 @@ CURLcode telrcv(struct connectdata *conn,
case CURL_TS_WILL:
printoption(data, "RCVD", CURL_WILL, c);
tn->please_negotiate = 1;
- rec_will(conn, c);
+ rec_will(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_WONT:
printoption(data, "RCVD", CURL_WONT, c);
tn->please_negotiate = 1;
- rec_wont(conn, c);
+ rec_wont(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DO:
printoption(data, "RCVD", CURL_DO, c);
tn->please_negotiate = 1;
- rec_do(conn, c);
+ rec_do(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DONT:
printoption(data, "RCVD", CURL_DONT, c);
tn->please_negotiate = 1;
- rec_dont(conn, c);
+ rec_dont(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
@@ -1192,7 +1144,7 @@ CURLcode telrcv(struct connectdata *conn,
CURL_SB_TERM(tn);
printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
- suboption(conn); /* handle sub-option */
+ suboption(data); /* handle sub-option */
tn->telrcv_state = CURL_TS_IAC;
goto process_iac;
}
@@ -1204,7 +1156,7 @@ CURLcode telrcv(struct connectdata *conn,
CURL_SB_ACCUM(tn, CURL_SE);
tn->subpointer -= 2;
CURL_SB_TERM(tn);
- suboption(conn); /* handle sub-option */
+ suboption(data); /* handle sub-option */
tn->telrcv_state = CURL_TS_DATA;
}
break;
@@ -1216,13 +1168,14 @@ CURLcode telrcv(struct connectdata *conn,
}
/* Escape and send a telnet data block */
-static CURLcode send_telnet_data(struct connectdata *conn,
+static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread)
{
ssize_t escapes, i, outlen;
unsigned char *outbuf = NULL;
CURLcode result = CURLE_OK;
ssize_t bytes_written, total_written;
+ struct connectdata *conn = data->conn;
/* Determine size of new buffer after escaping */
escapes = 0;
@@ -1261,7 +1214,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
break;
default: /* write! */
bytes_written = 0;
- result = Curl_write(conn, conn->sock[FIRSTSOCKET],
+ result = Curl_write(data, conn->sock[FIRSTSOCKET],
outbuf + total_written,
outlen - total_written,
&bytes_written);
@@ -1277,10 +1230,10 @@ static CURLcode send_telnet_data(struct connectdata *conn,
return result;
}
-static CURLcode telnet_done(struct connectdata *conn,
- CURLcode status, bool premature)
+static CURLcode telnet_done(struct Curl_easy *data,
+ CURLcode status, bool premature)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
(void)status; /* unused */
(void)premature; /* not used */
@@ -1290,22 +1243,17 @@ static CURLcode telnet_done(struct connectdata *conn,
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
- Curl_safefree(conn->data->req.protop);
+ Curl_safefree(data->req.p.telnet);
return CURLE_OK;
}
-static CURLcode telnet_do(struct connectdata *conn, bool *done)
+static CURLcode telnet_do(struct Curl_easy *data, bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef USE_WINSOCK
- HMODULE wsock2;
- WSOCK2_FUNC close_event_func;
- WSOCK2_EVENT create_event_func;
- WSOCK2_FUNC event_select_func;
- WSOCK2_FUNC enum_netevents_func;
WSAEVENT event_handle;
WSANETWORKEVENTS events;
HANDLE stdin_handle;
@@ -1329,86 +1277,32 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
*done = TRUE; /* unconditionally */
- result = init_telnet(conn);
+ result = init_telnet(data);
if(result)
return result;
- tn = (struct TELNET *)data->req.protop;
+ tn = data->req.p.telnet;
- result = check_telnet_options(conn);
+ result = check_telnet_options(data);
if(result)
return result;
#ifdef USE_WINSOCK
- /*
- ** This functionality only works with WinSock >= 2.0. So,
- ** make sure we have it.
- */
- result = check_wsock2(data);
- if(result)
- return result;
-
- /* OK, so we have WinSock 2.0. We need to dynamically */
- /* load ws2_32.dll and get the function pointers we need. */
- wsock2 = Curl_load_library(TEXT("WS2_32.DLL"));
- if(wsock2 == NULL) {
- failf(data, "failed to load WS2_32.DLL (%u)", GetLastError());
- return CURLE_FAILED_INIT;
- }
-
- /* Grab a pointer to WSACreateEvent */
- create_event_func =
- CURLX_FUNCTION_CAST(WSOCK2_EVENT,
- (GetProcAddress(wsock2, "WSACreateEvent")));
- if(create_event_func == NULL) {
- failf(data, "failed to find WSACreateEvent function (%u)", GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
- /* And WSACloseEvent */
- close_event_func = GetProcAddress(wsock2, "WSACloseEvent");
- if(close_event_func == NULL) {
- failf(data, "failed to find WSACloseEvent function (%u)", GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
- /* And WSAEventSelect */
- event_select_func = GetProcAddress(wsock2, "WSAEventSelect");
- if(event_select_func == NULL) {
- failf(data, "failed to find WSAEventSelect function (%u)", GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
- /* And WSAEnumNetworkEvents */
- enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents");
- if(enum_netevents_func == NULL) {
- failf(data, "failed to find WSAEnumNetworkEvents function (%u)",
- GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
/* We want to wait for both stdin and the socket. Since
** the select() function in winsock only works on sockets
** we have to use the WaitForMultipleObjects() call.
*/
/* First, create a sockets event object */
- event_handle = (WSAEVENT)create_event_func();
+ event_handle = WSACreateEvent();
if(event_handle == WSA_INVALID_EVENT) {
failf(data, "WSACreateEvent failed (%d)", SOCKERRNO);
- FreeLibrary(wsock2);
return CURLE_FAILED_INIT;
}
/* Tell winsock what events we want to listen to */
- if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) ==
- SOCKET_ERROR) {
- close_event_func(event_handle);
- FreeLibrary(wsock2);
+ if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
+ WSACloseEvent(event_handle);
return CURLE_OK;
}
@@ -1439,6 +1333,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
DWORD waitret = WaitForMultipleObjects(obj_count, objs,
FALSE, wait_timeout);
switch(waitret) {
+
case WAIT_TIMEOUT:
{
for(;;) {
@@ -1481,7 +1376,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
}
- result = send_telnet_data(conn, buf, readfile_read);
+ result = send_telnet_data(data, buf, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1499,7 +1394,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break;
}
- result = send_telnet_data(conn, buf, readfile_read);
+ result = send_telnet_data(data, buf, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1508,9 +1403,9 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break;
case WAIT_OBJECT_0:
-
+ {
events.lNetworkEvents = 0;
- if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
+ if(WSAEnumNetworkEvents(sockfd, event_handle, &events) == SOCKET_ERROR) {
err = SOCKERRNO;
if(err != EINPROGRESS) {
infof(data, "WSAEnumNetworkEvents failed (%d)", err);
@@ -1521,7 +1416,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
if(events.lNetworkEvents & FD_READ) {
/* read data from network */
- result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
+ result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1537,7 +1432,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break;
}
- result = telrcv(conn, (unsigned char *) buf, nread);
+ result = telrcv(data, (unsigned char *) buf, nread);
if(result) {
keepon = FALSE;
break;
@@ -1547,14 +1442,15 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
otherwise don't. We don't want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(conn);
+ negotiate(data);
tn->already_negotiated = 1;
}
}
if(events.lNetworkEvents & FD_CLOSE) {
keepon = FALSE;
}
- break;
+ }
+ break;
}
@@ -1569,19 +1465,9 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
/* We called WSACreateEvent, so call WSACloseEvent */
- if(!close_event_func(event_handle)) {
+ if(!WSACloseEvent(event_handle)) {
infof(data, "WSACloseEvent failed (%d)", SOCKERRNO);
}
-
- /* "Forget" pointers into the library we're about to free */
- create_event_func = NULL;
- close_event_func = NULL;
- event_select_func = NULL;
- enum_netevents_func = NULL;
-
- /* We called LoadLibrary, so call FreeLibrary */
- if(!FreeLibrary(wsock2))
- infof(data, "FreeLibrary(wsock2) failed (%u)", GetLastError());
#else
pfd[0].fd = sockfd;
pfd[0].events = POLLIN;
@@ -1610,7 +1496,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
- result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
+ result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1628,7 +1514,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
total_dl += nread;
Curl_pgrsSetDownloadCounter(data, total_dl);
- result = telrcv(conn, (unsigned char *)buf, nread);
+ result = telrcv(data, (unsigned char *)buf, nread);
if(result) {
keepon = FALSE;
break;
@@ -1638,7 +1524,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
otherwise don't. We don't want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(conn);
+ negotiate(data);
tn->already_negotiated = 1;
}
}
@@ -1662,7 +1548,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
if(nread > 0) {
- result = send_telnet_data(conn, buf, nread);
+ result = send_telnet_data(data, buf, nread);
if(result) {
keepon = FALSE;
break;
@@ -1685,7 +1571,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
}
- if(Curl_pgrsUpdate(conn)) {
+ if(Curl_pgrsUpdate(data)) {
result = CURLE_ABORTED_BY_CALLBACK;
break;
}
diff --git a/Utilities/cmcurl/lib/telnet.h b/Utilities/cmcurl/lib/telnet.h
index 431427f39..1427473a9 100644
--- a/Utilities/cmcurl/lib/telnet.h
+++ b/Utilities/cmcurl/lib/telnet.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 378d95608..3f1d1b51b 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -124,7 +124,7 @@ struct tftp_state_data {
tftp_mode_t mode;
tftp_error_t error;
tftp_event_t event;
- struct connectdata *conn;
+ struct Curl_easy *data;
curl_socket_t sockfd;
int retries;
int retry_time;
@@ -132,7 +132,6 @@ struct tftp_state_data {
time_t start_time;
time_t max_time;
time_t rx_time;
- unsigned short block;
struct Curl_sockaddr_storage local_addr;
struct Curl_sockaddr_storage remote_addr;
curl_socklen_t remote_addrlen;
@@ -140,6 +139,7 @@ struct tftp_state_data {
int sbytes;
int blksize;
int requested_blksize;
+ unsigned short block;
struct tftp_packet rpacket;
struct tftp_packet spacket;
};
@@ -148,16 +148,19 @@ struct tftp_state_data {
/* Forward declarations */
static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event);
-static CURLcode tftp_connect(struct connectdata *conn, bool *done);
-static CURLcode tftp_disconnect(struct connectdata *conn,
+static CURLcode tftp_connect(struct Curl_easy *data, bool *done);
+static CURLcode tftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
-static CURLcode tftp_do(struct connectdata *conn, bool *done);
-static CURLcode tftp_done(struct connectdata *conn,
+static CURLcode tftp_do(struct Curl_easy *data, bool *done);
+static CURLcode tftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode tftp_setup_connection(struct connectdata *conn);
-static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done);
-static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done);
-static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks);
+static CURLcode tftp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done);
+static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done);
+static int tftp_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
static CURLcode tftp_translate_code(tftp_error_t error);
@@ -183,6 +186,7 @@ const struct Curl_handler Curl_handler_tftp = {
ZERO_NULL, /* connection_check */
PORT_TFTP, /* defport */
CURLPROTO_TFTP, /* protocol */
+ CURLPROTO_TFTP, /* family */
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
@@ -205,11 +209,11 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
time(&state->start_time);
/* Compute drop-dead time */
- timeout_ms = Curl_timeleft(state->conn->data, NULL, start);
+ timeout_ms = Curl_timeleft(state->data, NULL, start);
if(timeout_ms < 0) {
/* time-out, bail out, go home */
- failf(state->conn->data, "Connection time-out");
+ failf(state->data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT;
}
@@ -260,7 +264,7 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
if(state->retry_time<1)
state->retry_time = 1;
- infof(state->conn->data,
+ 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);
@@ -302,7 +306,7 @@ static unsigned short getrpacketblock(const struct tftp_packet *packet)
return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
}
-static size_t Curl_strnlen(const char *string, size_t maxlen)
+static size_t tftp_strnlen(const char *string, size_t maxlen)
{
const char *end = memchr(string, '\0', maxlen);
return end ? (size_t) (end - string) : maxlen;
@@ -313,14 +317,14 @@ static const char *tftp_option_get(const char *buf, size_t len,
{
size_t loc;
- loc = Curl_strnlen(buf, len);
+ loc = tftp_strnlen(buf, len);
loc++; /* NULL term */
if(loc >= len)
return NULL;
*option = buf;
- loc += Curl_strnlen(buf + loc, len-loc);
+ loc += tftp_strnlen(buf + loc, len-loc);
loc++; /* NULL term */
if(loc > len)
@@ -334,7 +338,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
const char *ptr, int len)
{
const char *tmp = ptr;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
/* if OACK doesn't contain blksize option, the default (512) must be used */
state->blksize = TFTP_BLKSIZE_DEFAULT;
@@ -418,7 +422,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
{
CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
infof(data, "%s\n", "Connected for transmit");
#endif
@@ -434,7 +438,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
{
CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
infof(data, "%s\n", "Connected for receive");
#endif
@@ -452,7 +456,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
ssize_t senddata;
const char *mode = "octet";
char *filename;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
CURLcode result = CURLE_OK;
/* Set ascii mode if -B flag was used */
@@ -474,7 +478,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
if(data->set.upload) {
/* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
- state->conn->data->req.upload_fromhere =
+ state->data->req.upload_fromhere =
(char *)state->spacket.data + 4;
if(data->state.infilesize != -1)
Curl_pgrsSetUploadSize(data, data->state.infilesize);
@@ -486,13 +490,13 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
/* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path
string. */
- result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
+ result = Curl_urldecode(data, &state->data->state.up.path[1], 0,
&filename, NULL, REJECT_ZERO);
if(result)
return result;
if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
- failf(data, "TFTP file name too long\n");
+ failf(data, "TFTP file name too long");
free(filename);
return CURLE_TFTP_ILLEGAL; /* too long file name field */
}
@@ -550,8 +554,8 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
not have a size_t argument, like older unixes that want an 'int' */
senddata = sendto(state->sockfd, (void *)state->spacket.data,
(SEND_TYPE_ARG3)sbytes, 0,
- state->conn->ip_addr->ai_addr,
- state->conn->ip_addr->ai_addrlen);
+ data->conn->ip_addr->ai_addr,
+ data->conn->ip_addr->ai_addrlen);
if(senddata != (ssize_t)sbytes) {
char buffer[STRERROR_LEN];
failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
@@ -581,7 +585,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
break;
default:
- failf(state->conn->data, "tftp_send_first: internal error");
+ failf(state->data, "tftp_send_first: internal error");
break;
}
@@ -604,7 +608,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
{
ssize_t sbytes;
int rblock;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
char buffer[STRERROR_LEN];
switch(event) {
@@ -724,7 +728,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
**********************************************************/
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
{
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
ssize_t sbytes;
CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
@@ -793,14 +797,13 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
* data block.
* */
state->sbytes = 0;
- state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4;
+ state->data->req.upload_fromhere = (char *)state->spacket.data + 4;
do {
- result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
- &cb);
+ result = Curl_fillreadbuffer(data, state->blksize - state->sbytes, &cb);
if(result)
return result;
state->sbytes += (int)cb;
- state->conn->data->req.upload_fromhere += cb;
+ state->data->req.upload_fromhere += cb;
} while(state->sbytes < state->blksize && cb != 0);
sbytes = sendto(state->sockfd, (void *) state->spacket.data,
@@ -926,7 +929,7 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
tftp_event_t event)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
switch(state->state) {
case TFTP_STATE_START:
@@ -961,9 +964,11 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
* The disconnect callback
*
**********************************************************/
-static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode tftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
struct tftp_state_data *state = conn->proto.tftpc;
+ (void) data;
(void) dead_connection;
/* done, free dynamically allocated pkt buffers */
@@ -983,11 +988,12 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
* The connect callback
*
**********************************************************/
-static CURLcode tftp_connect(struct connectdata *conn, bool *done)
+static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
{
struct tftp_state_data *state;
int blksize;
int need_blksize;
+ struct connectdata *conn = data->conn;
blksize = TFTP_BLKSIZE_DEFAULT;
@@ -996,8 +1002,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
return CURLE_OUT_OF_MEMORY;
/* alloc pkt buffers based on specified blksize */
- if(conn->data->set.tftp_blksize) {
- blksize = (int)conn->data->set.tftp_blksize;
+ if(data->set.tftp_blksize) {
+ blksize = (int)data->set.tftp_blksize;
if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
return CURLE_TFTP_ILLEGAL;
}
@@ -1025,8 +1031,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
* little gain for UDP */
connclose(conn, "TFTP");
- state->conn = conn;
- state->sockfd = state->conn->sock[FIRSTSOCKET];
+ state->data = data;
+ state->sockfd = conn->sock[FIRSTSOCKET];
state->state = TFTP_STATE_START;
state->error = TFTP_ERR_NONE;
state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */
@@ -1055,14 +1061,14 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
conn->ip_addr->ai_addrlen);
if(rc) {
char buffer[STRERROR_LEN];
- failf(conn->data, "bind() failed; %s",
+ failf(data, "bind() failed; %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
return CURLE_COULDNT_CONNECT;
}
conn->bits.bound = TRUE;
}
- Curl_pgrsStartNow(conn->data);
+ Curl_pgrsStartNow(data);
*done = TRUE;
@@ -1076,16 +1082,17 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
* The done callback
*
**********************************************************/
-static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
+static CURLcode tftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
(void)status; /* unused */
(void)premature; /* not used */
- if(Curl_pgrsDone(conn))
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
/* If we have encountered an error */
@@ -1102,8 +1109,10 @@ static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
* The getsock callback
*
**********************************************************/
-static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int tftp_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0);
}
@@ -1115,12 +1124,12 @@ static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks)
* Called once select fires and data is ready on the socket
*
**********************************************************/
-static CURLcode tftp_receive_packet(struct connectdata *conn)
+static CURLcode tftp_receive_packet(struct Curl_easy *data)
{
struct Curl_sockaddr_storage fromaddr;
curl_socklen_t fromlen;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
struct SingleRequest *k = &data->req;
@@ -1153,7 +1162,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
/* Don't pass to the client empty or retransmitted packets */
if(state->rbytes > 4 &&
(NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)state->rpacket.data + 4,
state->rbytes-4);
if(result) {
@@ -1170,7 +1179,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
char *str = (char *)state->rpacket.data + 4;
size_t strn = state->rbytes - 4;
state->error = (tftp_error_t)error;
- if(Curl_strnlen(str, strn) < strn)
+ if(tftp_strnlen(str, strn) < strn)
infof(data, "TFTP error: %s\n", str);
break;
}
@@ -1191,7 +1200,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
}
/* Update the progress meter */
- if(Curl_pgrsUpdate(conn)) {
+ if(Curl_pgrsUpdate(data)) {
tftp_state_machine(state, TFTP_EVENT_ERROR);
return CURLE_ABORTED_BY_CALLBACK;
}
@@ -1206,9 +1215,10 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
* Check if timeouts have been reached
*
**********************************************************/
-static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
+static long 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;
if(event)
@@ -1216,7 +1226,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
time(&current);
if(current > state->max_time) {
- DEBUGF(infof(conn->data, "timeout: %ld > %ld\n",
+ DEBUGF(infof(data, "timeout: %ld > %ld\n",
(long)current, (long)state->max_time));
state->error = TFTP_ERR_TIMEOUT;
state->state = TFTP_STATE_FIN;
@@ -1241,13 +1251,13 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
* Handle single RX socket event and return
*
**********************************************************/
-static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
{
- tftp_event_t event;
- CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ tftp_event_t event;
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
- long timeout_ms = tftp_state_timeout(conn, &event);
+ long timeout_ms = tftp_state_timeout(data, &event);
*done = FALSE;
@@ -1276,7 +1286,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
state->event = TFTP_EVENT_ERROR;
}
else if(rc != 0) {
- result = tftp_receive_packet(conn);
+ result = tftp_receive_packet(data);
if(result)
return result;
result = tftp_state_machine(state, state->event);
@@ -1300,22 +1310,22 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
* Called from multi.c while DOing
*
**********************************************************/
-static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done)
{
CURLcode result;
- result = tftp_multi_statemach(conn, dophase_done);
+ result = tftp_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
else if(!result) {
/* The multi code doesn't have this logic for the DOING state so we
provide it for TFTP since it may do the entire transfer in this
state. */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(conn->data, Curl_now());
+ result = Curl_speedcheck(data, Curl_now());
}
return result;
}
@@ -1327,9 +1337,10 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
* Entry point for transfer from tftp_do, sarts state mach
*
**********************************************************/
-static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
+static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = CURLE_OK;
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
*dophase_done = FALSE;
@@ -1339,10 +1350,10 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
if((state->state == TFTP_STATE_FIN) || result)
return result;
- tftp_multi_statemach(conn, dophase_done);
+ tftp_multi_statemach(data, dophase_done);
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1358,15 +1369,16 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
*
**********************************************************/
-static CURLcode tftp_do(struct connectdata *conn, bool *done)
+static CURLcode tftp_do(struct Curl_easy *data, bool *done)
{
struct tftp_state_data *state;
CURLcode result;
+ struct connectdata *conn = data->conn;
*done = FALSE;
if(!conn->proto.tftpc) {
- result = tftp_connect(conn, done);
+ result = tftp_connect(data, done);
if(result)
return result;
}
@@ -1375,7 +1387,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
if(!state)
return CURLE_TFTP_ILLEGAL;
- result = tftp_perform(conn, done);
+ result = tftp_perform(data, done);
/* If tftp_perform() returned an error, use that for return code. If it
was OK, see if tftp_translate_code() has an error. */
@@ -1386,9 +1398,9 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
return result;
}
-static CURLcode tftp_setup_connection(struct connectdata *conn)
+static CURLcode tftp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
char *type;
conn->transport = TRNSPRT_UDP;
diff --git a/Utilities/cmcurl/lib/tftp.h b/Utilities/cmcurl/lib/tftp.h
index 33348300f..4b5bea275 100644
--- a/Utilities/cmcurl/lib/tftp.h
+++ b/Utilities/cmcurl/lib/tftp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index e761966a1..8523dad40 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h
index 53e063607..685e72961 100644
--- a/Utilities/cmcurl/lib/timeval.h
+++ b/Utilities/cmcurl/lib/timeval.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index a07c7af8c..2f29b29d8 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -78,6 +78,7 @@
#include "mime.h"
#include "strcase.h"
#include "urlapi-int.h"
+#include "hsts.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -92,12 +93,11 @@
*
* Returns a pointer to the first matching header or NULL if none matched.
*/
-char *Curl_checkheaders(const struct connectdata *conn,
+char *Curl_checkheaders(const struct Curl_easy *data,
const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
- struct Curl_easy *data = conn->data;
for(head = data->set.headers; head; head = head->next) {
if(strncasecompare(head->data, thisheader, thislen) &&
@@ -124,8 +124,8 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
* This function will be called to loop through the trailers buffer
* until no more data is available for sending.
*/
-static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
- void *raw)
+static size_t trailers_read(char *buffer, size_t size, size_t nitems,
+ void *raw)
{
struct Curl_easy *data = (struct Curl_easy *)raw;
struct dynbuf *trailers_buf = &data->state.trailers_buf;
@@ -141,7 +141,7 @@ static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
return to_copy;
}
-static size_t Curl_trailers_left(void *raw)
+static size_t trailers_left(void *raw)
{
struct Curl_easy *data = (struct Curl_easy *)raw;
struct dynbuf *trailers_buf = &data->state.trailers_buf;
@@ -153,10 +153,9 @@ static size_t Curl_trailers_left(void *raw)
* This function will call the read callback to fill our buffer with data
* to upload.
*/
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
size_t *nreadp)
{
- struct Curl_easy *data = conn->data;
size_t buffersize = bytes;
size_t nread;
@@ -165,9 +164,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
#ifdef CURL_DOES_CONVERSIONS
bool sending_http_headers = FALSE;
+ struct connectdata *conn = data->conn;
if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
- const struct HTTP *http = data->req.protop;
+ const struct HTTP *http = data->req.p.http;
if(http->sending == HTTPSEND_REQUEST)
/* We're sending the HTTP request headers, not the data.
@@ -230,7 +230,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
simply return to the previous point in the state machine as if
nothing happened.
*/
- readfunc = Curl_trailers_read;
+ readfunc = trailers_read;
extra_data = (void *)data;
}
else
@@ -253,7 +253,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
if(nread == CURL_READFUNC_PAUSE) {
struct SingleRequest *k = &data->req;
- if(conn->handler->flags & PROTOPT_NONETWORK) {
+ if(data->conn->handler->flags & PROTOPT_NONETWORK) {
/* protocols that work without network cannot be paused. This is
actually only FILE:// just now, and it can't pause since the transfer
isn't done using the "normal" procedure. */
@@ -366,7 +366,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
#ifndef CURL_DISABLE_HTTP
if(data->state.trailers_state == TRAILERS_SENDING &&
- !Curl_trailers_left(data)) {
+ !trailers_left(data)) {
Curl_dyn_free(&data->state.trailers_buf);
data->state.trailers_state = TRAILERS_DONE;
data->set.trailer_data = NULL;
@@ -409,9 +409,9 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
* POST/PUT with multi-pass authentication when a sending was denied and a
* resend is necessary.
*/
-CURLcode Curl_readrewind(struct connectdata *conn)
+CURLcode Curl_readrewind(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_mimepart *mimepart = &data->set.mimepost;
conn->bits.rewindaftersend = FALSE; /* we rewind now */
@@ -426,7 +426,7 @@ CURLcode Curl_readrewind(struct connectdata *conn)
CURLOPT_HTTPPOST, call app to rewind
*/
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
if(http->sendit)
mimepart = http->sendit;
@@ -435,9 +435,10 @@ CURLcode Curl_readrewind(struct connectdata *conn)
; /* do nothing */
else if(data->state.httpreq == HTTPREQ_POST_MIME ||
data->state.httpreq == HTTPREQ_POST_FORM) {
- if(Curl_mime_rewind(mimepart)) {
+ CURLcode result = Curl_mime_rewind(mimepart);
+ if(result) {
failf(data, "Cannot rewind mime/post data");
- return CURLE_SEND_FAIL_REWIND;
+ return result;
}
}
else {
@@ -598,7 +599,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(bytestoread) {
/* receive data from the network! */
- result = Curl_read(conn, conn->sockfd, buf, bytestoread, &nread);
+ result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
/* read would've blocked */
if(CURLE_AGAIN == result)
@@ -707,64 +708,10 @@ static CURLcode readwrite_data(struct Curl_easy *data,
write a piece of the body */
if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
/* HTTP-only checks */
-
- if(data->req.newurl) {
- if(conn->bits.close) {
- /* Abort after the headers if "follow Location" is set
- and we're set to close anyway. */
- k->keepon &= ~KEEP_RECV;
- *done = TRUE;
- return CURLE_OK;
- }
- /* We have a new url to load, but since we want to be able
- to re-use this connection properly, we read the full
- response in "ignore more" */
- k->ignorebody = TRUE;
- infof(data, "Ignoring the response-body\n");
- }
- if(data->state.resume_from && !k->content_range &&
- (data->state.httpreq == HTTPREQ_GET) &&
- !k->ignorebody) {
-
- if(k->size == data->state.resume_from) {
- /* The resume point is at the end of file, consider this fine
- even if it doesn't allow resume from here. */
- infof(data, "The entire document is already downloaded");
- connclose(conn, "already downloaded");
- /* Abort download */
- k->keepon &= ~KEEP_RECV;
- *done = TRUE;
- return CURLE_OK;
- }
-
- /* we wanted to resume a download, although the server doesn't
- * seem to support this and we did this with a GET (if it
- * wasn't a GET we did a POST or PUT resume) */
- failf(data, "HTTP server doesn't seem to support "
- "byte ranges. Cannot resume.");
- return CURLE_RANGE_ERROR;
- }
-
- if(data->set.timecondition && !data->state.range) {
- /* A time condition has been set AND no ranges have been
- requested. This seems to be what chapter 13.3.4 of
- RFC 2616 defines to be the correct action for a
- HTTP/1.1 client */
-
- if(!Curl_meets_timecondition(data, k->timeofdoc)) {
- *done = TRUE;
- /* We're simulating a http 304 from server so we return
- what should have been returned from the server */
- data->info.httpcode = 304;
- infof(data, "Simulate a HTTP 304 response!\n");
- /* we abort the transfer before it is completed == we ruin the
- re-use ability. Close the connection */
- connclose(conn, "Simulated 304 handling");
- return CURLE_OK;
- }
- } /* we have a time condition */
-
- } /* this is HTTP or RTSP */
+ result = Curl_http_firstwrite(data, conn, done);
+ if(result || *done)
+ return result;
+ }
} /* this is the first time we write a body part */
#endif /* CURL_DISABLE_HTTP */
@@ -795,7 +742,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
*/
CURLcode extra;
CHUNKcode res =
- Curl_httpchunk_read(conn, k->str, nread, &nread, &extra);
+ Curl_httpchunk_read(data, k->str, nread, &nread, &extra);
if(CHUNKE_OK < res) {
if(CHUNKE_PASSTHRU_ERROR == res) {
@@ -806,18 +753,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
return CURLE_RECV_ERROR;
}
if(CHUNKE_STOP == res) {
- size_t dataleft;
/* we're done reading chunks! */
k->keepon &= ~KEEP_RECV; /* read no more */
- /* There are now possibly N number of bytes at the end of the
- str buffer that weren't written to the client.
- Push it back to be read on the next pass. */
-
- dataleft = conn->chunk.dataleft;
- if(dataleft != 0) {
- infof(conn->data, "Leftovers after chunking: %zu bytes\n",
- dataleft);
+ /* N number of bytes at the end of the str buffer that weren't
+ written to the client. */
+ if(conn->chunk.datasize) {
+ infof(data, "Leftovers after chunking: % "
+ CURL_FORMAT_CURL_OFF_T "u bytes\n",
+ conn->chunk.datasize);
}
}
/* If it returned OK, we just keep going */
@@ -867,11 +811,11 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* Don't let excess data pollute body writes */
if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&data->state.headerb),
headlen);
else
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&data->state.headerb),
(size_t)k->maxdownload);
@@ -884,19 +828,19 @@ static CURLcode readwrite_data(struct Curl_easy *data,
in http_chunks.c.
Make sure that ALL_CONTENT_ENCODINGS contains all the
encodings handled here. */
- if(conn->data->set.http_ce_skip || !k->writer_stack) {
+ if(data->set.http_ce_skip || !k->writer_stack) {
if(!k->ignorebody) {
#ifndef CURL_DISABLE_POP3
if(conn->handler->protocol & PROTO_FAMILY_POP3)
- result = Curl_pop3_write(conn, k->str, nread);
+ result = Curl_pop3_write(data, k->str, nread);
else
#endif /* CURL_DISABLE_POP3 */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
nread);
}
}
else if(!k->ignorebody)
- result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
+ result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
}
k->badheader = HEADER_NORMAL; /* taken care of now */
@@ -957,17 +901,18 @@ static CURLcode readwrite_data(struct Curl_easy *data,
return CURLE_OK;
}
-CURLcode Curl_done_sending(struct connectdata *conn,
+CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k)
{
+ struct connectdata *conn = data->conn;
k->keepon &= ~KEEP_SEND; /* we're done writing */
/* These functions should be moved into the handler struct! */
- Curl_http2_done_sending(conn);
- Curl_quic_done_sending(conn);
+ Curl_http2_done_sending(data, conn);
+ Curl_quic_done_sending(data);
if(conn->bits.rewindaftersend) {
- CURLcode result = Curl_readrewind(conn);
+ CURLcode result = Curl_readrewind(data);
if(result)
return result;
}
@@ -1015,6 +960,8 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
*didwhat |= KEEP_SEND;
do {
+ curl_off_t nbody;
+
/* only read more data if there's no upload data already
present in the upload buffer */
if(0 == k->upload_present) {
@@ -1028,7 +975,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/* HTTP pollution, this should be written nicer to become more
protocol agnostic. */
size_t fillcount;
- struct HTTP *http = k->protop;
+ struct HTTP *http = k->p.http;
if((k->exp100 == EXP100_SENDING_REQUEST) &&
(http->sending == HTTPSEND_BODY)) {
@@ -1053,7 +1000,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
sending_http_headers = FALSE;
}
- result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size,
+ result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
&fillcount);
if(result)
return result;
@@ -1068,7 +1015,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
break;
}
if(nread <= 0) {
- result = Curl_done_sending(conn, k);
+ result = Curl_done_sending(data, k);
if(result)
return result;
break;
@@ -1130,7 +1077,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
#ifndef CURL_DISABLE_SMTP
if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
- result = Curl_smtp_escape_eob(conn, nread);
+ result = Curl_smtp_escape_eob(data, nread);
if(result)
return result;
}
@@ -1142,7 +1089,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
}
/* write to socket (send away data) */
- result = Curl_write(conn,
+ result = Curl_write(data,
conn->writesockfd, /* socket to send to */
k->upload_fromhere, /* buffer pointer */
k->upload_present, /* buffer size */
@@ -1152,13 +1099,26 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
win_update_buffer_size(conn->writesockfd);
- if(data->set.verbose)
+ if(k->pendingheader) {
+ /* parts of what was sent was header */
+ curl_off_t n = CURLMIN(k->pendingheader, bytes_written);
/* show the data before we change the pointer upload_fromhere */
- Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
- (size_t)bytes_written);
+ Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, (size_t)n);
+ k->pendingheader -= n;
+ nbody = bytes_written - n; /* size of the written body part */
+ }
+ else
+ nbody = bytes_written;
- k->writebytecount += bytes_written;
- Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ if(nbody) {
+ /* show the data before we change the pointer upload_fromhere */
+ Curl_debug(data, CURLINFO_DATA_OUT,
+ &k->upload_fromhere[bytes_written - nbody],
+ (size_t)nbody);
+
+ k->writebytecount += nbody;
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ }
if((!k->upload_chunky || k->forbidchunk) &&
(k->writebytecount == data->state.infilesize)) {
@@ -1186,7 +1146,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
k->upload_present = 0; /* no more bytes left */
if(k->upload_done) {
- result = Curl_done_sending(conn, k);
+ result = Curl_done_sending(data, k);
if(result)
return result;
}
@@ -1233,7 +1193,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
else
fd_write = CURL_SOCKET_BAD;
- if(conn->data->state.drain) {
+ if(data->state.drain) {
select_res |= CURL_CSELECT_IN;
DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n"));
}
@@ -1247,6 +1207,10 @@ CURLcode Curl_readwrite(struct connectdata *conn,
return CURLE_SEND_ERROR;
}
+#ifdef USE_HYPER
+ if(conn->datastream)
+ return conn->datastream(data, conn, &didwhat, done, select_res);
+#endif
/* We go ahead and do a read if we have a readable socket or if
the stream was rewound (in which case we have data in a
buffer) */
@@ -1266,10 +1230,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
k->now = Curl_now();
- if(didwhat) {
- ;
- }
- else {
+ if(!didwhat) {
/* no read no write, this is a timeout? */
if(k->exp100 == EXP100_AWAITING_CONTINUE) {
/* This should allow some time for the header to arrive, but only a
@@ -1296,7 +1257,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
}
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, k->now);
@@ -1355,7 +1316,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
failf(data, "transfer closed with outstanding read data remaining");
return CURLE_PARTIAL_FILE;
}
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
}
@@ -1373,15 +1334,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
* keeps track of. This function will only be called for connections that are
* in the proper state to have this information available.
*/
-int Curl_single_getsock(const struct connectdata *conn,
+int Curl_single_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock)
{
- const struct Curl_easy *data = conn->data;
int bitmap = GETSOCK_BLANK;
unsigned sockindex = 0;
if(conn->handler->perform_getsock)
- return conn->handler->perform_getsock(conn, sock);
+ return conn->handler->perform_getsock(data, conn, sock);
/* don't include HOLD and PAUSE connections */
if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
@@ -1529,8 +1490,23 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
}
#endif
Curl_http2_init_state(&data->state);
+ Curl_hsts_loadcb(data, data->hsts);
+ }
+
+ /*
+ * Set user-agent. Used for HTTP, but since we can attempt to tunnel
+ * basically anything through a http proxy we can't limit this based on
+ * protocol.
+ */
+ if(data->set.str[STRING_USERAGENT]) {
+ Curl_safefree(data->state.aptr.uagent);
+ data->state.aptr.uagent =
+ aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
+ if(!data->state.aptr.uagent)
+ return CURLE_OUT_OF_MEMORY;
}
+ data->req.headerbytecount = 0;
return result;
}
@@ -1573,6 +1549,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
bool reachedmax = FALSE;
CURLUcode uc;
+ DEBUGASSERT(type != FOLLOW_NONE);
+
if(type == FOLLOW_REDIR) {
if((data->set.maxredirs != -1) &&
(data->set.followlocation >= data->set.maxredirs)) {
@@ -1604,8 +1582,11 @@ CURLcode Curl_follow(struct Curl_easy *data,
}
}
- if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
- /* This is an absolute URL, don't allow the custom port number */
+ if((type != FOLLOW_RETRY) &&
+ (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
+ Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
+ /* If this is not redirect due to a 401 or 407 response and an absolute
+ URL: don't allow a custom port number */
disallowport = TRUE;
DEBUGASSERT(data->state.uh);
@@ -1686,7 +1667,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
* request with an error page. To be sure that libcurl gets the page that
* most user agents would get, libcurl has to force GET.
*
- * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
if((data->state.httpreq == HTTPREQ_POST
@@ -1711,7 +1692,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
* request with an error page. To be sure that libcurl gets the page that
* most user agents would get, libcurl has to force GET.
*
- * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
if((data->state.httpreq == HTTPREQ_POST
@@ -1765,10 +1746,9 @@ CURLcode Curl_follow(struct Curl_easy *data,
/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
NOTE: that the *url is malloc()ed. */
-CURLcode Curl_retry_request(struct connectdata *conn,
- char **url)
+CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
bool retry = FALSE;
*url = NULL;
@@ -1798,7 +1778,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
to issue again, but the nghttp2 API can deliver the message to other
streams as well, which is why this adds the check the data counters
too. */
- infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
+ infof(data, "REFUSED_STREAM, retrying a fresh connect\n");
data->state.refused_stream = FALSE; /* clear again */
retry = TRUE;
}
@@ -1810,9 +1790,9 @@ CURLcode Curl_retry_request(struct connectdata *conn,
data->state.retrycount = 0;
return CURLE_SEND_ERROR;
}
- infof(conn->data, "Connection died, retrying a fresh connect\
+ infof(data, "Connection died, retrying a fresh connect\
(retry count: %d)\n", data->state.retrycount);
- *url = strdup(conn->data->change.url);
+ *url = strdup(data->change.url);
if(!*url)
return CURLE_OUT_OF_MEMORY;
@@ -1826,7 +1806,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
if(data->req.writebytecount) {
- CURLcode result = Curl_readrewind(conn);
+ CURLcode result = Curl_readrewind(data);
if(result) {
Curl_safefree(*url);
return result;
@@ -1853,7 +1833,7 @@ Curl_setup_transfer(
{
struct SingleRequest *k = &data->req;
struct connectdata *conn = data->conn;
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
bool httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
(http->sending == HTTPSEND_REQUEST));
DEBUGASSERT(conn != NULL);
diff --git a/Utilities/cmcurl/lib/transfer.h b/Utilities/cmcurl/lib/transfer.h
index 67fd91f25..0fa3d55e8 100644
--- a/Utilities/cmcurl/lib/transfer.h
+++ b/Utilities/cmcurl/lib/transfer.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
***************************************************************************/
#define Curl_headersep(x) ((((x)==':') || ((x)==';')))
-char *Curl_checkheaders(const struct connectdata *conn,
+char *Curl_checkheaders(const struct Curl_easy *data,
const char *thisheader);
void Curl_init_CONNECT(struct Curl_easy *data);
@@ -36,9 +36,8 @@ typedef enum {
allow initing to this */
FOLLOW_FAKE, /* only records stuff, not actually following */
FOLLOW_RETRY, /* set if this is a request retry as opposed to a real
- redirect following */
- FOLLOW_REDIR, /* a full true redirect */
- FOLLOW_LAST /* never used */
+ redirect following */
+ FOLLOW_REDIR /* a full true redirect */
} followtype;
CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
@@ -46,16 +45,16 @@ CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data, bool *done,
bool *comeback);
-int Curl_single_getsock(const struct connectdata *conn,
- curl_socket_t *socks);
-CURLcode Curl_readrewind(struct connectdata *conn);
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+int Curl_single_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+CURLcode Curl_readrewind(struct Curl_easy *data);
+CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
size_t *nreadp);
-CURLcode Curl_retry_request(struct connectdata *conn, char **url);
+CURLcode Curl_retry_request(struct Curl_easy *data, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
-CURLcode Curl_done_sending(struct connectdata *conn,
+CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k);
/* This sets up a forthcoming transfer */
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 150667aa9..c02d2c201 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -96,6 +96,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "getinfo.h"
#include "urlapi-int.h"
#include "system_win32.h"
+#include "hsts.h"
/* And now for the protocols */
#include "ftp.h"
@@ -130,7 +131,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "memdebug.h"
static void conn_free(struct connectdata *conn);
-static unsigned int get_protocol_family(unsigned int protocol);
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
* more than just a few bytes to play with. Don't let it become too small or
@@ -140,6 +140,24 @@ static unsigned int get_protocol_family(unsigned int protocol);
# error READBUFFER_SIZE is too small
#endif
+/*
+* get_protocol_family()
+*
+* This is used to return the protocol family for a given protocol.
+*
+* Parameters:
+*
+* 'h' [in] - struct Curl_handler pointer.
+*
+* Returns the family as a single bit protocol identifier.
+*/
+static unsigned int get_protocol_family(const struct Curl_handler *h)
+{
+ DEBUGASSERT(h);
+ DEBUGASSERT(h->family);
+ return h->family;
+}
+
/*
* Protocol table. Schemes (roughly) in 2019 popularity order:
@@ -215,9 +233,8 @@ static const struct Curl_handler * const protocols[] = {
#endif
#endif
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
- (CURL_SIZEOF_CURL_OFF_T > 4) && \
- (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4)
&Curl_handler_smb,
#ifdef USE_SSL
&Curl_handler_smbs,
@@ -228,12 +245,15 @@ static const struct Curl_handler * const protocols[] = {
&Curl_handler_rtsp,
#endif
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
&Curl_handler_mqtt,
#endif
#ifndef CURL_DISABLE_GOPHER
&Curl_handler_gopher,
+#ifdef USE_SSL
+ &Curl_handler_gophers,
+#endif
#endif
#ifdef USE_LIBRTMP
@@ -274,6 +294,7 @@ static const struct Curl_handler Curl_handler_dummy = {
ZERO_NULL, /* connection_check */
0, /* defport */
0, /* protocol */
+ 0, /* family */
PROTOPT_NONE /* flags */
};
@@ -343,6 +364,9 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_expire_clear(data); /* shut off timers */
+ /* Detach connection if any is left. This should not be normal, but can be
+ the case for example with CONNECT_ONLY + recv/send (test 556) */
+ Curl_detach_connnection(data);
m = data->multi;
if(m)
/* This handle is still part of a multi handle, take care of this first
@@ -392,11 +416,10 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_dyn_free(&data->state.headerb);
Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, TRUE);
-#ifdef USE_ALTSVC
Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
- Curl_altsvc_cleanup(data->asi);
- data->asi = NULL;
-#endif
+ Curl_altsvc_cleanup(&data->asi);
+ Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
+ Curl_hsts_cleanup(&data->hsts);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
@@ -404,7 +427,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->info.wouldredirect);
/* this destroys the channel and we cannot use it anymore after this */
- Curl_resolver_cleanup(data->state.resolver);
+ Curl_resolver_cleanup(data->state.async.resolver);
Curl_http2_cleanup_dependencies(data);
Curl_convert_close(data);
@@ -428,9 +451,12 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->state.aptr.rtsp_transport);
#ifndef CURL_DISABLE_DOH
- Curl_dyn_free(&data->req.doh.probe[0].serverdoh);
- Curl_dyn_free(&data->req.doh.probe[1].serverdoh);
- curl_slist_free_all(data->req.doh.headers);
+ if(data->req.doh) {
+ Curl_dyn_free(&data->req.doh->probe[0].serverdoh);
+ Curl_dyn_free(&data->req.doh->probe[1].serverdoh);
+ curl_slist_free_all(data->req.doh->headers);
+ Curl_safefree(data->req.doh);
+ }
#endif
/* destruct wildcard structures if it is needed */
@@ -480,6 +506,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
set->ftp_filemethod = FTPFILE_MULTICWD;
+ set->ftp_skip_ip = TRUE; /* skip PASV IP by default */
#endif
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
@@ -616,7 +643,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
data->magic = CURLEASY_MAGIC_NUMBER;
- result = Curl_resolver_init(data, &data->state.resolver);
+ result = Curl_resolver_init(data, &data->state.async.resolver);
if(result) {
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
free(data);
@@ -637,7 +664,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
}
if(result) {
- Curl_resolver_cleanup(data->state.resolver);
+ Curl_resolver_cleanup(data->state.async.resolver);
Curl_dyn_free(&data->state.headerb);
Curl_freeset(data);
free(data);
@@ -688,29 +715,29 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-static void conn_shutdown(struct connectdata *conn)
+static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
{
DEBUGASSERT(conn);
- infof(conn->data, "Closing connection %ld\n", conn->connection_id);
- DEBUGASSERT(conn->data);
+ DEBUGASSERT(data);
+ infof(data, "Closing connection %ld\n", conn->connection_id);
/* possible left-overs from the async name resolvers */
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
/* close the SSL stuff before we close any sockets since they will/may
write to the sockets */
- Curl_ssl_close(conn, FIRSTSOCKET);
- Curl_ssl_close(conn, SECONDARYSOCKET);
+ Curl_ssl_close(data, conn, FIRSTSOCKET);
+ Curl_ssl_close(data, conn, SECONDARYSOCKET);
/* close possibly still open sockets */
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
- Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
- Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
+ Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]);
if(CURL_SOCKET_BAD != conn->tempsock[0])
- Curl_closesocket(conn, conn->tempsock[0]);
+ Curl_closesocket(data, conn, conn->tempsock[0]);
if(CURL_SOCKET_BAD != conn->tempsock[1])
- Curl_closesocket(conn, conn->tempsock[1]);
+ Curl_closesocket(data, conn, conn->tempsock[1]);
}
static void conn_free(struct connectdata *conn)
@@ -805,19 +832,23 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
/* Cleanup NEGOTIATE connection-related data */
Curl_http_auth_cleanup_negotiate(conn);
- /* the protocol specific disconnect handler and conn_shutdown need a transfer
- for the connection! */
- conn->data = data;
-
if(conn->bits.connect_only)
/* treat the connection as dead in CONNECT_ONLY situations */
dead_connection = TRUE;
+ /* temporarily attach the connection to this transfer handle for the
+ disonnect and shutdown */
+ Curl_attach_connnection(data, conn);
+
if(conn->handler->disconnect)
/* This is set if protocol-specific cleanups should be made */
- conn->handler->disconnect(conn, dead_connection);
+ conn->handler->disconnect(data, conn, dead_connection);
+
+ conn_shutdown(data, conn);
+
+ /* detach it again */
+ Curl_detach_connnection(data);
- conn_shutdown(conn);
conn_free(conn);
return CURLE_OK;
}
@@ -915,15 +946,13 @@ static bool conn_maxage(struct Curl_easy *data,
struct connectdata *conn,
struct curltime now)
{
- if(!conn->data) {
- timediff_t idletime = Curl_timediff(now, conn->lastused);
- idletime /= 1000; /* integer seconds is fine */
+ timediff_t idletime = Curl_timediff(now, conn->lastused);
+ idletime /= 1000; /* integer seconds is fine */
- if(idletime > data->set.maxage_conn) {
- infof(data, "Too old connection (%ld seconds), disconnect it\n",
- idletime);
- return TRUE;
- }
+ if(idletime > data->set.maxage_conn) {
+ infof(data, "Too old connection (%ld seconds), disconnect it\n",
+ idletime);
+ return TRUE;
}
return FALSE;
}
@@ -940,23 +969,29 @@ static bool conn_maxage(struct Curl_easy *data,
static bool extract_if_dead(struct connectdata *conn,
struct Curl_easy *data)
{
- if(!CONN_INUSE(conn) && !conn->data) {
+ if(!CONN_INUSE(conn)) {
/* The check for a dead socket makes sense only if the connection isn't in
use */
bool dead;
struct curltime now = Curl_now();
if(conn_maxage(data, conn, now)) {
+ /* avoid check if already too old */
dead = TRUE;
}
else if(conn->handler->connection_check) {
/* The protocol has a special method for checking the state of the
connection. Use it to check if the connection is dead. */
unsigned int state;
- struct Curl_easy *olddata = conn->data;
- conn->data = data; /* use this transfer for now */
- state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
- conn->data = olddata;
+
+ /* 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 */
@@ -981,10 +1016,11 @@ struct prunedead {
* Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
*
*/
-static int call_extract_if_dead(struct connectdata *conn, void *param)
+static int call_extract_if_dead(struct Curl_easy *data,
+ struct connectdata *conn, void *param)
{
struct prunedead *p = (struct prunedead *)param;
- if(extract_if_dead(conn, p->data)) {
+ if(extract_if_dead(conn, data)) {
/* stop the iteration here, pass back the connection that was extracted */
p->extracted = conn;
return 1;
@@ -994,14 +1030,16 @@ static int call_extract_if_dead(struct connectdata *conn, void *param)
/*
* This function scans the connection cache for half-open/dead connections,
- * closes and removes them.
- * The cleanup is done at most once per second.
+ * closes and removes them. The cleanup is done at most once per second.
+ *
+ * When called, this transfer has no connection attached.
*/
static void prune_dead_connections(struct Curl_easy *data)
{
struct curltime now = Curl_now();
timediff_t elapsed;
+ DEBUGASSERT(!data->conn); /* no connection */
CONNCACHE_LOCK(data);
elapsed =
Curl_timediff(now, data->state.conn_cache->last_cleanup);
@@ -1019,7 +1057,7 @@ static void prune_dead_connections(struct Curl_easy *data)
Curl_conncache_remove_conn(data, prune.extracted, TRUE);
/* disconnect it */
- (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
+ (void)Curl_disconnect(data, prune.extracted, TRUE);
}
CONNCACHE_LOCK(data);
data->state.conn_cache->last_cleanup = now;
@@ -1071,11 +1109,11 @@ ConnectionExists(struct Curl_easy *data,
/* Look up the bundle with all the connections to this particular host.
Locks the connection cache, beware of early returns! */
- bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache,
+ bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache,
&hostbundle);
if(bundle) {
/* Max pipe length is zero (unlimited) for multiplexed connections */
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
infof(data, "Found bundle for host %s: %p [%s]\n",
hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
@@ -1121,13 +1159,16 @@ ConnectionExists(struct Curl_easy *data,
/* connect-only or to-be-closed connections will not be reused */
continue;
+ if(extract_if_dead(check, data)) {
+ /* disconnect it */
+ (void)Curl_disconnect(data, check, TRUE);
+ continue;
+ }
+
if(bundle->multiuse == BUNDLE_MULTIPLEX)
multiplexed = CONN_INUSE(check);
- if(canmultiplex) {
- ;
- }
- else {
+ if(!canmultiplex) {
if(multiplexed) {
/* can only happen within multi handles, and means that another easy
handle is using this connection */
@@ -1135,9 +1176,9 @@ ConnectionExists(struct Curl_easy *data,
}
if(Curl_resolver_asynch()) {
- /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
+ /* primary_ip[0] is NUL only if the resolving of the name hasn't
completed yet and until then we don't re-use this connection */
- if(!check->ip_addr_str[0]) {
+ if(!check->primary_ip[0]) {
infof(data,
"Connection #%ld is still name resolving, can't reuse\n",
check->connection_id);
@@ -1171,7 +1212,7 @@ ConnectionExists(struct Curl_easy *data,
if((needle->handler->flags&PROTOPT_SSL) !=
(check->handler->flags&PROTOPT_SSL))
/* don't do mixed SSL and non-SSL connections */
- if(get_protocol_family(check->handler->protocol) !=
+ if(get_protocol_family(check->handler) !=
needle->handler->protocol || !check->bits.tls_upgraded)
/* except protocols that have been upgraded via TLS */
continue;
@@ -1276,7 +1317,7 @@ ConnectionExists(struct Curl_easy *data,
is allowed to be upgraded via TLS */
if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
- (get_protocol_family(check->handler->protocol) ==
+ (get_protocol_family(check->handler) ==
needle->handler->protocol && check->bits.tls_upgraded)) &&
(!needle->bits.conn_to_host || strcasecompare(
needle->conn_to_host.name, check->conn_to_host.name)) &&
@@ -1439,17 +1480,18 @@ ConnectionExists(struct Curl_easy *data,
* verboseconnect() displays verbose information after a connect
*/
#ifndef CURL_DISABLE_VERBOSE_STRINGS
-void Curl_verboseconnect(struct connectdata *conn)
+void Curl_verboseconnect(struct Curl_easy *data,
+ struct connectdata *conn)
{
- if(conn->data->set.verbose)
- infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
+ if(data->set.verbose)
+ infof(data, "Connected to %s (%s) port %ld (#%ld)\n",
#ifndef CURL_DISABLE_PROXY
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
#endif
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname,
- conn->ip_addr_str, conn->port, conn->connection_id);
+ conn->primary_ip, conn->port, conn->connection_id);
}
#endif
@@ -1488,16 +1530,14 @@ static void strip_trailing_dot(struct hostname *host)
/*
* Perform any necessary IDN conversion of hostname
*/
-CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
+CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
struct hostname *host)
{
- struct Curl_easy *data = conn->data;
-
#ifndef USE_LIBIDN2
(void)data;
- (void)conn;
+ (void)data;
#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
- (void)conn;
+ (void)data;
#endif
/* set the name we use to display the host name */
@@ -1517,13 +1557,18 @@ CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
int flags = IDN2_NFC_INPUT;
#endif
int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
+ if(rc != IDN2_OK)
+ /* fallback to TR46 Transitional mode for better IDNA2003
+ compatibility */
+ rc = idn2_lookup_ul((const char *)host->name, &ace_hostname,
+ IDN2_TRANSITIONAL);
if(rc == IDN2_OK) {
host->encalloc = (char *)ace_hostname;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
}
else {
- failf(data, "Failed to convert %s to ACE; %s\n", host->name,
+ failf(data, "Failed to convert %s to ACE; %s", host->name,
idn2_strerror(rc));
return CURLE_URL_MALFORMAT;
}
@@ -1538,7 +1583,7 @@ CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
}
else {
char buffer[STRERROR_LEN];
- failf(data, "Failed to convert %s to ACE; %s\n", host->name,
+ failf(data, "Failed to convert %s to ACE; %s", host->name,
Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
return CURLE_URL_MALFORMAT;
}
@@ -1629,9 +1674,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();
- /* Store off the configured connection upkeep time. */
- conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
-
conn->data = data; /* Setup the association between this connection
and the Curl_easy */
@@ -1787,12 +1829,14 @@ CURLcode Curl_uc_to_curlcode(CURLUcode uc)
* the scope_id based on that!
*/
-static void zonefrom_url(CURLU *uh, struct connectdata *conn)
+static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
+ struct connectdata *conn)
{
char *zoneid;
- CURLUcode uc;
-
- uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
+ CURLUcode uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
if(!uc && zoneid) {
char *endp;
@@ -1815,7 +1859,7 @@ static void zonefrom_url(CURLU *uh, struct connectdata *conn)
scopeidx = if_nametoindex(zoneid);
#endif
if(!scopeidx)
- infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid,
+ infof(data, "Invalid zoneid: %s; %s\n", zoneid,
strerror(errno));
else
conn->scope_id = scopeidx;
@@ -1891,6 +1935,37 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
if(uc)
return Curl_uc_to_curlcode(uc);
+ uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
+ if(uc) {
+ if(!strcasecompare("file", data->state.up.scheme))
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifdef USE_HSTS
+ if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
+ if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) {
+ char *url;
+ Curl_safefree(data->state.up.scheme);
+ 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);
+ /* 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)
+ return Curl_uc_to_curlcode(uc);
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
+ infof(data, "Switched from HTTP to HTTPS due to HSTS => %s\n",
+ data->change.url);
+ }
+ }
+#endif
+
result = findprotocol(data, conn, data->state.up.scheme);
if(result)
return result;
@@ -1936,12 +2011,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
else if(uc != CURLUE_NO_OPTIONS)
return Curl_uc_to_curlcode(uc);
- uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
- if(uc) {
- if(!strcasecompare("file", data->state.up.scheme))
- return CURLE_OUT_OF_MEMORY;
- }
-
uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
if(uc)
return Curl_uc_to_curlcode(uc);
@@ -1954,7 +2023,9 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
}
else {
unsigned long port = strtoul(data->state.up.port, NULL, 10);
- conn->port = conn->remote_port = curlx_ultous(port);
+ conn->port = conn->remote_port =
+ (data->set.use_port && data->state.allow_port) ?
+ (int)data->set.use_port : curlx_ultous(port);
}
(void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
@@ -1970,7 +2041,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
hlen = strlen(hostname);
hostname[hlen - 1] = 0;
- zonefrom_url(uh, conn);
+ zonefrom_url(uh, data, conn);
}
/* make sure the connect struct gets its own copy of the host name */
@@ -2028,7 +2099,8 @@ static CURLcode setup_range(struct Curl_easy *data)
*
* This MUST get called after proxy magic has been figured out.
*/
-static CURLcode setup_connection_internals(struct connectdata *conn)
+static CURLcode setup_connection_internals(struct Curl_easy *data,
+ struct connectdata *conn)
{
const struct Curl_handler *p;
CURLcode result;
@@ -2037,7 +2109,7 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
p = conn->handler;
if(p->setup_connection) {
- result = (*p->setup_connection)(conn);
+ result = (*p->setup_connection)(data, conn);
if(result)
return result;
@@ -2060,12 +2132,14 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
void Curl_free_request_state(struct Curl_easy *data)
{
- Curl_safefree(data->req.protop);
+ Curl_safefree(data->req.p.http);
Curl_safefree(data->req.newurl);
#ifndef CURL_DISABLE_DOH
- Curl_close(&data->req.doh.probe[0].easy);
- Curl_close(&data->req.doh.probe[1].easy);
+ if(data->req.doh) {
+ Curl_close(&data->req.doh->probe[0].easy);
+ Curl_close(&data->req.doh->probe[1].easy);
+ }
#endif
}
@@ -2122,7 +2196,7 @@ static bool check_noproxy(const char *name, const char *no_proxy)
/* Look for the end of the token. */
;
- /* To match previous behaviour, where it was necessary to specify
+ /* To match previous behavior, where it was necessary to specify
* ".local.com" to prevent matching "notlocal.com", we will leave
* the '.' off.
*/
@@ -2155,7 +2229,8 @@ static bool check_noproxy(const char *name, const char *no_proxy)
* name and is not limited to HTTP proxies only.
* The returned pointer must be freed by the caller (unless NULL)
****************************************************************/
-static char *detect_proxy(struct connectdata *conn)
+static char *detect_proxy(struct Curl_easy *data,
+ struct connectdata *conn)
{
char *proxy = NULL;
@@ -2180,6 +2255,9 @@ static char *detect_proxy(struct connectdata *conn)
const char *protop = conn->handler->scheme;
char *envp = proxy_env;
char *prox;
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
/* Now, build <protocol>_proxy and check for such a one to use */
while(*protop)
@@ -2222,7 +2300,7 @@ static char *detect_proxy(struct connectdata *conn)
}
}
if(proxy)
- infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
+ infof(data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
return proxy;
}
@@ -2238,7 +2316,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
curl_proxytype proxytype)
{
char *portptr = NULL;
- long port = -1;
+ int port = -1;
char *proxyuser = NULL;
char *proxypasswd = NULL;
char *host;
@@ -2327,14 +2405,14 @@ static CURLcode parse_proxy(struct Curl_easy *data,
curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
if(portptr) {
- port = strtol(portptr, NULL, 10);
+ port = (int)strtol(portptr, NULL, 10);
free(portptr);
}
else {
if(data->set.proxyport)
/* None given in the proxy string, then get the default one if it is
given */
- port = data->set.proxyport;
+ port = (int)data->set.proxyport;
else {
if(proxytype == CURLPROXY_HTTPS)
port = CURL_DEFAULT_HTTPS_PROXY_PORT;
@@ -2361,7 +2439,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
size_t len = strlen(host);
host[len-1] = 0; /* clear the trailing bracket */
host++;
- zonefrom_url(uhp, conn);
+ zonefrom_url(uhp, data, conn);
}
proxyinfo->host.name = host;
@@ -2377,8 +2455,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
static CURLcode parse_proxy_auth(struct Curl_easy *data,
struct connectdata *conn)
{
- char *proxyuser = data->set.str[STRING_PROXYUSERNAME];
- char *proxypasswd = data->set.str[STRING_PROXYPASSWORD];
+ 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] : "";
CURLcode result = CURLE_OK;
if(proxyuser)
@@ -2392,13 +2472,13 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
/* create_conn helper to parse and init proxy values. to be called after unix
socket init but before any proxy vars are evaluated. */
-static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
+static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
+ struct connectdata *conn)
{
char *proxy = NULL;
char *socksproxy = NULL;
char *no_proxy = NULL;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
/*************************************************************
* Extract the user and password from the authentication string
@@ -2440,7 +2520,7 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
no_proxy = curl_getenv(p);
}
if(no_proxy) {
- infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
+ infof(data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
}
}
@@ -2452,7 +2532,7 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
#ifndef CURL_DISABLE_HTTP
else if(!proxy && !socksproxy)
/* if the host is not in the noproxy list, detect proxy. */
- proxy = detect_proxy(conn);
+ proxy = detect_proxy(data, conn);
#endif /* CURL_DISABLE_HTTP */
Curl_safefree(no_proxy);
@@ -2551,6 +2631,9 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
conn->bits.socksproxy = FALSE;
conn->bits.proxy_user_passwd = FALSE;
conn->bits.tunnel_proxy = FALSE;
+ /* CURLPROXY_HTTPS does not have its own flag in conn->bits, yet we need
+ to signal that CURLPROXY_HTTPS is not used for this connection */
+ conn->http_proxy.proxytype = CURLPROXY_HTTP;
}
out:
@@ -3070,7 +3153,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
conn_to_host = conn_to_host->next;
}
-#ifdef USE_ALTSVC
+#ifndef CURL_DISABLE_ALTSVC
if(data->asi && !host && (port == -1) &&
((conn->handler->protocol == CURLPROTO_HTTPS) ||
#ifdef CURLDEBUG
@@ -3223,7 +3306,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
conn->hostname_resolve = strdup(connhost->name);
if(!conn->hostname_resolve)
return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
*async = TRUE;
@@ -3248,7 +3331,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
conn->hostname_resolve = strdup(host->name);
if(!conn->hostname_resolve)
return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
@@ -3276,9 +3359,15 @@ static CURLcode resolve_server(struct Curl_easy *data,
* previously existing one. All relevant data is copied over and old_conn is
* ready for freeing once this function returns.
*/
-static void reuse_conn(struct connectdata *old_conn,
+static void reuse_conn(struct Curl_easy *data,
+ struct connectdata *old_conn,
struct connectdata *conn)
{
+ /* 'local_ip' and 'local_port' get filled with local's numerical
+ 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;
#ifndef CURL_DISABLE_PROXY
Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
@@ -3291,7 +3380,7 @@ static void reuse_conn(struct connectdata *old_conn,
allocated in vain and is targeted for destruction */
Curl_free_primary_ssl_config(&old_conn->ssl_config);
- conn->data = old_conn->data;
+ 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 */
@@ -3345,7 +3434,11 @@ static void reuse_conn(struct connectdata *old_conn,
old_conn->hostname_resolve = NULL;
/* persist connection info in session handle */
- Curl_persistconninfo(conn);
+ if(conn->transport == TRNSPRT_TCP) {
+ Curl_conninfo_local(data, conn->sock[FIRSTSOCKET],
+ local_ip, &local_port);
+ }
+ Curl_persistconninfo(data, conn, local_ip, local_port);
conn_reset_all_postponed_data(old_conn); /* free buffers */
@@ -3446,7 +3539,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* After the unix socket init but before the proxy vars are used, parse and
initialize the proxy vars */
#ifndef CURL_DISABLE_PROXY
- result = create_conn_helper_init_proxy(conn);
+ result = create_conn_helper_init_proxy(data, conn);
if(result)
goto out;
@@ -3487,22 +3580,22 @@ static CURLcode create_conn(struct Curl_easy *data,
/*************************************************************
* IDN-convert the hostnames
*************************************************************/
- result = Curl_idnconvert_hostname(conn, &conn->host);
+ result = Curl_idnconvert_hostname(data, &conn->host);
if(result)
goto out;
if(conn->bits.conn_to_host) {
- result = Curl_idnconvert_hostname(conn, &conn->conn_to_host);
+ result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
if(result)
goto out;
}
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy) {
- result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host);
+ result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
if(result)
goto out;
}
if(conn->bits.socksproxy) {
- result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host);
+ result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
if(result)
goto out;
}
@@ -3539,7 +3632,7 @@ static CURLcode create_conn(struct Curl_easy *data,
* Setup internals depending on protocol. Needs to be done after
* we figured out what/if proxy to use.
*************************************************************/
- result = setup_connection_internals(conn);
+ result = setup_connection_internals(data, conn);
if(result)
goto out;
@@ -3559,15 +3652,15 @@ static CURLcode create_conn(struct Curl_easy *data,
/* this is supposed to be the connect function so we better at least check
that the file is present here! */
DEBUGASSERT(conn->handler->connect_it);
- Curl_persistconninfo(conn);
- result = conn->handler->connect_it(conn, &done);
+ Curl_persistconninfo(data, conn, NULL, -1);
+ result = conn->handler->connect_it(data, &done);
/* Setup a "faked" transfer that'll do nothing */
if(!result) {
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
Curl_attach_connnection(data, conn);
- result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data);
if(result)
goto out;
@@ -3578,7 +3671,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result) {
DEBUGASSERT(conn->handler->done);
/* we ignore the return code for the protocol-specific DONE */
- (void)conn->handler->done(conn, result, FALSE);
+ (void)conn->handler->done(data, result, FALSE);
goto out;
}
Curl_setup_transfer(data, -1, -1, FALSE, -1);
@@ -3611,6 +3704,7 @@ static CURLcode create_conn(struct Curl_easy *data,
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.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
@@ -3627,18 +3721,15 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_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 = data->set.str[STRING_CERT_PROXY];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
- data->set.proxy_ssl.cert_blob = data->set.blobs[BLOB_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 = data->set.str[STRING_CERT_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];
@@ -3653,7 +3744,6 @@ static CURLcode create_conn(struct Curl_easy *data,
#endif
#endif
- data->set.ssl.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY_ORIG];
data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
@@ -3694,12 +3784,11 @@ static CURLcode create_conn(struct Curl_easy *data,
if(reuse) {
/*
- * We already have a connection for this, we got the former connection
- * in the conn_temp variable and thus we need to cleanup the one we
- * just allocated before we can move along and use the previously
- * existing one.
+ * We already have a connection for this, we got the former connection in
+ * the conn_temp variable and thus we need to cleanup the one we just
+ * allocated before we can move along and use the previously existing one.
*/
- reuse_conn(conn, conn_temp);
+ reuse_conn(data, conn, conn_temp);
#ifdef USE_SSL
free(conn->ssl_extra);
#endif
@@ -3741,7 +3830,8 @@ static CURLcode create_conn(struct Curl_easy *data,
/* this gets a lock on the conncache */
const char *bundlehost;
struct connectbundle *bundle =
- Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost);
+ Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
+ &bundlehost);
if(max_host_connections > 0 && bundle &&
(bundle->num_connections >= max_host_connections)) {
@@ -3752,8 +3842,7 @@ static CURLcode create_conn(struct Curl_easy *data,
CONNCACHE_UNLOCK(data);
if(conn_candidate)
- (void)Curl_disconnect(data, conn_candidate,
- /* dead_connection */ FALSE);
+ (void)Curl_disconnect(data, conn_candidate, FALSE);
else {
infof(data, "No more connections allowed to host %s: %zu\n",
bundlehost, max_host_connections);
@@ -3773,8 +3862,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* The cache is full. Let's see if we can kill a connection. */
conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate)
- (void)Curl_disconnect(data, conn_candidate,
- /* dead_connection */ FALSE);
+ (void)Curl_disconnect(data, conn_candidate, FALSE);
else {
infof(data, "No connections available in cache\n");
connections_available = FALSE;
@@ -3796,8 +3884,7 @@ static CURLcode create_conn(struct Curl_easy *data,
* cache of ours!
*/
Curl_attach_connnection(data, conn);
-
- result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data);
if(result)
goto out;
}
@@ -3869,11 +3956,11 @@ out:
* conn->data MUST already have been setup fine (in create_conn)
*/
-CURLcode Curl_setup_conn(struct connectdata *conn,
+CURLcode Curl_setup_conn(struct Curl_easy *data,
bool *protocol_done)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
@@ -3891,20 +3978,6 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
lingering set from a previous invoke */
conn->bits.proxy_connect_closed = FALSE;
#endif
- /*
- * Set user-agent. Used for HTTP, but since we can attempt to tunnel
- * basically anything through a http proxy we can't limit this based on
- * protocol.
- */
- if(data->set.str[STRING_USERAGENT]) {
- Curl_safefree(data->state.aptr.uagent);
- data->state.aptr.uagent =
- aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
- if(!data->state.aptr.uagent)
- return CURLE_OUT_OF_MEMORY;
- }
-
- data->req.headerbytecount = 0;
#ifdef CURL_DO_LINEEND_CONV
data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
@@ -3916,7 +3989,7 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
- result = Curl_connecthost(conn, conn->dns_entry);
+ result = Curl_connecthost(data, conn, conn->dns_entry);
if(result)
return result;
}
@@ -3927,8 +4000,8 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
*protocol_done = TRUE;
- Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
- Curl_verboseconnect(conn);
+ Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
+ Curl_verboseconnect(data, conn);
}
conn->now = Curl_now(); /* time this *after* the connect is done, we set
@@ -3961,7 +4034,7 @@ CURLcode Curl_connect(struct Curl_easy *data,
/* DNS resolution is done: that's either because this is a reused
connection, in which case DNS was unnecessary, or because DNS
really did finish already (synch resolver/fast async resolve) */
- result = Curl_setup_conn(conn, protocol_done);
+ result = Curl_setup_conn(data, protocol_done);
}
}
@@ -4026,113 +4099,3 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
return CURLE_OK;
}
-
-/*
-* get_protocol_family()
-*
-* This is used to return the protocol family for a given protocol.
-*
-* Parameters:
-*
-* protocol [in] - A single bit protocol identifier such as HTTP or HTTPS.
-*
-* Returns the family as a single bit protocol identifier.
-*/
-
-static unsigned int get_protocol_family(unsigned int protocol)
-{
- unsigned int family;
-
- switch(protocol) {
- case CURLPROTO_HTTP:
- case CURLPROTO_HTTPS:
- family = CURLPROTO_HTTP;
- break;
-
- case CURLPROTO_FTP:
- case CURLPROTO_FTPS:
- family = CURLPROTO_FTP;
- break;
-
- case CURLPROTO_SCP:
- family = CURLPROTO_SCP;
- break;
-
- case CURLPROTO_SFTP:
- family = CURLPROTO_SFTP;
- break;
-
- case CURLPROTO_TELNET:
- family = CURLPROTO_TELNET;
- break;
-
- case CURLPROTO_LDAP:
- case CURLPROTO_LDAPS:
- family = CURLPROTO_LDAP;
- break;
-
- case CURLPROTO_DICT:
- family = CURLPROTO_DICT;
- break;
-
- case CURLPROTO_FILE:
- family = CURLPROTO_FILE;
- break;
-
- case CURLPROTO_TFTP:
- family = CURLPROTO_TFTP;
- break;
-
- case CURLPROTO_IMAP:
- case CURLPROTO_IMAPS:
- family = CURLPROTO_IMAP;
- break;
-
- case CURLPROTO_POP3:
- case CURLPROTO_POP3S:
- family = CURLPROTO_POP3;
- break;
-
- case CURLPROTO_SMTP:
- case CURLPROTO_SMTPS:
- family = CURLPROTO_SMTP;
- break;
-
- case CURLPROTO_RTSP:
- family = CURLPROTO_RTSP;
- break;
-
- case CURLPROTO_RTMP:
- case CURLPROTO_RTMPS:
- family = CURLPROTO_RTMP;
- break;
-
- case CURLPROTO_RTMPT:
- case CURLPROTO_RTMPTS:
- family = CURLPROTO_RTMPT;
- break;
-
- case CURLPROTO_RTMPE:
- family = CURLPROTO_RTMPE;
- break;
-
- case CURLPROTO_RTMPTE:
- family = CURLPROTO_RTMPTE;
- break;
-
- case CURLPROTO_GOPHER:
- family = CURLPROTO_GOPHER;
- break;
-
- case CURLPROTO_SMB:
- case CURLPROTO_SMBS:
- family = CURLPROTO_SMB;
- break;
-
- default:
- family = 0;
- break;
- }
-
- return family;
-}
diff --git a/Utilities/cmcurl/lib/url.h b/Utilities/cmcurl/lib/url.h
index 1941dc6a4..929fc60f2 100644
--- a/Utilities/cmcurl/lib/url.h
+++ b/Utilities/cmcurl/lib/url.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,22 +23,6 @@
***************************************************************************/
#include "curl_setup.h"
-#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
-#define READBUFFER_MAX CURL_MAX_READ_SIZE
-#define READBUFFER_MIN 1024
-
-/* The default upload buffer size, should not be smaller than
- CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
- a write callback.
-
- The size was 16KB for many years but was bumped to 64KB because it makes
- libcurl able to do significantly faster uploads in some circumstances. Even
- larger buffers can help further, but this is deemed a fair memory/speed
- compromise. */
-#define UPLOADBUFFER_DEFAULT 65536
-#define UPLOADBUFFER_MAX (2*1024*1024)
-#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
-
/*
* Prototypes for library-wide functions provided by url.c
*/
@@ -53,7 +37,7 @@ CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect);
CURLcode Curl_disconnect(struct Curl_easy *data,
struct connectdata *, bool dead_connection);
-CURLcode Curl_setup_conn(struct connectdata *conn,
+CURLcode Curl_setup_conn(struct Curl_easy *data,
bool *protocol_done);
void Curl_free_request_state(struct Curl_easy *data);
CURLcode Curl_parse_login_details(const char *login, const size_t len,
@@ -63,7 +47,7 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
bool Curl_is_ASCII_name(const char *hostname);
-CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
+CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
struct hostname *host);
void Curl_free_idnconverted_hostname(struct hostname *host);
@@ -72,9 +56,9 @@ void Curl_free_idnconverted_hostname(struct hostname *host);
specified */
#ifdef CURL_DISABLE_VERBOSE_STRINGS
-#define Curl_verboseconnect(x) Curl_nop_stmt
+#define Curl_verboseconnect(x,y) Curl_nop_stmt
#else
-void Curl_verboseconnect(struct connectdata *conn);
+void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn);
#endif
#ifdef CURL_DISABLE_PROXY
diff --git a/Utilities/cmcurl/lib/urlapi-int.h b/Utilities/cmcurl/lib/urlapi-int.h
index d14d53d97..425723309 100644
--- a/Utilities/cmcurl/lib/urlapi-int.h
+++ b/Utilities/cmcurl/lib/urlapi-int.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -28,7 +28,7 @@
bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
#ifdef DEBUGBUILD
-CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname);
+CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname, bool);
#endif
#endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
index acbfb8287..e3a788221 100644
--- a/Utilities/cmcurl/lib/urlapi.c
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -497,7 +497,8 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
return result;
}
-UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname)
+UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
+ bool has_scheme)
{
char *portptr = NULL;
char endbracket;
@@ -542,10 +543,14 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname)
/* Browser behavior adaptation. If there's a colon with no digits after,
just cut off the name there which makes us ignore the colon and just
- use the default port. Firefox, Chrome and Safari all do that. */
+ use the default port. Firefox, Chrome and Safari all do that.
+
+ Don't do it if the URL has no scheme, to make something that looks like
+ a scheme not work!
+ */
if(!portptr[1]) {
*portptr = '\0';
- return CURLUE_OK;
+ return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
}
if(!ISDIGIT(portptr[1]))
@@ -904,7 +909,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
if(result)
return result;
- result = Curl_parse_port(u, hostname);
+ result = Curl_parse_port(u, hostname, url_has_scheme);
if(result)
return result;
@@ -978,12 +983,14 @@ void curl_url_cleanup(CURLU *u)
}
}
-#define DUP(dest, src, name) \
- if(src->name) { \
- dest->name = strdup(src->name); \
- if(!dest->name) \
- goto fail; \
- }
+#define DUP(dest, src, name) \
+ do { \
+ if(src->name) { \
+ dest->name = strdup(src->name); \
+ if(!dest->name) \
+ goto fail; \
+ } \
+ } while(0)
CURLU *curl_url_dup(CURLU *in)
{
@@ -1255,8 +1262,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_UNKNOWN_PART;
}
if(storep && *storep) {
- free(*storep);
- *storep = NULL;
+ Curl_safefree(*storep);
}
return CURLUE_OK;
}
@@ -1284,8 +1290,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
break;
case CURLUPART_HOST:
storep = &u->host;
- free(u->zoneid);
- u->zoneid = NULL;
+ Curl_safefree(u->zoneid);
break;
case CURLUPART_ZONEID:
storep = &u->zoneid;
@@ -1389,28 +1394,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if(urlencode) {
const unsigned char *i;
char *o;
- bool free_part = FALSE;
char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
if(!enc)
return CURLUE_OUT_OF_MEMORY;
- if(plusencode) {
- /* space to plus */
- i = (const unsigned char *)part;
- for(o = enc; *i; ++o, ++i)
- *o = (*i == ' ') ? '+' : *i;
- *o = 0; /* null-terminate */
- part = strdup(enc);
- if(!part) {
- free(enc);
- return CURLUE_OUT_OF_MEMORY;
- }
- free_part = TRUE;
- }
for(i = (const unsigned char *)part, o = enc; *i; i++) {
- if(Curl_isunreserved(*i) ||
- ((*i == '/') && urlskipslash) ||
- ((*i == '=') && equalsencode) ||
- ((*i == '+') && plusencode)) {
+ if((*i == ' ') && plusencode) {
+ *o = '+';
+ o++;
+ }
+ else if(Curl_isunreserved(*i) ||
+ ((*i == '/') && urlskipslash) ||
+ ((*i == '=') && equalsencode)) {
if((*i == '=') && equalsencode)
/* only skip the first equals sign */
equalsencode = FALSE;
@@ -1424,8 +1418,6 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
*o = 0; /* null-terminate */
newp = enc;
- if(free_part)
- free((char *)part);
}
else {
char *p;
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 0ae926927..f7d60b249 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -76,9 +76,7 @@
/* length of longest IPv6 address string including the trailing null */
#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")
-/* Default FTP/IMAP etc response timeout in milliseconds.
- Symbian OS panics when given a timeout much greater than 1/2 hour.
-*/
+/* Default FTP/IMAP etc response timeout in milliseconds */
#define RESP_TIMEOUT (120*1000)
/* Max string input length is a precaution against abuse and to detect junk
@@ -107,19 +105,27 @@
#include "dynbuf.h"
/* return the count of bytes sent, or -1 on error */
-typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
+typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
const void *buf, /* data to write */
size_t len, /* max amount to write */
CURLcode *err); /* error to return */
/* return the count of bytes read, or -1 on error */
-typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
+typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
char *buf, /* store data here */
size_t len, /* max amount to read */
CURLcode *err); /* error to return */
+#ifdef USE_HYPER
+typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
+ struct connectdata *conn,
+ int *didwhat,
+ bool *done,
+ int select_res);
+#endif
+
#include "mime.h"
#include "imap.h"
#include "pop3.h"
@@ -134,6 +140,7 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#include "wildcard.h"
#include "multihandle.h"
#include "quic.h"
+#include "c-hyper.h"
#ifdef HAVE_GSSAPI
# ifdef HAVE_GSSGNU
@@ -153,6 +160,22 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */
+#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
+#define READBUFFER_MAX CURL_MAX_READ_SIZE
+#define READBUFFER_MIN 1024
+
+/* The default upload buffer size, should not be smaller than
+ CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
+ a write callback.
+
+ The size was 16KB for many years but was bumped to 64KB because it makes
+ libcurl able to do significantly faster uploads in some circumstances. Even
+ larger buffers can help further, but this is deemed a fair memory/speed
+ compromise. */
+#define UPLOADBUFFER_DEFAULT 65536
+#define UPLOADBUFFER_MAX (2*1024*1024)
+#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
+
#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
@@ -207,14 +230,14 @@ struct ssl_backend_data;
/* struct for data related to each SSL connection */
struct ssl_connect_data {
- /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
- but at least asked to or meaning to use it. See 'state' for the exact
- current state of the connection. */
ssl_connection_state state;
ssl_connect_state connecting_state;
#if defined(USE_SSL)
struct ssl_backend_data *backend;
#endif
+ /* Use ssl encrypted communications TRUE/FALSE. The library is not
+ necessarily using ssl at the moment but at least asked to or means to use
+ it. See 'state' for the exact current state of the connection. */
BIT(use);
};
@@ -230,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;
+ 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 */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
@@ -244,8 +268,6 @@ struct ssl_config_data {
struct curl_blob *issuercert_blob;
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
- char *cert; /* client certificate file name */
- struct curl_blob *cert_blob;
char *cert_type; /* format for certificate (default: PEM)*/
char *key; /* private key file name */
struct curl_blob *key_blob;
@@ -271,7 +293,7 @@ struct ssl_general_config {
};
/* information stored about one single SSL session */
-struct curl_ssl_session {
+struct Curl_ssl_session {
char *name; /* host name for which this ID was used */
char *conn_to_host; /* host name for the connection (may be NULL) */
const char *scheme; /* protocol scheme used */
@@ -371,8 +393,8 @@ struct ntlmdata {
#else
unsigned int flags;
unsigned char nonce[8];
- void *target_info; /* TargetInfo received in the ntlm type-2 message */
unsigned int target_info_len;
+ void *target_info; /* TargetInfo received in the ntlm type-2 message */
#if defined(NTLM_WB_ENABLED)
/* used for communication with Samba's winbind daemon helper ntlm_auth */
@@ -472,6 +494,7 @@ struct ConnectBits {
EPRT doesn't work we disable it for the forthcoming
requests */
BIT(ftp_use_data_ssl); /* Enabled SSL for the data connection */
+ BIT(ftp_use_control_ssl); /* Enabled SSL for the control connection */
#endif
BIT(netrc); /* name+password provided by netrc */
BIT(bound); /* set true if bind() has already been done on this socket/
@@ -516,24 +539,24 @@ struct hostname {
#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
+#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
+#define USE_CURL_ASYNC
struct Curl_async {
char *hostname;
- int port;
struct Curl_dns_entry *dns;
+ struct thread_data *tdata;
+ void *resolver; /* resolver state, if it is used in the URL state -
+ ares_channel f.e. */
+ int port;
int status; /* if done is TRUE, this is the status from the callback */
- void *os_specific; /* 'struct thread_data' for Windows */
BIT(done); /* set TRUE when the lookup is complete */
};
+#endif
+
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
-/* These function pointer types are here only to allow easier typecasting
- within the source when we need to cast between data pointers (such as NULL)
- and function pointers. */
-typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
-typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
-
enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
@@ -580,8 +603,8 @@ struct dohdata {
struct curl_slist *headers;
struct dnsprobe probe[DOH_PROBE_SLOTS];
unsigned int pending; /* still outstanding requests */
- const char *host;
int port;
+ const char *host;
};
/*
@@ -606,6 +629,8 @@ struct SingleRequest {
following second response code) result in a
CURLE_GOT_NOTHING error code */
+ curl_off_t pendingheader; /* this many bytes left to send is actually
+ header and not body */
struct curltime start; /* transfer started at this time */
struct curltime now; /* current time */
enum {
@@ -622,6 +647,7 @@ struct SingleRequest {
Content-Range: header */
int httpcode; /* error code from the 'HTTP/1.? XXX' or
'RTSP/1.? XXX' line */
+ int keepon;
struct curltime start100; /* time stamp to wait for the 100 code from */
enum expect100 exp100; /* expect 100 continue state */
enum upgrade101 upgr101; /* 101 upgrade state */
@@ -630,7 +656,6 @@ struct SingleRequest {
struct contenc_writer *writer_stack;
time_t timeofdoc;
long bodywrites;
- int keepon;
char *location; /* This points to an allocated version of the Location:
header data */
char *newurl; /* Set to the new URL to use when a redirect or a retry is
@@ -645,10 +670,25 @@ struct SingleRequest {
and the 'upload_present' contains the number of bytes available at this
position */
char *upload_fromhere;
- void *protop; /* Allocated protocol-specific data. Each protocol
- handler makes sure this points to data it needs. */
+
+ /* Allocated protocol-specific data. Each protocol handler makes sure this
+ points to data it needs. */
+ union {
+ struct FILEPROTO *file;
+ struct FTP *ftp;
+ struct HTTP *http;
+ struct IMAP *imap;
+ struct ldapreqinfo *ldap;
+ struct MQTT *mqtt;
+ struct POP3 *pop3;
+ struct RTSP *rtsp;
+ struct smb_request *smb;
+ struct SMTP *smtp;
+ struct SSHPROTO *ssh;
+ struct TELNET *telnet;
+ } p;
#ifndef CURL_DISABLE_DOH
- struct dohdata doh; /* DoH specific data for this request */
+ struct dohdata *doh; /* DoH specific data for this request */
#endif
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
@@ -673,18 +713,20 @@ struct SingleRequest {
struct Curl_handler {
const char *scheme; /* URL scheme name. */
- /* Complement to setup_connection_internals(). */
- CURLcode (*setup_connection)(struct connectdata *);
+ /* Complement to setup_connection_internals(). This is done before the
+ transfer "owns" the connection. */
+ CURLcode (*setup_connection)(struct Curl_easy *data,
+ struct connectdata *conn);
/* These two functions MUST be set to be protocol dependent */
- CURLcode (*do_it)(struct connectdata *, bool *done);
- Curl_done_func done;
+ CURLcode (*do_it)(struct Curl_easy *data, bool *done);
+ CURLcode (*done)(struct Curl_easy *, CURLcode, bool);
/* If the curl_do() function is better made in two halves, this
* curl_do_more() function will be called afterwards, if set. For example
* for doing the FTP stuff after the PASV/PORT command.
*/
- Curl_do_more_func do_more;
+ CURLcode (*do_more)(struct Curl_easy *, int *);
/* This function *MAY* be set to a protocol-dependent function that is run
* after the connect() and everything is done, as a step in the connection.
@@ -692,39 +734,41 @@ struct Curl_handler {
* function completes before return. If it doesn't complete, the caller
* should call the curl_connecting() function until it is.
*/
- CURLcode (*connect_it)(struct connectdata *, bool *done);
+ CURLcode (*connect_it)(struct Curl_easy *data, bool *done);
/* See above. */
- CURLcode (*connecting)(struct connectdata *, bool *done);
- CURLcode (*doing)(struct connectdata *, bool *done);
+ CURLcode (*connecting)(struct Curl_easy *data, bool *done);
+ CURLcode (*doing)(struct Curl_easy *data, bool *done);
/* Called from the multi interface during the PROTOCONNECT phase, and it
should then return a proper fd set */
- int (*proto_getsock)(struct connectdata *conn,
- curl_socket_t *socks);
+ int (*proto_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DOING phase, and it should
then return a proper fd set */
- int (*doing_getsock)(struct connectdata *conn,
- curl_socket_t *socks);
+ int (*doing_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_MORE phase, and it should
then return a proper fd set */
- int (*domore_getsock)(struct connectdata *conn,
- curl_socket_t *socks);
+ int (*domore_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_DONE, PERFORM and
WAITPERFORM phases, and it should then return a proper fd set. Not setting
this will make libcurl use the generic default one. */
- int (*perform_getsock)(const struct connectdata *conn,
- curl_socket_t *socks);
+ int (*perform_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection. If the handler
- * is called because the connection has been considered dead, dead_connection
- * is set to TRUE.
+ * is called because the connection has been considered dead,
+ * dead_connection is set to TRUE. The connection is already disassociated
+ * from the transfer here.
*/
- CURLcode (*disconnect)(struct connectdata *, bool dead_connection);
+ CURLcode (*disconnect)(struct Curl_easy *, struct connectdata *,
+ bool dead_connection);
/* If used, this function gets called from transfer.c:readwrite_data() to
allow the protocol to do extra reads/writes */
@@ -734,12 +778,15 @@ struct Curl_handler {
/* This function can perform various checks on the connection. See
CONNCHECK_* for more information about the checks that can be performed,
and CONNRESULT_* for the results that can be returned. */
- unsigned int (*connection_check)(struct connectdata *conn,
+ unsigned int (*connection_check)(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform);
- long defport; /* Default port. */
+ 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_* */
};
@@ -802,7 +849,11 @@ struct proxy_info {
/* struct for HTTP CONNECT state data */
struct http_connect_state {
struct dynbuf rcvbuf;
- int keepon;
+ 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 */
@@ -839,13 +890,9 @@ enum connect_t {
#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) && \
((x) < CONNECT_DONE))
-#define SOCKS_REQUEST_BUFSIZE 600 /* room for large user/pw (255 max each) */
struct connstate {
enum connect_t state;
- unsigned char socksreq[SOCKS_REQUEST_BUFSIZE];
-
- /* CONNECT_SOCKS_SEND */
ssize_t outstanding; /* send this many bytes more */
unsigned char *outp; /* send from this pointer */
};
@@ -860,7 +907,7 @@ struct connectdata {
connection is used! */
struct Curl_easy *data;
struct connstate cnnct;
- struct curl_llist_element bundle_node; /* conncache */
+ struct Curl_llist_element bundle_node; /* conncache */
/* chunk is for HTTP chunked encoding, but is in the general connectdata
struct only because we can do just about any protocol through a HTTP proxy
@@ -892,11 +939,6 @@ struct connectdata {
struct Curl_addrinfo *ip_addr;
struct Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
- /* 'ip_addr_str' is the ip_addr data as a human readable string.
- It remains available as long as the connection does, which is longer than
- the ip_addr itself. */
- char ip_addr_str[MAX_IPADR_LEN];
-
unsigned int scope_id; /* Scope id for IPv6 */
enum {
@@ -919,7 +961,7 @@ struct connectdata {
struct proxy_info socks_proxy;
struct proxy_info http_proxy;
#endif
- long port; /* which port to use locally */
+ int port; /* which port to use locally - to connect to */
int remote_port; /* the remote port, not the proxy port! */
int conn_to_port; /* the remote port to connect to. valid only if
bits.conn_to_port is set */
@@ -934,14 +976,7 @@ struct connectdata {
these are updated with data which comes directly from the socket. */
char primary_ip[MAX_IPADR_LEN];
- long primary_port;
-
- /* 'local_ip' and 'local_port' get filled with local's numerical
- 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;
+ unsigned char ip_version; /* copied from the Curl_easy at creation time */
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
@@ -978,13 +1013,14 @@ struct connectdata {
#endif
struct ConnectBits bits; /* various state-flags for this connection */
+ /* The field below gets set in Curl_connecthost */
+ int num_addr; /* number of addresses to try to connect to */
/* connecttime: when connect() is called on the current IP address. Used to
be able to track when to move on to try next IP - but only when the multi
interface is used. */
struct curltime connecttime;
- /* The two fields below get set in Curl_connecthost */
- int num_addr; /* number of addresses to try to connect to */
+ /* The field below gets set in Curl_connecthost */
/* how long time in milliseconds to spend on trying to connect to each IP
address, per family */
timediff_t timeoutms_per_addr[2];
@@ -992,15 +1028,11 @@ struct connectdata {
const struct Curl_handler *handler; /* Connection's protocol handler */
const struct Curl_handler *given; /* The protocol first given */
- long ip_version; /* copied from the Curl_easy at creation time */
-
/* Protocols can use a custom keepalive mechanism to keep connections alive.
This allows those protocols to track the last time the keepalive mechanism
was used on this connection. */
struct curltime keepalive;
- long upkeep_interval_ms; /* Time between calls for connection upkeep. */
-
/**** curl_get() phase fields */
curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
@@ -1024,7 +1056,7 @@ struct connectdata {
struct kerberos5data krb5; /* variables into the structure definition, */
#endif /* however, some of them are ftp specific. */
- struct curl_llist easyq; /* List of easy handles using this connection */
+ struct Curl_llist easyq; /* List of easy handles using this connection */
curl_seek_callback seek_func; /* function that seeks the input */
void *seek_client; /* pointer to pass to the seek() above */
@@ -1051,9 +1083,6 @@ struct connectdata {
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif
- /* data used for the asynch name resolve callback */
- struct Curl_async async;
-
/* for chunked-encoded trailer */
struct dynbuf trailer;
@@ -1072,27 +1101,30 @@ struct connectdata {
struct mqtt_conn mqtt;
} proto;
- int cselect_bits; /* bitmask of socket events */
- int waitfor; /* current READ/WRITE bits to wait for */
-
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
- int socks5_gssapi_enctype;
+ struct http_connect_state *connect_state; /* for HTTP CONNECT */
+ struct connectbundle *bundle; /* The bundle we are member of */
+#ifdef USE_UNIX_SOCKETS
+ char *unix_domain_socket;
+#endif
+#ifdef USE_HYPER
+ /* if set, an alternative data transfer function */
+ Curl_datastream datastream;
#endif
-
/* When this connection is created, store the conditions for the local end
bind. This is stored before the actual bind and before any connection is
made and will serve the purpose of being used for comparison reasons so
that subsequent bound-requested connections aren't accidentally re-using
wrong connections. */
char *localdev;
- unsigned short localport;
int localportrange;
- struct http_connect_state *connect_state; /* for HTTP CONNECT */
- struct connectbundle *bundle; /* The bundle we are member of */
+ int cselect_bits; /* bitmask of socket events */
+ int waitfor; /* current READ/WRITE bits to wait for */
int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
-#ifdef USE_UNIX_SOCKETS
- char *unix_domain_socket;
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ int socks5_gssapi_enctype;
#endif
+ unsigned short localport;
};
/* The end of connectdata. */
@@ -1134,6 +1166,7 @@ struct PureInfo {
OpenSSL, GnuTLS, Schannel, NSS and GSKit
builds. Asked for with CURLOPT_CERTINFO
/ CURLINFO_CERTINFO */
+ CURLproxycode pxcode;
BIT(timecond); /* set to TRUE if the time condition didn't match, which
thus made the document NOT get fetched */
};
@@ -1187,17 +1220,6 @@ struct Progress {
};
typedef enum {
- HTTPREQ_NONE, /* first in list */
- HTTPREQ_GET,
- HTTPREQ_POST,
- HTTPREQ_POST_FORM, /* we make a difference internally */
- HTTPREQ_POST_MIME, /* we make a difference internally */
- HTTPREQ_PUT,
- HTTPREQ_HEAD,
- HTTPREQ_LAST /* last in list */
-} Curl_HttpReq;
-
-typedef enum {
RTSPREQ_NONE, /* first in list */
RTSPREQ_OPTIONS,
RTSPREQ_DESCRIBE,
@@ -1274,7 +1296,7 @@ typedef enum {
* One instance for each timeout an easy handle can set.
*/
struct time_node {
- struct curl_llist_element list;
+ struct Curl_llist_element list;
struct curltime time;
expire_id eid;
};
@@ -1294,7 +1316,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 */
@@ -1314,12 +1335,12 @@ struct UrlState {
strdup() data.
*/
int first_remote_port; /* remote port of the first (not followed) request */
- struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
+ struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
long sessionage; /* number of the most recent session */
- unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
- char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
+ 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 */
#ifdef HAVE_SIGNAL
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
void (*prev_signal)(int sig);
@@ -1329,8 +1350,9 @@ struct UrlState {
struct auth authhost; /* auth details for host */
struct auth authproxy; /* auth details for proxy */
- void *resolver; /* resolver state, if it is used in the URL state -
- ares_channel f.e. */
+#ifdef USE_CURL_ASYNC
+ struct Curl_async async; /* asynchronous name resolver data */
+#endif
#if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */
@@ -1338,7 +1360,7 @@ struct UrlState {
#endif /* USE_OPENSSL */
struct curltime expiretime; /* set this with Curl_expire() only */
struct Curl_tree timenode; /* for the splay stuff */
- struct curl_llist timeoutlist; /* list of pending timeouts */
+ struct Curl_llist timeoutlist; /* list of pending timeouts */
struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */
/* a place to store the most recently set FTP entrypath */
@@ -1347,8 +1369,7 @@ struct UrlState {
int httpversion; /* the lowest HTTP version*10 reported by any server
involved in this request */
-#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
- !defined(__SYMBIAN32__)
+#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
/* do FTP line-end conversions on most platforms */
#define CURL_DO_LINEEND_CONV
/* for FTP downloads: track CRLF sequences that span blocks */
@@ -1379,7 +1400,9 @@ 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
#ifndef CURL_DISABLE_HTTP
size_t trailers_bytes_sent;
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
@@ -1387,6 +1410,9 @@ struct UrlState {
#endif
trailers_state trailers_state; /* whether we are sending trailers
and what stage are we at */
+#ifdef USE_HYPER
+ CURLcode hresult; /* used to pass return codes back from hyper callbacks */
+#endif
/* Dynamically allocated strings, MUST be freed before this struct is
killed. */
@@ -1531,39 +1557,30 @@ enum dupstring {
STRING_RTSP_SESSION_ID, /* Session ID to use */
STRING_RTSP_STREAM_URI, /* Stream URI for this request */
STRING_RTSP_TRANSPORT, /* Transport for this session */
-
STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
-
STRING_PROXY_SERVICE_NAME, /* Proxy service name */
STRING_SERVICE_NAME, /* Service name */
STRING_MAIL_FROM,
STRING_MAIL_AUTH,
-
STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth <username> */
STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
STRING_TLSAUTH_PASSWORD_ORIG, /* 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 */
-
STRING_TARGET, /* CURLOPT_REQUEST_TARGET */
STRING_DOH, /* CURLOPT_DOH_URL */
-
STRING_ALTSVC, /* CURLOPT_ALTSVC */
-
+ STRING_HSTS, /* CURLOPT_HSTS */
STRING_SASL_AUTHZID, /* CURLOPT_SASL_AUTHZID */
-
- STRING_TEMP_URL, /* temp URL storage for proxy use */
-
STRING_DNS_SERVERS,
STRING_DNS_INTERFACE,
STRING_DNS_LOCAL_IP4,
STRING_DNS_LOCAL_IP6,
+ STRING_SSL_EC_CURVES,
/* -- end of null-terminated strings -- */
@@ -1573,6 +1590,7 @@ enum dupstring {
STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
+ STRING_AWS_SIGV4, /* Parameters for V4 signature */
STRING_LAST /* not used, just an end-of-list marker */
};
@@ -1647,7 +1665,12 @@ struct UserDefined {
curl_conv_callback convtonetwork;
/* function to convert from UTF-8 encoding: */
curl_conv_callback convfromutf8;
-
+#ifdef USE_HSTS
+ curl_hstsread_callback hsts_read;
+ void *hsts_read_userp;
+ curl_hstswrite_callback hsts_write;
+ void *hsts_write_userp;
+#endif
void *progress_client; /* pointer to pass to the progress callback */
void *ioctl_client; /* pointer to pass to the ioctl callback */
long timeout; /* in milliseconds, 0 means no timeout */
@@ -1683,8 +1706,11 @@ struct UserDefined {
struct curl_slist *connect_to; /* list of host:port mappings to override
the hostname and port to connect to */
curl_TimeCond timecondition; /* kind of time/date comparison */
+ curl_proxytype proxytype; /* what kind of proxy that is in use */
time_t timevalue; /* what time to compare with */
+#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) */
struct ssl_config_data ssl; /* user defined SSL stuff */
@@ -1692,15 +1718,14 @@ struct UserDefined {
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
#endif
struct ssl_general_config general_ssl; /* general user defined SSL stuff */
- curl_proxytype proxytype; /* what kind of proxy that is in use */
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 */
void *private_data; /* application-private data */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
- long ipver; /* the CURL_IPRESOLVE_* defines in the public header file
- 0 - whatever, 1 - v2, 2 - v6 */
+ unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header
+ file 0 - whatever, 1 - v2, 2 - v6 */
curl_off_t max_filesize; /* Maximum file size to download */
#ifndef CURL_DISABLE_FTP
curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
@@ -1839,7 +1864,7 @@ struct UserDefined {
};
struct Names {
- struct curl_hash *hostcache;
+ struct Curl_hash *hostcache;
enum {
HCACHE_NONE, /* not pointing to anything */
HCACHE_MULTI, /* points to a shared one in the multi handle */
@@ -1858,13 +1883,17 @@ struct Names {
*/
struct Curl_easy {
+ /* First a simple identifier to easier detect if a user mix up this easy
+ handle with a multi handle. Set this to CURLEASY_MAGIC_NUMBER */
+ unsigned int magic;
+
/* first, two fields for the linked list of these */
struct Curl_easy *next;
struct Curl_easy *prev;
struct connectdata *conn;
- struct curl_llist_element connect_queue;
- struct curl_llist_element conn_queue; /* list per connectdata */
+ struct Curl_llist_element connect_queue;
+ struct Curl_llist_element conn_queue; /* list per connectdata */
CURLMstate mstate; /* the handle's state */
CURLcode result; /* previous result */
@@ -1898,7 +1927,10 @@ struct Curl_easy {
NOTE that the 'cookie' field in the
UserDefined struct defines if the "engine"
is to be used or not. */
-#ifdef USE_ALTSVC
+#ifdef USE_HSTS
+ struct hsts *hsts;
+#endif
+#ifndef CURL_DISABLE_ALTSVC
struct altsvcinfo *asi; /* the alt-svc cache */
#endif
struct Progress progress; /* for all the progress meter data */
@@ -1915,7 +1947,9 @@ struct Curl_easy {
iconv_t inbound_cd; /* for translating from the network encoding */
iconv_t utf8_cd; /* for translating to UTF8 */
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
- unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */
+#ifdef USE_HYPER
+ struct hyptransfer hyp;
+#endif
};
#define LIBCURL_NAME "libcurl"
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index 3a5c9430f..620dba03e 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/cram.c b/Utilities/cmcurl/lib/vauth/cram.c
index 717d7f093..1a376259a 100644
--- a/Utilities/cmcurl/lib/vauth/cram.c
+++ b/Utilities/cmcurl/lib/vauth/cram.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index b9210a8fe..559852fcb 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -61,12 +61,14 @@
It converts digest text to ASCII so the MD5 will be correct for
what ultimately goes over the network.
*/
-#define CURL_OUTPUT_DIGEST_CONV(a, b) \
- result = Curl_convert_to_network(a, b, strlen(b)); \
- if(result) { \
- free(b); \
- return result; \
- }
+#define CURL_OUTPUT_DIGEST_CONV(a, b) \
+ do { \
+ result = Curl_convert_to_network(a, b, strlen(b)); \
+ if(result) { \
+ free(b); \
+ return result; \
+ } \
+ } while(0)
#endif /* !USE_WINDOWS_SSPI */
bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
diff --git a/Utilities/cmcurl/lib/vauth/digest.h b/Utilities/cmcurl/lib/vauth/digest.h
index cc05fdb76..ee373cd82 100644
--- a/Utilities/cmcurl/lib/vauth/digest.h
+++ b/Utilities/cmcurl/lib/vauth/digest.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index 4998306ce..dad947a37 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -10,7 +10,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -38,6 +38,7 @@
#include "sendf.h"
#include "strdup.h"
#include "strcase.h"
+#include "strerror.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -134,7 +135,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(status != SEC_E_OK) {
free(input_token);
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
@@ -220,6 +221,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
status == SEC_I_COMPLETE_AND_CONTINUE)
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ char buffer[STRERROR_LEN];
+
s_pSecFn->FreeCredentialsHandle(&credentials);
Curl_sspi_free_identity(p_identity);
free(spn);
@@ -229,6 +232,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
+ infof(data, "schannel: InitializeSecurityContext failed: %s\n",
+ Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+
return CURLE_AUTH_ERROR;
}
@@ -433,7 +439,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
&SecurityPackage);
if(status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
@@ -611,6 +617,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
status == SEC_I_COMPLETE_AND_CONTINUE)
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ char buffer[STRERROR_LEN];
+
s_pSecFn->FreeCredentialsHandle(&credentials);
Curl_sspi_free_identity(p_identity);
@@ -621,6 +629,9 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
+ infof(data, "schannel: InitializeSecurityContext failed: %s\n",
+ Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
index 95bab0e2e..0412815e9 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
@@ -6,11 +6,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index 1fb6257ea..b2d163534 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -125,7 +125,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
TEXT(SP_NAME_KERBEROS),
&SecurityPackage);
if(status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index ecfeacb9a..a3117f3fe 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -497,7 +497,6 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
const char *passwdp,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
-
{
/* NTLM type-3 message structure:
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.h b/Utilities/cmcurl/lib/vauth/ntlm.h
index 1136b0f8d..8ec23ad4f 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.h
+++ b/Utilities/cmcurl/lib/vauth/ntlm.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index 84ea51dad..07dc97398 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -106,7 +106,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
&SecurityPackage);
if(status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/oauth2.c b/Utilities/cmcurl/lib/vauth/oauth2.c
index b4e9f8e70..ca5842a7c 100644
--- a/Utilities/cmcurl/lib/vauth/oauth2.c
+++ b/Utilities/cmcurl/lib/vauth/oauth2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
index ed7ce029e..120925ff3 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index 194f250f8..4aa1ba957 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -130,7 +130,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
TEXT(SP_NAME_NEGOTIATE),
&SecurityPackage);
if(nego->status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/vauth.c b/Utilities/cmcurl/lib/vauth/vauth.c
index d98e66c68..129b8f8b5 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.c
+++ b/Utilities/cmcurl/lib/vauth/vauth.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/vauth.h b/Utilities/cmcurl/lib/vauth/vauth.h
index a1a557d2a..f25cfc329 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.h
+++ b/Utilities/cmcurl/lib/vauth/vauth.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2020, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index 4f6dda24f..a9102ec1e 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -31,8 +31,8 @@
#include "curl_printf.h"
#ifdef USE_ARES
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- (defined(WIN32) || defined(__SYMBIAN32__))
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ defined(WIN32)
# define CARES_STATICLIB
# endif
# include <ares.h>
@@ -56,10 +56,6 @@
#ifdef HAVE_ZLIB_H
#include <zlib.h>
-#ifdef __SYMBIAN32__
-/* zlib pollutes the namespace with this definition */
-#undef WIN32
-#endif
#endif
#ifdef HAVE_BROTLI
@@ -104,7 +100,7 @@ static size_t zstd_version(char *buf, size_t bufsz)
* zeros in the data.
*/
-#define VERSION_PARTS 14 /* number of substrings we can concatenate */
+#define VERSION_PARTS 15 /* number of substrings we can concatenate */
char *curl_version(void)
{
@@ -148,6 +144,9 @@ char *curl_version(void)
#ifdef USE_LIBRTMP
char rtmp_version[40];
#endif
+#ifdef USE_HYPER
+ char hyper_buf[30];
+#endif
int i = 0;
int j;
@@ -232,6 +231,10 @@ char *curl_version(void)
src[i++] = rtmp_version;
}
#endif
+#ifdef USE_HYPER
+ msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version());
+ src[i++] = hyper_buf;
+#endif
DEBUGASSERT(i <= VERSION_PARTS);
@@ -278,6 +281,9 @@ static const char * const protocols[] = {
#ifndef CURL_DISABLE_GOPHER
"gopher",
#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
+ "gophers",
+#endif
#ifndef CURL_DISABLE_HTTP
"http",
#endif
@@ -298,7 +304,7 @@ static const char * const protocols[] = {
"ldaps",
#endif
#endif
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
"mqtt",
#endif
#ifndef CURL_DISABLE_POP3
@@ -319,9 +325,8 @@ static const char * const protocols[] = {
#ifdef USE_SSH
"sftp",
#endif
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
- (CURL_SIZEOF_CURL_OFF_T > 4) && \
- (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4)
"smb",
# ifdef USE_SSL
"smbs",
@@ -399,7 +404,7 @@ static curl_version_info_data version_info = {
#if defined(USE_TLS_SRP)
| CURL_VERSION_TLSAUTH_SRP
#endif
-#if defined(USE_NGHTTP2)
+#if defined(USE_NGHTTP2) || defined(USE_HYPER)
| CURL_VERSION_HTTP2
#endif
#if defined(ENABLE_QUIC)
@@ -420,9 +425,12 @@ static curl_version_info_data version_info = {
#if defined(HAVE_ZSTD)
| CURL_VERSION_ZSTD
#endif
-#if defined(USE_ALTSVC)
+#ifndef CURL_DISABLE_ALTSVC
| CURL_VERSION_ALTSVC
#endif
+#if defined(USE_HSTS)
+ | CURL_VERSION_HSTS
+#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
@@ -449,7 +457,8 @@ static curl_version_info_data version_info = {
NULL,
#endif
0, /* zstd_ver_num */
- NULL /* zstd version */
+ NULL, /* zstd version */
+ NULL /* Hyper version */
};
curl_version_info_data *curl_version_info(CURLversion stamp)
@@ -471,15 +480,16 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
static char zstd_buffer[80];
#endif
-
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
+#ifndef CURL_DISABLE_PROXY
if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
version_info.features |= CURL_VERSION_HTTPS_PROXY;
else
version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
#endif
+#endif
#ifdef HAVE_LIBZ
version_info.libz_version = zlibVersion();
@@ -544,6 +554,14 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
}
#endif
+#ifdef USE_HYPER
+ {
+ static char hyper_buffer[30];
+ msnprintf(hyper_buffer, sizeof(hyper_buffer), "Hyper/%s", hyper_version());
+ version_info.hyper_version = hyper_buffer;
+ }
+#endif
+
(void)stamp; /* avoid compiler warnings, we don't use this */
return &version_info;
}
diff --git a/Utilities/cmcurl/lib/version_win32.c b/Utilities/cmcurl/lib/version_win32.c
index 6561d36be..b8157e989 100644
--- a/Utilities/cmcurl/lib/version_win32.c
+++ b/Utilities/cmcurl/lib/version_win32.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/version_win32.h b/Utilities/cmcurl/lib/version_win32.h
index 94cc62667..9b1bd8887 100644
--- a/Utilities/cmcurl/lib/version_win32.h
+++ b/Utilities/cmcurl/lib/version_win32.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c
index 20ee08dd6..d4d0e8bf4 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -87,10 +87,10 @@ struct h3out {
"+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1"
#endif
-static CURLcode ng_process_ingress(struct connectdata *conn,
+static CURLcode ng_process_ingress(struct Curl_easy *data,
curl_socket_t sockfd,
struct quicsocket *qs);
-static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
+static CURLcode ng_flush_egress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs);
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
size_t datalen, void *user_data,
@@ -126,7 +126,7 @@ quic_from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level)
case ssl_encryption_handshake:
return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
case ssl_encryption_application:
- return NGTCP2_CRYPTO_LEVEL_APP;
+ return NGTCP2_CRYPTO_LEVEL_APPLICATION;
default:
assert(0);
}
@@ -143,7 +143,7 @@ quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level)
case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE:
return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
case GNUTLS_ENCRYPTION_LEVEL_APPLICATION:
- return NGTCP2_CRYPTO_LEVEL_APP;
+ return NGTCP2_CRYPTO_LEVEL_APPLICATION;
default:
assert(0);
}
@@ -170,20 +170,22 @@ static void quic_settings(struct quicsocket *qs,
uint64_t stream_buffer_size)
{
ngtcp2_settings *s = &qs->settings;
+ ngtcp2_transport_params *t = &qs->transport_params;
ngtcp2_settings_default(s);
+ ngtcp2_transport_params_default(t);
#ifdef DEBUG_NGTCP2
s->log_printf = quic_printf;
#else
s->log_printf = NULL;
#endif
s->initial_ts = timestamp();
- s->transport_params.initial_max_stream_data_bidi_local = stream_buffer_size;
- s->transport_params.initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
- s->transport_params.initial_max_stream_data_uni = QUIC_MAX_STREAMS;
- s->transport_params.initial_max_data = QUIC_MAX_DATA;
- s->transport_params.initial_max_streams_bidi = 1;
- s->transport_params.initial_max_streams_uni = 3;
- s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT;
+ t->initial_max_stream_data_bidi_local = stream_buffer_size;
+ t->initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
+ t->initial_max_stream_data_uni = QUIC_MAX_STREAMS;
+ t->initial_max_data = QUIC_MAX_DATA;
+ t->initial_max_streams_bidi = 1;
+ t->initial_max_streams_uni = 3;
+ t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
if(qs->qlogfd != -1) {
s->qlog.write = qlog_callback;
}
@@ -265,7 +267,7 @@ static int quic_set_encryption_secrets(SSL *ssl,
qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
return 0;
- if(level == NGTCP2_CRYPTO_LEVEL_APP) {
+ if(level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
if(init_ngh3_conn(qs) != CURLE_OK)
return 0;
}
@@ -349,14 +351,8 @@ static int quic_init_ssl(struct quicsocket *qs)
SSL_set_app_data(qs->ssl, qs);
SSL_set_connect_state(qs->ssl);
- switch(qs->version) {
-#ifdef NGTCP2_PROTO_VER
- case NGTCP2_PROTO_VER:
- alpn = (const uint8_t *)NGHTTP3_ALPN_H3;
- alpnlen = sizeof(NGHTTP3_ALPN_H3) - 1;
- break;
-#endif
- }
+ alpn = (const uint8_t *)NGHTTP3_ALPN_H3;
+ alpnlen = sizeof(NGHTTP3_ALPN_H3) - 1;
if(alpn)
SSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen);
@@ -382,7 +378,7 @@ static int secret_func(gnutls_session_t ssl,
qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
return 0;
- if(level == NGTCP2_CRYPTO_LEVEL_APP) {
+ if(level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
if(init_ngh3_conn(qs) != CURLE_OK)
return -1;
}
@@ -532,15 +528,9 @@ static int quic_init_ssl(struct quicsocket *qs)
return 1;
}
- switch(qs->version) {
-#ifdef NGTCP2_PROTO_VER
- case NGTCP2_PROTO_VER:
- /* 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;
- break;
-#endif
- }
+ /* 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;
if(alpn.data)
gnutls_alpn_set_protocols(qs->ssl, &alpn, 1, 0);
@@ -568,10 +558,8 @@ cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level,
static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
- struct quicsocket *qs = (struct quicsocket *)user_data;
+ (void)user_data;
(void)tconn;
- infof(qs->conn->data, "QUIC handshake is completed\n");
-
return 0;
}
@@ -599,8 +587,6 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
nconsumed =
nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin);
if(nconsumed < 0) {
- failf(qs->conn->data, "nghttp3_conn_read_stream returned error: %s\n",
- nghttp3_strerror((int)nconsumed));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -628,8 +614,6 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen);
if(rv != 0) {
- failf(qs->conn->data, "nghttp3_conn_add_ack_offset returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -649,8 +633,6 @@ 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) {
- failf(qs->conn->data, "nghttp3_conn_close_stream returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -670,8 +652,6 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
if(rv != 0) {
- failf(qs->conn->data, "nghttp3_conn_reset_stream returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -701,8 +681,6 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id);
if(rv != 0) {
- failf(qs->conn->data, "nghttp3_conn_unblock_stream returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -713,23 +691,23 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
uint8_t *token, size_t cidlen,
void *user_data)
{
- struct quicsocket *qs = (struct quicsocket *)user_data;
CURLcode result;
(void)tconn;
+ (void)user_data;
- result = Curl_rand(qs->conn->data, cid->data, cidlen);
+ result = Curl_rand(NULL, cid->data, cidlen);
if(result)
return NGTCP2_ERR_CALLBACK_FAILURE;
cid->datalen = cidlen;
- result = Curl_rand(qs->conn->data, token, NGTCP2_STATELESS_RESET_TOKENLEN);
+ result = Curl_rand(NULL, token, NGTCP2_STATELESS_RESET_TOKENLEN);
if(result)
return NGTCP2_ERR_CALLBACK_FAILURE;
return 0;
}
-static ngtcp2_conn_callbacks ng_callbacks = {
+static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_client_initial_cb,
NULL, /* recv_client_initial */
cb_recv_crypto_data,
@@ -767,7 +745,8 @@ static ngtcp2_conn_callbacks ng_callbacks = {
/*
* Might be called twice for happy eyeballs.
*/
-CURLcode Curl_quic_connect(struct connectdata *conn,
+CURLcode Curl_quic_connect(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t sockfd,
int sockindex,
const struct sockaddr *addr,
@@ -777,14 +756,13 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
int rv;
CURLcode result;
ngtcp2_path path; /* TODO: this must be initialized properly */
- struct Curl_easy *data = conn->data;
struct quicsocket *qs = &conn->hequic[sockindex];
char ipbuf[40];
long port;
int qfd;
if(qs->conn)
- Curl_quic_disconnect(conn, sockindex);
+ Curl_quic_disconnect(data, conn, sockindex);
qs->conn = conn;
/* extract the used address as a string */
@@ -798,7 +776,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
infof(data, "Connect socket %d over QUIC to %s:%ld\n",
sockfd, ipbuf, port);
- qs->version = NGTCP2_PROTO_VER;
+ qs->version = NGTCP2_PROTO_VER_MAX;
#ifdef USE_OPENSSL
qs->sslctx = quic_ssl_ctx(data);
if(!qs->sslctx)
@@ -828,16 +806,13 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
if(rv == -1)
return CURLE_QUIC_CONNECT_ERROR;
- ngtcp2_addr_init(&path.local, &qs->local_addr, qs->local_addrlen, NULL);
+ ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
+ qs->local_addrlen, NULL);
ngtcp2_addr_init(&path.remote, addr, addrlen, NULL);
-#ifdef NGTCP2_PROTO_VER
-#define QUICVER NGTCP2_PROTO_VER
-#else
-#error "unsupported ngtcp2 version"
-#endif
- rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, QUICVER,
- &ng_callbacks, &qs->settings, NULL, qs);
+ rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path,
+ NGTCP2_PROTO_VER_MIN, &ng_callbacks,
+ &qs->settings, &qs->transport_params, NULL, qs);
if(rc)
return CURLE_QUIC_CONNECT_ERROR;
@@ -858,9 +833,10 @@ int Curl_quic_ver(char *p, size_t len)
ng2->version_str, ht3->version_str);
}
-static int ng_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks)
{
- struct SingleRequest *k = &conn->data->req;
+ struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET];
@@ -876,12 +852,6 @@ static int ng_getsock(struct connectdata *conn, curl_socket_t *socks)
return bitmap;
}
-static int ng_perform_getsock(const struct connectdata *conn,
- curl_socket_t *socks)
-{
- return ng_getsock((struct connectdata *)conn, socks);
-}
-
static void qs_disconnect(struct quicsocket *qs)
{
int i;
@@ -912,25 +882,30 @@ static void qs_disconnect(struct quicsocket *qs)
#endif
}
-void Curl_quic_disconnect(struct connectdata *conn,
+void Curl_quic_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
int tempindex)
{
+ (void)data;
if(conn->transport == TRNSPRT_QUIC)
qs_disconnect(&conn->hequic[tempindex]);
}
-static CURLcode ng_disconnect(struct connectdata *conn,
+static CURLcode ng_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
(void)dead_connection;
- Curl_quic_disconnect(conn, 0);
- Curl_quic_disconnect(conn, 1);
+ Curl_quic_disconnect(data, conn, 0);
+ Curl_quic_disconnect(data, conn, 1);
return CURLE_OK;
}
-static unsigned int ng_conncheck(struct connectdata *conn,
+static unsigned int ng_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
+ (void)data;
(void)conn;
(void)checks_to_perform;
return CONNRESULT_NONE;
@@ -948,12 +923,13 @@ static const struct Curl_handler Curl_handler_http3 = {
ng_getsock, /* proto_getsock */
ng_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ng_perform_getsock, /* perform_getsock */
+ ng_getsock, /* perform_getsock */
ng_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ng_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
@@ -962,7 +938,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
(void)conn;
(void)stream_id;
(void)app_error_code;
@@ -1008,7 +984,7 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream_id,
void *user_data, void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
CURLcode result = CURLE_OK;
(void)conn;
@@ -1067,7 +1043,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
void *user_data, void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
CURLcode result = CURLE_OK;
(void)conn;
(void)stream_id;
@@ -1091,7 +1067,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
CURLcode result = CURLE_OK;
(void)conn;
(void)stream_id;
@@ -1148,7 +1124,7 @@ static int cb_h3_send_stop_sending(nghttp3_conn *conn, int64_t stream_id,
return 0;
}
-static nghttp3_conn_callbacks ngh3_callbacks = {
+static nghttp3_callbacks ngh3_callbacks = {
cb_h3_acked_stream_data, /* acked_stream_data */
cb_h3_stream_close,
cb_h3_recv_data,
@@ -1166,6 +1142,7 @@ static nghttp3_conn_callbacks ngh3_callbacks = {
cb_h3_send_stop_sending,
NULL, /* push_stream */
NULL, /* end_stream */
+ NULL, /* reset_stream */
};
static int init_ngh3_conn(struct quicsocket *qs)
@@ -1175,11 +1152,10 @@ static int init_ngh3_conn(struct quicsocket *qs)
int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;
if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) {
- failf(qs->conn->data, "too few available QUIC streams");
return CURLE_QUIC_CONNECT_ERROR;
}
- nghttp3_conn_settings_default(&qs->h3settings);
+ nghttp3_settings_default(&qs->h3settings);
rc = nghttp3_conn_client_new(&qs->h3conn,
&ngh3_callbacks,
@@ -1248,14 +1224,15 @@ static size_t drain_overflow_buffer(struct HTTP *stream)
}
/* incoming data frames on the h3 stream */
-static ssize_t ngh3_stream_recv(struct connectdata *conn,
+static ssize_t ngh3_stream_recv(struct Curl_easy *data,
int sockindex,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct quicsocket *qs = conn->quic;
if(!stream->memlen) {
@@ -1270,11 +1247,11 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
as possible to the receive buffer before receiving more */
drain_overflow_buffer(stream);
- if(ng_process_ingress(conn, sockfd, qs)) {
+ if(ng_process_ingress(data, sockfd, qs)) {
*curlcode = CURLE_RECV_ERROR;
return -1;
}
- if(ng_flush_egress(conn, sockfd, qs)) {
+ if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -1290,7 +1267,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
/* extend the stream window with the data we're consuming and send out
any additional packets to tell the server that we can receive more */
extend_stream_window(qs->qconn, stream);
- if(ng_flush_egress(conn, sockfd, qs)) {
+ if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -1302,7 +1279,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
return 0;
}
- infof(conn->data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
+ infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
*curlcode = CURLE_AGAIN;
return -1;
}
@@ -1313,9 +1290,8 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
- (void)conn;
- (void)stream_id;
+ struct HTTP *stream = data->req.p.http;
+ int rv;
(void)user_data;
if(!data->set.postfields) {
@@ -1324,6 +1300,13 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
"cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
datalen, stream->h3out->used));
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
+
+ if(stream->h3out->used == 0) {
+ rv = nghttp3_conn_resume_stream(conn, stream_id);
+ if(rv != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+ }
}
return 0;
}
@@ -1335,7 +1318,7 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_easy *data = stream_user_data;
size_t nread;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
(void)conn;
(void)stream_id;
(void)user_data;
@@ -1359,13 +1342,14 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
nread = H3_SEND_SIZE - out->windex;
memcpy(&out->buf[out->windex], stream->upload_mem, nread);
- out->windex += nread;
- out->used += nread;
/* that's the chunk we return to nghttp3 */
vec[0].base = &out->buf[out->windex];
vec[0].len = nread;
+ out->windex += nread;
+ out->used += nread;
+
if(out->windex == H3_SEND_SIZE)
out->windex = 0; /* wrap */
stream->upload_mem += nread;
@@ -1383,7 +1367,7 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
(stream->upload_left <= 0)) {
H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
*pflags = NGHTTP3_DATA_FLAG_EOF;
- return 0;
+ return nread ? 1 : 0;
}
else if(!nread) {
return NGHTTP3_ERR_WOULDBLOCK;
@@ -1395,10 +1379,11 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
field list. */
#define AUTHORITY_DST_IDX 3
-static CURLcode http_request(struct connectdata *conn, const void *mem,
+static CURLcode http_request(struct Curl_easy *data, const void *mem,
size_t len)
{
- struct HTTP *stream = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *stream = data->req.p.http;
size_t nheader;
size_t i;
size_t authority_idx;
@@ -1406,7 +1391,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
char *end, *line_end;
struct quicsocket *qs = conn->quic;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
nghttp3_nv *nva = NULL;
int64_t stream3_id;
int rc;
@@ -1414,7 +1398,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL);
if(rc) {
- failf(conn->data, "can get bidi streams");
+ failf(data, "can get bidi streams");
result = CURLE_SEND_ERROR;
goto fail;
}
@@ -1573,7 +1557,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
if(acc > MAX_ACC) {
infof(data, "http_request: Warning: The cumulative length of all "
- "headers exceeds %zu bytes and that could cause the "
+ "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC);
}
}
@@ -1600,8 +1584,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
stream->h3out = h3out;
rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
- nva, nheader, &data_reader,
- conn->data);
+ nva, nheader, &data_reader, data);
if(rc) {
result = CURLE_SEND_ERROR;
goto fail;
@@ -1611,9 +1594,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
default:
stream->upload_left = 0; /* nothing left to send */
rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
- nva, nheader,
- NULL, /* no body! */
- conn->data);
+ nva, nheader, NULL, data);
if(rc) {
result = CURLE_SEND_ERROR;
goto fail;
@@ -1632,19 +1613,20 @@ fail:
free(nva);
return result;
}
-static ssize_t ngh3_stream_send(struct connectdata *conn,
+static ssize_t ngh3_stream_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
ssize_t sent;
+ struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
if(!stream->h3req) {
- CURLcode result = http_request(conn, mem, len);
+ CURLcode result = http_request(data, mem, len);
if(result) {
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -1652,7 +1634,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn,
sent = len;
}
else {
- H3BUGF(infof(conn->data, "ngh3_stream_send() wants to send %zd bytes\n",
+ H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n",
len));
if(!stream->upload_len) {
stream->upload_mem = mem;
@@ -1666,7 +1648,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn,
}
}
- if(ng_flush_egress(conn, sockfd, qs)) {
+ if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -1684,13 +1666,13 @@ static void ng_has_connected(struct connectdata *conn, int tempindex)
conn->httpversion = 30;
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
conn->quic = &conn->hequic[tempindex];
- DEBUGF(infof(conn->data, "ngtcp2 established connection!\n"));
}
/*
* There can be multiple connection attempts going on in parallel.
*/
-CURLcode Curl_quic_is_connected(struct connectdata *conn,
+CURLcode Curl_quic_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *done)
{
@@ -1698,11 +1680,11 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
struct quicsocket *qs = &conn->hequic[sockindex];
curl_socket_t sockfd = conn->tempsock[sockindex];
- result = ng_process_ingress(conn, sockfd, qs);
+ result = ng_process_ingress(data, sockfd, qs);
if(result)
goto error;
- result = ng_flush_egress(conn, sockfd, qs);
+ result = ng_flush_egress(data, sockfd, qs);
if(result)
goto error;
@@ -1718,7 +1700,8 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
}
-static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
+static CURLcode ng_process_ingress(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct quicsocket *qs)
{
ssize_t recvd;
@@ -1729,10 +1712,11 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
socklen_t remote_addrlen;
ngtcp2_path path;
ngtcp2_tstamp ts = timestamp();
+ ngtcp2_pkt_info pi = { 0 };
for(;;) {
remote_addrlen = sizeof(remote_addr);
- while((recvd = recvfrom(sockfd, buf, bufsize, 0,
+ while((recvd = recvfrom(sockfd, (char *)buf, bufsize, 0,
(struct sockaddr *)&remote_addr,
&remote_addrlen)) == -1 &&
SOCKERRNO == EINTR)
@@ -1741,16 +1725,16 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK)
break;
- failf(conn->data, "ngtcp2: recvfrom() unexpectedly returned %d", recvd);
+ failf(data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd);
return CURLE_RECV_ERROR;
}
- ngtcp2_addr_init(&path.local, &qs->local_addr,
+ ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
qs->local_addrlen, NULL);
ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr,
remote_addrlen, NULL);
- rv = ngtcp2_conn_read_pkt(qs->qconn, &path, buf, recvd, ts);
+ rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
if(rv != 0) {
/* TODO Send CONNECTION_CLOSE if possible */
return CURLE_RECV_ERROR;
@@ -1760,7 +1744,8 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
return CURLE_OK;
}
-static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
+static CURLcode ng_flush_egress(struct Curl_easy *data,
+ int sockfd,
struct quicsocket *qs)
{
int rv;
@@ -1778,8 +1763,9 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
int fin;
nghttp3_vec vec[16];
ssize_t ndatalen;
+ uint32_t flags;
- switch(qs->local_addr.sa_family) {
+ switch(qs->local_addr.ss_family) {
case AF_INET:
pktlen = NGTCP2_MAX_PKTLEN_IPV4;
break;
@@ -1794,7 +1780,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
if(rv != 0) {
- failf(conn->data, "ngtcp2_conn_handle_expiry returned error: %s\n",
+ failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
ngtcp2_strerror(rv));
return CURLE_SEND_ERROR;
}
@@ -1803,75 +1789,68 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
for(;;) {
outlen = -1;
+ veccnt = 0;
+ stream_id = -1;
+ fin = 0;
+
if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) {
veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
sizeof(vec) / sizeof(vec[0]));
if(veccnt < 0) {
- failf(conn->data, "nghttp3_conn_writev_stream returned error: %s\n",
+ failf(data, "nghttp3_conn_writev_stream returned error: %s",
nghttp3_strerror((int)veccnt));
return CURLE_SEND_ERROR;
}
- else if(veccnt > 0) {
- uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
- (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- outlen =
- ngtcp2_conn_writev_stream(qs->qconn, &ps.path,
- out, pktlen, &ndatalen,
- flags, stream_id,
- (const ngtcp2_vec *)vec, veccnt, ts);
- if(outlen == 0) {
- break;
- }
- if(outlen < 0) {
- if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
- outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
- assert(ndatalen == -1);
- rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
- if(rv != 0) {
- failf(conn->data,
- "nghttp3_conn_block_stream returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- }
- else if(outlen == NGTCP2_ERR_WRITE_MORE) {
- assert(ndatalen > 0);
- rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id,
- ndatalen);
- if(rv != 0) {
- failf(conn->data,
- "nghttp3_conn_add_write_offset returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- }
- else {
- assert(ndatalen == -1);
- failf(conn->data, "ngtcp2_conn_writev_stream returned error: %s\n",
- ngtcp2_strerror((int)outlen));
- return CURLE_SEND_ERROR;
- }
+ }
+
+ flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
+ (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
+ outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen,
+ &ndatalen, flags, stream_id,
+ (const ngtcp2_vec *)vec, veccnt, ts);
+ if(outlen == 0) {
+ break;
+ }
+ if(outlen < 0) {
+ if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
+ outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
+ assert(ndatalen == -1);
+ rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_block_stream returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
}
- else {
- assert(ndatalen == -1);
+ continue;
+ }
+ else if(outlen == NGTCP2_ERR_WRITE_MORE) {
+ assert(ndatalen >= 0);
+ rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
}
+ continue;
}
- }
- if(outlen < 0) {
- outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, out, pktlen, ts);
- if(outlen < 0) {
- failf(conn->data, "ngtcp2_conn_write_pkt returned error: %s\n",
+ else {
+ assert(ndatalen == -1);
+ failf(data, "ngtcp2_conn_writev_stream returned error: %s",
ngtcp2_strerror((int)outlen));
return CURLE_SEND_ERROR;
}
- if(outlen == 0)
- break;
+ }
+ else if(ndatalen >= 0) {
+ rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
+ }
}
memcpy(&remote_addr, ps.path.remote.addr, ps.path.remote.addrlen);
- while((sent = send(sockfd, out, outlen, 0)) == -1 &&
+ while((sent = send(sockfd, (const char *)out, outlen, 0)) == -1 &&
SOCKERRNO == EINTR)
;
@@ -1881,7 +1860,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
break;
}
else {
- failf(conn->data, "send() returned %zd (errno %d)\n", sent,
+ failf(data, "send() returned %zd (errno %d)", sent,
SOCKERRNO);
return CURLE_SEND_ERROR;
}
@@ -1896,7 +1875,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
else {
timeout = expiry - ts;
}
- Curl_expire(conn->data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
+ Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
}
return CURLE_OK;
@@ -1905,11 +1884,13 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
/*
* Called from transfer.c:done_sending when we stop HTTP/3 uploading.
*/
-CURLcode Curl_quic_done_sending(struct connectdata *conn)
+CURLcode Curl_quic_done_sending(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
+ DEBUGASSERT(conn);
if(conn->handler == &Curl_handler_http3) {
/* only for HTTP/3 transfers */
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct quicsocket *qs = conn->quic;
stream->upload_done = TRUE;
(void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
@@ -1926,7 +1907,7 @@ void Curl_quic_done(struct Curl_easy *data, bool premature)
(void)premature;
if(data->conn->handler == &Curl_handler_http3) {
/* only for HTTP/3 transfers */
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
Curl_dyn_free(&stream->overflow);
}
}
@@ -1941,7 +1922,7 @@ bool Curl_quic_data_pending(const struct Curl_easy *data)
buffer and allocated an overflow buffer. Since it's possible that
there's no more data coming on the socket, we need to keep reading
until the overflow buffer is empty. */
- const struct HTTP *stream = data->req.protop;
+ const struct HTTP *stream = data->req.p.http;
return Curl_dyn_len(&stream->overflow) > 0;
}
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.h b/Utilities/cmcurl/lib/vquic/ngtcp2.h
index afdd01b7c..cbede4514 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.h
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -48,6 +48,7 @@ struct quicsocket {
ngtcp2_cid scid;
uint32_t version;
ngtcp2_settings settings;
+ ngtcp2_transport_params transport_params;
#ifdef USE_OPENSSL
SSL_CTX *sslctx;
SSL *ssl;
@@ -58,11 +59,11 @@ struct quicsocket {
struct quic_handshake crypto_data[3];
/* the last TLS alert description generated by the local endpoint */
uint8_t tls_alert;
- struct sockaddr local_addr;
+ struct sockaddr_storage local_addr;
socklen_t local_addrlen;
nghttp3_conn *h3conn;
- nghttp3_conn_settings h3settings;
+ nghttp3_settings h3settings;
int qlogfd;
};
diff --git a/Utilities/cmcurl/lib/vquic/quiche.c b/Utilities/cmcurl/lib/vquic/quiche.c
index fd9cb8bd3..d138dd3a2 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.c
+++ b/Utilities/cmcurl/lib/vquic/quiche.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -53,21 +53,22 @@
#define QUIC_MAX_DATA (1*1024*1024)
#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
-static CURLcode process_ingress(struct connectdata *conn,
+static CURLcode process_ingress(struct Curl_easy *data,
curl_socket_t sockfd,
struct quicsocket *qs);
-static CURLcode flush_egress(struct connectdata *conn, curl_socket_t sockfd,
+static CURLcode flush_egress(struct Curl_easy *data, curl_socket_t sockfd,
struct quicsocket *qs);
-static CURLcode http_request(struct connectdata *conn, const void *mem,
+static CURLcode http_request(struct Curl_easy *data, const void *mem,
size_t len);
static Curl_recv h3_stream_recv;
static Curl_send h3_stream_send;
-static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int quiche_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
- struct SingleRequest *k = &conn->data->req;
+ struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET];
@@ -83,14 +84,18 @@ static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks)
return bitmap;
}
-static int quiche_perform_getsock(const struct connectdata *conn,
- curl_socket_t *socks)
-{
- return quiche_getsock((struct connectdata *)conn, socks);
-}
-
-static CURLcode qs_disconnect(struct quicsocket *qs)
+static CURLcode qs_disconnect(struct Curl_easy *data,
+ struct quicsocket *qs)
{
+ DEBUGASSERT(qs);
+ if(qs->conn) {
+ (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0);
+ /* flushing the egress is not a failsafe way to deliver all the
+ outstanding packets, but we also don't want to get stuck here... */
+ (void)flush_egress(data, qs->sockfd, qs);
+ quiche_conn_free(qs->conn);
+ qs->conn = NULL;
+ }
if(qs->h3config)
quiche_h3_config_free(qs->h3config);
if(qs->h3c)
@@ -99,41 +104,41 @@ static CURLcode qs_disconnect(struct quicsocket *qs)
quiche_config_free(qs->cfg);
qs->cfg = NULL;
}
- if(qs->conn) {
- quiche_conn_free(qs->conn);
- qs->conn = NULL;
- }
return CURLE_OK;
}
-static CURLcode quiche_disconnect(struct connectdata *conn,
+static CURLcode quiche_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
struct quicsocket *qs = conn->quic;
(void)dead_connection;
- return qs_disconnect(qs);
+ return qs_disconnect(data, qs);
}
-void Curl_quic_disconnect(struct connectdata *conn,
+void Curl_quic_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
int tempindex)
{
if(conn->transport == TRNSPRT_QUIC)
- qs_disconnect(&conn->hequic[tempindex]);
+ qs_disconnect(data, &conn->hequic[tempindex]);
}
-static unsigned int quiche_conncheck(struct connectdata *conn,
+static unsigned int quiche_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
+ (void)data;
(void)conn;
(void)checks_to_perform;
return CONNRESULT_NONE;
}
-static CURLcode quiche_do(struct connectdata *conn, bool *done)
+static CURLcode quiche_do(struct Curl_easy *data, bool *done)
{
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
stream->h3req = FALSE; /* not sent */
- return Curl_http(conn, done);
+ return Curl_http(data, done);
}
static const struct Curl_handler Curl_handler_http3 = {
@@ -148,12 +153,13 @@ static const struct Curl_handler Curl_handler_http3 = {
quiche_getsock, /* proto_getsock */
quiche_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- quiche_perform_getsock, /* perform_getsock */
+ quiche_getsock, /* perform_getsock */
quiche_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
quiche_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
@@ -165,14 +171,16 @@ static void quiche_debug_log(const char *line, void *argp)
}
#endif
-CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
+CURLcode Curl_quic_connect(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t sockfd,
int sockindex,
const struct sockaddr *addr, socklen_t addrlen)
{
CURLcode result;
struct quicsocket *qs = &conn->hequic[sockindex];
- struct Curl_easy *data = conn->data;
char *keylog_file = NULL;
+ char ipbuf[40];
+ long port;
#ifdef DEBUG_QUICHE
/* initialize debug log callback only once */
@@ -186,6 +194,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
(void)addr;
(void)addrlen;
+ qs->sockfd = sockfd;
qs->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
if(!qs->cfg) {
failf(data, "can't create quiche config");
@@ -236,20 +245,22 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
}
#endif
- result = flush_egress(conn, sockfd, qs);
+ result = flush_egress(data, sockfd, qs);
if(result)
return result;
- /* store the used address as a string */
- if(!Curl_addr2string((struct sockaddr*)addr, addrlen,
- conn->primary_ip, &conn->primary_port)) {
+ /* extract the used address as a string */
+ if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
char buffer[STRERROR_LEN];
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
- Curl_persistconninfo(conn);
+
+ infof(data, "Connect socket %d over QUIC to %s:%ld\n",
+ sockfd, ipbuf, port);
+
+ Curl_persistconninfo(data, conn, NULL, -1);
/* for connection reuse purposes: */
conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
@@ -313,38 +324,39 @@ static CURLcode quiche_has_connected(struct connectdata *conn,
/*
* This function gets polled to check if this QUIC connection has connected.
*/
-CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
+CURLcode Curl_quic_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
bool *done)
{
CURLcode result;
struct quicsocket *qs = &conn->hequic[sockindex];
curl_socket_t sockfd = conn->tempsock[sockindex];
- result = process_ingress(conn, sockfd, qs);
+ result = process_ingress(data, sockfd, qs);
if(result)
goto error;
- result = flush_egress(conn, sockfd, qs);
+ result = flush_egress(data, sockfd, qs);
if(result)
goto error;
if(quiche_conn_is_established(qs->conn)) {
*done = TRUE;
result = quiche_has_connected(conn, 0, sockindex);
- DEBUGF(infof(conn->data, "quiche established connection!\n"));
+ DEBUGF(infof(data, "quiche established connection!\n"));
}
return result;
error:
- qs_disconnect(qs);
+ qs_disconnect(data, qs);
return result;
}
-static CURLcode process_ingress(struct connectdata *conn, int sockfd,
+static CURLcode process_ingress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs)
{
ssize_t recvd;
- struct Curl_easy *data = conn->data;
uint8_t *buf = (uint8_t *)data->state.buffer;
size_t bufsize = data->set.buffer_size;
@@ -357,7 +369,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd,
break;
if(recvd < 0) {
- failf(conn->data, "quiche: recv() unexpectedly returned %d "
+ failf(data, "quiche: recv() unexpectedly returned %zd "
"(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd);
return CURLE_RECV_ERROR;
}
@@ -367,7 +379,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd,
break;
if(recvd < 0) {
- failf(conn->data, "quiche_conn_recv() == %d", recvd);
+ failf(data, "quiche_conn_recv() == %zd", recvd);
return CURLE_RECV_ERROR;
}
} while(1);
@@ -379,11 +391,11 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd,
* flush_egress drains the buffers and sends off data.
* Calls failf() on errors.
*/
-static CURLcode flush_egress(struct connectdata *conn, int sockfd,
+static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs)
{
ssize_t sent;
- static uint8_t out[1200];
+ uint8_t out[1200];
int64_t timeout_ns;
do {
@@ -392,14 +404,13 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd,
break;
if(sent < 0) {
- failf(conn->data, "quiche_conn_send returned %zd\n",
- sent);
+ failf(data, "quiche_conn_send returned %zd", sent);
return CURLE_SEND_ERROR;
}
sent = send(sockfd, out, sent, 0);
if(sent < 0) {
- failf(conn->data, "send() returned %zd\n", sent);
+ failf(data, "send() returned %zd", sent);
return CURLE_SEND_ERROR;
}
} while(1);
@@ -408,7 +419,7 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd,
timeout_ns = quiche_conn_timeout_as_nanos(qs->conn);
if(timeout_ns)
/* expire uses milliseconds */
- Curl_expire(conn->data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);
+ Curl_expire(data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);
return CURLE_OK;
}
@@ -446,7 +457,7 @@ static int cb_each_header(uint8_t *name, size_t name_len,
return 0;
}
-static ssize_t h3_stream_recv(struct connectdata *conn,
+static ssize_t h3_stream_recv(struct Curl_easy *data,
int sockindex,
char *buf,
size_t buffersize,
@@ -454,18 +465,18 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
{
ssize_t recvd = -1;
ssize_t rcode;
+ struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex];
quiche_h3_event *ev;
int rc;
struct h3h1header headers;
- struct Curl_easy *data = conn->data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
headers.dest = buf;
headers.destlen = buffersize;
headers.nlen = 0;
- if(process_ingress(conn, sockfd, qs)) {
+ if(process_ingress(data, sockfd, qs)) {
infof(data, "h3_stream_recv returns on ingress\n");
*curlcode = CURLE_RECV_ERROR;
return -1;
@@ -525,7 +536,7 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
quiche_h3_event_free(ev);
}
- if(flush_egress(conn, sockfd, qs)) {
+ if(flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -539,19 +550,20 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
return recvd;
}
-static ssize_t h3_stream_send(struct connectdata *conn,
+static ssize_t h3_stream_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
ssize_t sent;
+ struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
if(!stream->h3req) {
- CURLcode result = http_request(conn, mem, len);
+ CURLcode result = http_request(data, mem, len);
if(result) {
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -559,8 +571,7 @@ static ssize_t h3_stream_send(struct connectdata *conn,
sent = len;
}
else {
- H3BUGF(infof(conn->data, "Pass on %zd body bytes to quiche\n",
- len));
+ H3BUGF(infof(data, "Pass on %zd body bytes to quiche\n", len));
sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
(uint8_t *)mem, len, FALSE);
if(sent < 0) {
@@ -569,7 +580,7 @@ static ssize_t h3_stream_send(struct connectdata *conn,
}
}
- if(flush_egress(conn, sockfd, qs)) {
+ if(flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -591,12 +602,13 @@ int Curl_quic_ver(char *p, size_t len)
field list. */
#define AUTHORITY_DST_IDX 3
-static CURLcode http_request(struct connectdata *conn, const void *mem,
+static CURLcode http_request(struct Curl_easy *data, const void *mem,
size_t len)
{
/*
*/
- struct HTTP *stream = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *stream = data->req.p.http;
size_t nheader;
size_t i;
size_t authority_idx;
@@ -606,7 +618,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
quiche_h3_header *nva = NULL;
struct quicsocket *qs = conn->quic;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
stream->h3req = TRUE; /* senf off! */
@@ -761,7 +772,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
if(acc > MAX_ACC) {
infof(data, "http_request: Warning: The cumulative length of all "
- "headers exceeds %zu bytes and that could cause the "
+ "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC);
}
}
@@ -819,14 +830,15 @@ fail:
/*
* Called from transfer.c:done_sending when we stop HTTP/3 uploading.
*/
-CURLcode Curl_quic_done_sending(struct connectdata *conn)
+CURLcode Curl_quic_done_sending(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
+ DEBUGASSERT(conn);
if(conn->handler == &Curl_handler_http3) {
/* only for HTTP/3 transfers */
ssize_t sent;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct quicsocket *qs = conn->quic;
- fprintf(stderr, "!!! Curl_quic_done_sending\n");
stream->upload_done = TRUE;
sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
NULL, 0, TRUE);
diff --git a/Utilities/cmcurl/lib/vquic/quiche.h b/Utilities/cmcurl/lib/vquic/quiche.h
index c8d1837b5..d311e9988 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.h
+++ b/Utilities/cmcurl/lib/vquic/quiche.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -41,6 +41,7 @@ struct quicsocket {
quiche_h3_conn *h3c;
quiche_h3_config *h3config;
uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
+ curl_socket_t sockfd;
uint32_t version;
};
diff --git a/Utilities/cmcurl/lib/vquic/vquic.c b/Utilities/cmcurl/lib/vquic/vquic.c
index aae8e0951..7c0cc6df2 100644
--- a/Utilities/cmcurl/lib/vquic/vquic.c
+++ b/Utilities/cmcurl/lib/vquic/vquic.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vquic/vquic.h b/Utilities/cmcurl/lib/vquic/vquic.h
index ecff0edf4..eb8a893d9 100644
--- a/Utilities/cmcurl/lib/vquic/vquic.h
+++ b/Utilities/cmcurl/lib/vquic/vquic.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vssh/libssh.c b/Utilities/cmcurl/lib/vssh/libssh.c
index 8988e2392..08896ab5b 100644
--- a/Utilities/cmcurl/lib/vssh/libssh.c
+++ b/Utilities/cmcurl/lib/vssh/libssh.c
@@ -5,14 +5,14 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 - 2020 Red Hat, Inc.
+ * Copyright (C) 2017 - 2021 Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
* Robert Kolcun, Andreas Schneider
*
* 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.haxx.se/docs/copyright.html.
+ * 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
@@ -107,34 +107,37 @@
#endif
/* Local functions: */
-static CURLcode myssh_connect(struct connectdata *conn, bool *done);
-static CURLcode myssh_multi_statemach(struct connectdata *conn,
+static CURLcode myssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done);
-static CURLcode myssh_do_it(struct connectdata *conn, bool *done);
+static CURLcode myssh_do_it(struct Curl_easy *data, bool *done);
-static CURLcode scp_done(struct connectdata *conn,
+static CURLcode scp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode scp_disconnect(struct connectdata *conn,
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
-static CURLcode sftp_done(struct connectdata *conn,
+static CURLcode sftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead);
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done);
-static void sftp_quote(struct connectdata *conn);
-static void sftp_quote_stat(struct connectdata *conn);
-static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock);
-static int myssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
+static void sftp_quote(struct Curl_easy *data);
+static void sftp_quote_stat(struct Curl_easy *data);
+static int myssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *sock);
-static CURLcode myssh_setup_connection(struct connectdata *conn);
+static CURLcode myssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* SCP protocol handler.
@@ -152,12 +155,13 @@ const struct Curl_handler Curl_handler_scp = {
myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- myssh_perform_getsock, /* perform_getsock */
+ myssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
+ CURLPROTO_SCP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
};
@@ -177,12 +181,13 @@ const struct Curl_handler Curl_handler_sftp = {
myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- myssh_perform_getsock, /* perform_getsock */
+ myssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -221,12 +226,13 @@ static CURLcode sftp_error_to_CURLE(int err)
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void mystate(struct connectdata *conn, sshstate nowstate
+static void mystate(struct Curl_easy *data, sshstate nowstate
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
@@ -295,7 +301,7 @@ static void mystate(struct connectdata *conn, sshstate nowstate
if(sshc->state != nowstate) {
- infof(conn->data, "SSH %p state change from %s to %s (line %d)\n",
+ infof(data, "SSH %p state change from %s to %s (line %d)\n",
(void *) sshc, names[sshc->state], names[nowstate],
lineno);
}
@@ -314,10 +320,10 @@ static void mystate(struct connectdata *conn, sshstate nowstate
*
* Returns SSH_OK or SSH_ERROR.
*/
-static int myssh_is_known(struct connectdata *conn)
+static int myssh_is_known(struct Curl_easy *data)
{
int rc;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
ssh_key pubkey;
size_t hlen;
@@ -527,10 +533,10 @@ static int myssh_is_known(struct connectdata *conn)
cleanup:
if(found_base64) {
- free(found_base64);
+ (free)(found_base64);
}
if(known_base64) {
- free(known_base64);
+ (free)(known_base64);
}
if(hash)
ssh_clean_pubkey_hash(&hash);
@@ -544,14 +550,14 @@ cleanup:
}
#define MOVE_TO_ERROR_STATE(_r) { \
- state(conn, SSH_SESSION_DISCONNECT); \
+ state(data, SSH_SESSION_DISCONNECT); \
sshc->actualcode = _r; \
rc = SSH_ERROR; \
break; \
}
#define MOVE_TO_SFTP_CLOSE_STATE() { \
- state(conn, SSH_SFTP_CLOSE); \
+ state(data, SSH_SFTP_CLOSE); \
sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
rc = SSH_ERROR; \
break; \
@@ -560,7 +566,7 @@ cleanup:
#define MOVE_TO_LAST_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_PASS_INIT); \
+ state(data, SSH_AUTH_PASS_INIT); \
break; \
} \
else { \
@@ -570,7 +576,7 @@ cleanup:
#define MOVE_TO_TERTIARY_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_KEY_INIT); \
+ state(data, SSH_AUTH_KEY_INIT); \
break; \
} \
else { \
@@ -580,7 +586,7 @@ cleanup:
#define MOVE_TO_SECONDARY_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_GSSAPI); \
+ state(data, SSH_AUTH_GSSAPI); \
break; \
} \
else { \
@@ -658,11 +664,11 @@ restart:
* to will be set to TRUE if the libssh function returns SSH_AGAIN
* meaning it wants to be called again when the socket is ready
*/
-static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
+static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *protop = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *protop = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc = SSH_NO_ERROR, err;
@@ -687,7 +693,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
non-blocking */
ssh_set_blocking(sshc->ssh_session, 0);
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
@@ -700,17 +706,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
}
- state(conn, SSH_HOSTKEY);
+ state(data, SSH_HOSTKEY);
/* FALLTHROUGH */
case SSH_HOSTKEY:
- rc = myssh_is_known(conn);
+ rc = myssh_is_known(data);
if(rc != SSH_OK) {
MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
}
- state(conn, SSH_AUTHLIST);
+ state(data, SSH_AUTHLIST);
/* FALLTHROUGH */
case SSH_AUTHLIST:{
sshc->authed = FALSE;
@@ -724,7 +730,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Authenticated with none\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
else if(rc == SSH_AUTH_ERROR) {
@@ -733,17 +739,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
- state(conn, SSH_AUTH_PKEY_INIT);
+ state(data, SSH_AUTH_PKEY_INIT);
infof(data, "Authentication using SSH public key file\n");
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
- state(conn, SSH_AUTH_GSSAPI);
+ state(data, SSH_AUTH_GSSAPI);
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
}
else { /* unsupported authentication method */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
@@ -783,7 +789,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
- state(conn, SSH_AUTH_PKEY);
+ state(data, SSH_AUTH_PKEY);
break;
}
@@ -798,7 +804,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = SSH_OK;
sshc->authed = TRUE;
infof(data, "Completed public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
@@ -815,7 +821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
else {
@@ -839,7 +845,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = SSH_OK;
sshc->authed = TRUE;
infof(data, "Completed gssapi authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
@@ -848,7 +854,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_KEY_INIT:
if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
- state(conn, SSH_AUTH_KEY);
+ state(data, SSH_AUTH_KEY);
}
else {
MOVE_TO_LAST_AUTH;
@@ -866,7 +872,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->authed = TRUE;
infof(data, "completed keyboard interactive authentication\n");
}
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
case SSH_AUTH_PASS_INIT:
@@ -874,7 +880,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* Host key authentication is intentionally not implemented */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
}
- state(conn, SSH_AUTH_PASS);
+ state(data, SSH_AUTH_PASS);
/* FALLTHROUGH */
case SSH_AUTH_PASS:
@@ -887,7 +893,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed password authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
@@ -906,17 +912,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
*/
infof(data, "Authentication complete\n");
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
conn->sockfd = sock;
conn->writesockfd = CURL_SOCKET_BAD;
if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
break;
}
infof(data, "SSH CONNECT phase done\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_INIT:
@@ -938,7 +944,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
break;
}
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
/* FALLTHROUGH */
case SSH_SFTP_REALPATH:
/*
@@ -948,32 +954,31 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->homedir == NULL) {
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
- conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ data->state.most_recent_ftp_entrypath = sshc->homedir;
/* This is the last step in the SFTP connect phase. Do note that while
we get the homedir here, we get the "workingpath" in the DO action
since the homedir will remain the same between request but the
working path will not. */
DEBUGF(infof(data, "SSH CONNECT phase done\n"));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_QUOTE_INIT:
-
- result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
@@ -981,16 +986,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(data->set.postquote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.postquote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
case SSH_SFTP_QUOTE:
/* Send any quote commands */
- sftp_quote(conn);
+ sftp_quote(data);
break;
case SSH_SFTP_NEXT_QUOTE:
@@ -1000,21 +1005,21 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->quote_item = sshc->quote_item->next;
if(sshc->quote_item) {
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
if(sshc->nextstate != SSH_NO_STATE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_NO_STATE;
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
}
break;
case SSH_SFTP_QUOTE_STAT:
- sftp_quote_stat(conn);
+ sftp_quote_stat(data);
break;
case SSH_SFTP_QUOTE_SETSTAT:
@@ -1025,7 +1030,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
/* sshc->actualcode = sftp_error_to_CURLE(err);
@@ -1033,7 +1038,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
* the error the libssh2 backend is returning */
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -1044,12 +1049,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_MKDIR:
@@ -1059,12 +1064,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RENAME:
@@ -1075,12 +1080,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RMDIR:
@@ -1089,12 +1094,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_UNLINK:
@@ -1103,12 +1108,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_STATVFS:
@@ -1120,7 +1125,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1143,29 +1148,29 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
@@ -1179,18 +1184,18 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sftp_attributes_free(attrs);
}
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(protop->path[strlen(protop->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
@@ -1226,7 +1231,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = O_WRONLY|O_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = O_WRONLY|O_CREAT|O_TRUNC;
if(sshc->sftp_file)
@@ -1244,7 +1249,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* try to create the path remotely */
rc = 0;
sshc->secondCreateDirs = 1;
- state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ state(data, SSH_SFTP_CREATE_DIRS_INIT);
break;
}
else {
@@ -1327,17 +1332,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
case SSH_SFTP_CREATE_DIRS_INIT:
if(strlen(protop->path) > 1) {
sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
}
else {
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -1347,10 +1352,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
*sshc->slash_pos = 0;
infof(data, "Creating directory '%s'\n", protop->path);
- state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
@@ -1373,13 +1378,13 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
rc = 0; /* clear rc and continue */
}
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
break;
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -1394,7 +1399,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_get_error(sshc->ssh_session));
MOVE_TO_SFTP_CLOSE_STATE();
}
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
@@ -1413,16 +1418,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
tmpLine = aprintf("%s\n", sshc->readdir_filename);
if(tmpLine == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
tmpLine, sshc->readdir_len + 1);
free(tmpLine);
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
/* since this counts what we send to the client, we include the
@@ -1430,18 +1435,15 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
data->req.bytecount += sshc->readdir_len + 1;
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT,
- (char *)sshc->readdir_filename,
- sshc->readdir_len);
- }
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
+ sshc->readdir_len);
}
else {
sshc->readdir_currLen = strlen(sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1453,7 +1455,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
S_IFLNK)) {
sshc->readdir_linkPath = malloc(PATH_MAX + 1);
if(sshc->readdir_linkPath == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1461,15 +1463,15 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
sshc->readdir_filename);
- state(conn, SSH_SFTP_READDIR_LINK);
+ state(data, SSH_SFTP_READDIR_LINK);
break;
}
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
}
}
else if(sftp_dir_eof(sshc->sftp_dir)) {
- state(conn, SSH_SFTP_READDIR_DONE);
+ state(data, SSH_SFTP_READDIR_DONE);
break;
}
else {
@@ -1516,7 +1518,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_totalLen);
if(!new_readdir_line) {
sshc->readdir_line = NULL;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1534,24 +1536,21 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_filename = NULL;
sshc->readdir_longentry = NULL;
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
/* FALLTHROUGH */
case SSH_SFTP_READDIR_BOTTOM:
sshc->readdir_currLen += msnprintf(sshc->readdir_line +
sshc->readdir_currLen,
sshc->readdir_totalLen -
sshc->readdir_currLen, "\n");
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
sshc->readdir_line,
sshc->readdir_currLen);
if(!result) {
-
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen);
- }
+ Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
+ sshc->readdir_currLen);
data->req.bytecount += sshc->readdir_currLen;
}
Curl_safefree(sshc->readdir_line);
@@ -1559,10 +1558,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_tmp = NULL;
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
else
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR_DONE:
@@ -1571,7 +1570,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_DOWNLOAD_INIT:
@@ -1590,7 +1589,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_SFTP_CLOSE_STATE();
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
break;
case SSH_SFTP_DOWNLOAD_STAT:
@@ -1622,14 +1621,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME;
}
- if(conn->data->state.use_range) {
+ if(data->state.use_range) {
curl_off_t from, to;
char *ptr;
char *ptr2;
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR;
}
@@ -1712,7 +1711,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -1728,12 +1727,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
sshc->sftp_recv_state = 0;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -1751,11 +1750,11 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
SSH_SFTP_CLOSE to pass the correct result back */
if(sshc->nextstate != SSH_NO_STATE &&
sshc->nextstate != SSH_SFTP_CLOSE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_SFTP_CLOSE;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
}
break;
@@ -1776,17 +1775,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
SSH_STRING_FREE_CHAR(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
break;
-
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -1802,17 +1800,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->scp_session =
ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
- state(conn, SSH_SCP_UPLOAD_INIT);
+ state(data, SSH_SCP_UPLOAD_INIT);
}
else {
sshc->scp_session =
ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
- state(conn, SSH_SCP_DOWNLOAD_INIT);
+ state(data, SSH_SCP_DOWNLOAD_INIT);
}
if(!sshc->scp_session) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1823,7 +1821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1832,7 +1830,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
(int)data->set.new_file_perms);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1851,7 +1849,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_OUT;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
@@ -1860,10 +1858,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
- state(conn, SSH_SCP_DOWNLOAD);
+ state(data, SSH_SCP_DOWNLOAD);
/* FALLTHROUGH */
case SSH_SCP_DOWNLOAD:{
@@ -1872,7 +1870,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_pull_request(sshc->scp_session);
if(rc != SSH_SCP_REQUEST_NEWFILE) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
break;
}
@@ -1890,14 +1888,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_IN;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
case SSH_SCP_DONE:
if(data->set.upload)
- state(conn, SSH_SCP_SEND_EOF);
+ state(data, SSH_SCP_SEND_EOF);
else
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
@@ -1915,7 +1913,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
}
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
@@ -1927,7 +1925,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
/* FALLTHROUGH */
case SSH_SESSION_DISCONNECT:
@@ -1942,9 +1940,9 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_disconnect(sshc->ssh_session);
SSH_STRING_FREE_CHAR(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
/* FALLTHROUGH */
case SSH_SESSION_FREE:
if(sshc->ssh_session) {
@@ -1992,7 +1990,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_QUIT:
@@ -2000,7 +1998,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2019,10 +2017,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int myssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int myssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
int bitmap = GETSOCK_BLANK;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
if(conn->waitfor & KEEP_RECV)
@@ -2034,16 +2034,6 @@ static int myssh_perform_getsock(const struct connectdata *conn,
return bitmap;
}
-/* Generic function called by the multi interface to figure out what socket(s)
- to wait for and for what actions during the DOING and PROTOCONNECT states*/
-static int myssh_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
- /* if we know the direction we can use the generic *_getsock() function even
- for the protocol_connect and doing states */
- return myssh_perform_getsock(conn, sock);
-}
-
static void myssh_block2waitfor(struct connectdata *conn, bool block)
{
struct ssh_conn *sshc = &conn->proto.sshc;
@@ -2065,13 +2055,14 @@ static void myssh_block2waitfor(struct connectdata *conn, bool block)
}
/* called repeatedly until done from multi.c */
-static CURLcode myssh_multi_statemach(struct connectdata *conn,
+static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
- CURLcode result = myssh_statemach_act(conn, &block);
+ CURLcode result = myssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
myssh_block2waitfor(conn, block);
@@ -2079,24 +2070,24 @@ static CURLcode myssh_multi_statemach(struct connectdata *conn,
return result;
}
-static CURLcode myssh_block_statemach(struct connectdata *conn,
+static CURLcode myssh_block_statemach(struct Curl_easy *data,
bool disconnect)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = myssh_statemach_act(conn, &block);
+ result = myssh_statemach_act(data, &block);
if(result)
break;
if(!disconnect) {
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -2125,11 +2116,13 @@ static CURLcode myssh_block_statemach(struct connectdata *conn,
/*
* SSH setup connection
*/
-static CURLcode myssh_setup_connection(struct connectdata *conn)
+static CURLcode myssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -2143,17 +2136,17 @@ static Curl_send scp_send, sftp_send;
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time.
*/
-static CURLcode myssh_connect(struct connectdata *conn, bool *done)
+static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
{
struct ssh_conn *ssh;
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
int rc;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- myssh_setup_connection(conn);
+ if(!data->req.p.ssh)
+ myssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
@@ -2246,22 +2239,22 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done)
/* we do not verify here, we do it at the state machine,
* after connection */
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
- result = myssh_multi_statemach(conn, done);
+ result = myssh_multi_statemach(data, done);
return result;
}
/* called from multi.c while DOing */
-static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
{
CURLcode result;
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -2276,34 +2269,35 @@ static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
*/
static
-CURLcode scp_perform(struct connectdata *conn,
+CURLcode scp_perform(struct Curl_easy *data,
bool *connected, bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SCP_TRANS_INIT);
+ state(data, SSH_SCP_TRANS_INIT);
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
-static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
+static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -2320,9 +2314,9 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = scp_perform(conn, &connected, done);
+ result = scp_perform(data, &connected, done);
else
- result = sftp_perform(conn, &connected, done);
+ result = sftp_perform(data, &connected, done);
return result;
}
@@ -2330,7 +2324,8 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode scp_disconnect(struct connectdata *conn,
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
CURLcode result = CURLE_OK;
@@ -2340,9 +2335,9 @@ static CURLcode scp_disconnect(struct connectdata *conn,
if(ssh->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
- result = myssh_block_statemach(conn, TRUE);
+ result = myssh_block_statemach(data, TRUE);
}
return result;
@@ -2350,44 +2345,45 @@ static CURLcode scp_disconnect(struct connectdata *conn,
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *protop = conn->data->req.protop;
+ struct SSHPROTO *protop = data->req.p.ssh;
if(!status) {
/* run the state-machine */
- result = myssh_block_statemach(conn, FALSE);
+ result = myssh_block_statemach(data, FALSE);
}
else
result = status;
if(protop)
Curl_safefree(protop->path);
- if(Curl_pgrsDone(conn))
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
-static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void) premature; /* not used */
if(!status)
- state(conn, SSH_SCP_DONE);
+ state(data, SSH_SCP_DONE);
- return myssh_done(conn, status);
+ return myssh_done(data, status);
}
-static ssize_t scp_send(struct connectdata *conn, int sockindex,
+static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
int rc;
+ struct connectdata *conn = data->conn;
(void) sockindex; /* we only support SCP on the fixed known primary socket */
(void) err;
@@ -2413,10 +2409,11 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return len;
}
-static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
(void) err;
(void) sockindex; /* we only support SCP on the fixed known primary socket */
@@ -2452,38 +2449,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = myssh_multi_statemach(conn, dophase_done);
+ CURLcode result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -2491,46 +2489,50 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
CURLcode result = CURLE_OK;
(void) dead_connection;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = myssh_block_statemach(conn, TRUE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = myssh_block_statemach(data, TRUE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
- bool premature)
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
+ bool premature)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
if(!status) {
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!premature && conn->data->set.postquote && !conn->bits.retry)
+ if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
}
- return myssh_done(conn, status);
+ return myssh_done(data, status);
}
/* return number of sent bytes */
-static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
+ struct connectdata *conn = data->conn;
(void)sockindex;
nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
@@ -2556,10 +2558,11 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
(void)sockindex;
DEBUGASSERT(len < CURL_MAX_READ_SIZE);
@@ -2567,8 +2570,8 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
switch(conn->proto.sshc.sftp_recv_state) {
case 0:
conn->proto.sshc.sftp_file_index =
- sftp_async_read_begin(conn->proto.sshc.sftp_file,
- (uint32_t)len);
+ sftp_async_read_begin(conn->proto.sshc.sftp_file,
+ (uint32_t)len);
if(conn->proto.sshc.sftp_file_index < 0) {
*err = CURLE_RECV_ERROR;
return -1;
@@ -2602,11 +2605,11 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
}
}
-static void sftp_quote(struct connectdata *conn)
+static void sftp_quote(struct Curl_easy *data)
{
const char *cp;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *protop = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *protop = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result;
@@ -2632,26 +2635,25 @@ static void sftp_quote(struct connectdata *conn)
protop->path);
if(!tmp) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
return;
}
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
- }
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
+
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
using ordinary FTP. */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
else
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
return;
}
@@ -2662,7 +2664,7 @@ static void sftp_quote(struct connectdata *conn)
cp = strchr(cmd, ' ');
if(cp == NULL) {
failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2678,7 +2680,7 @@ static void sftp_quote(struct connectdata *conn)
failf(data, "Out of memory");
else
failf(data, "Syntax error: Bad first parameter");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
@@ -2692,7 +2694,9 @@ static void sftp_quote(struct connectdata *conn)
*/
if(strncasecompare(cmd, "chgrp ", 6) ||
strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6)) {
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -2702,16 +2706,16 @@ static void sftp_quote(struct connectdata *conn)
if(result == CURLE_OUT_OF_MEMORY)
failf(data, "Out of memory");
else
- failf(data, "Syntax error in chgrp/chmod/chown: "
+ failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
"Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
sshc->quote_attrs = NULL;
- state(conn, SSH_SFTP_QUOTE_STAT);
+ state(data, SSH_SFTP_QUOTE_STAT);
return;
}
if(strncasecompare(cmd, "ln ", 3) ||
@@ -2726,17 +2730,17 @@ static void sftp_quote(struct connectdata *conn)
else
failf(data, "Syntax error in ln/symlink: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
return;
}
else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
- state(conn, SSH_SFTP_QUOTE_MKDIR);
+ state(data, SSH_SFTP_QUOTE_MKDIR);
return;
}
else if(strncasecompare(cmd, "rename ", 7)) {
@@ -2750,26 +2754,26 @@ static void sftp_quote(struct connectdata *conn)
else
failf(data, "Syntax error in rename: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(conn, SSH_SFTP_QUOTE_RENAME);
+ state(data, SSH_SFTP_QUOTE_RENAME);
return;
}
else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
- state(conn, SSH_SFTP_QUOTE_RMDIR);
+ state(data, SSH_SFTP_QUOTE_RMDIR);
return;
}
else if(strncasecompare(cmd, "rm ", 3)) {
- state(conn, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_UNLINK);
return;
}
#ifdef HAS_STATVFS_SUPPORT
else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(conn, SSH_SFTP_QUOTE_STATVFS);
+ state(data, SSH_SFTP_QUOTE_STATVFS);
return;
}
#endif
@@ -2777,14 +2781,14 @@ static void sftp_quote(struct connectdata *conn)
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
}
-static void sftp_quote_stat(struct connectdata *conn)
+static void sftp_quote_stat(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
char *cmd = sshc->quote_item->data;
sshc->acceptfail = FALSE;
@@ -2812,7 +2816,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %d",
sftp_get_error(sshc->sftp_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2826,7 +2830,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2841,7 +2845,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2856,16 +2860,44 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
+ else if(strncasecompare(cmd, "atime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect access date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ return;
+ }
+ sshc->quote_attrs->atime = (uint32_t)date;
+ sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
+ }
+ else if(strncasecompare(cmd, "mtime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect modification date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ return;
+ }
+ sshc->quote_attrs->mtime = (uint32_t)date;
+ sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
+ }
/* Now send the completed structure... */
- state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ state(data, SSH_SFTP_QUOTE_SETSTAT);
return;
}
diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c
index 4f56bb44c..3130dcc74 100644
--- a/Utilities/cmcurl/lib/vssh/libssh2.c
+++ b/Utilities/cmcurl/lib/vssh/libssh2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -103,30 +103,24 @@ static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);
-static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn);
-static CURLcode ssh_connect(struct connectdata *conn, bool *done);
-static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
-static CURLcode ssh_do(struct connectdata *conn, bool *done);
-
-static CURLcode scp_done(struct connectdata *conn,
- CURLcode, bool premature);
-static CURLcode scp_doing(struct connectdata *conn,
- bool *dophase_done);
-static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
-
-static CURLcode sftp_done(struct connectdata *conn,
- CURLcode, bool premature);
-static CURLcode sftp_doing(struct connectdata *conn,
- bool *dophase_done);
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
-static
-CURLcode sftp_perform(struct connectdata *conn,
- bool *connected,
- bool *dophase_done);
-static int ssh_getsock(struct connectdata *conn, curl_socket_t *sock);
-static int ssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
-static CURLcode ssh_setup_connection(struct connectdata *conn);
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
+static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
+static CURLcode ssh_do(struct Curl_easy *data, bool *done);
+static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature);
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection);
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature);
+static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
+ bool *dophase_done);
+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);
/*
* SCP protocol handler.
@@ -144,12 +138,13 @@ const struct Curl_handler Curl_handler_scp = {
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ssh_perform_getsock, /* perform_getsock */
+ ssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
+ CURLPROTO_SCP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -171,12 +166,13 @@ const struct Curl_handler Curl_handler_sftp = {
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ssh_perform_getsock, /* perform_getsock */
+ ssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -306,8 +302,9 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free)
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void state(struct connectdata *conn, sshstate nowstate)
+static void state(struct Curl_easy *data, sshstate nowstate)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
@@ -378,7 +375,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
if(sshc->state != nowstate) {
- infof(conn->data, "SFTP %p state change from %s to %s\n",
+ infof(data, "SFTP %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
@@ -432,16 +429,16 @@ static int sshkeycallback(struct Curl_easy *easy,
#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
#endif
-static CURLcode ssh_knownhost(struct connectdata *conn)
+static CURLcode ssh_knownhost(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
- struct Curl_easy *data = conn->data;
-
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
/* we're asked to verify the host against a file */
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
+ struct libssh2_knownhost *host = NULL;
int rc;
int keytype;
size_t keylen;
@@ -456,7 +453,6 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
* What host name does OpenSSH store in its file if an IDN name is
* used?
*/
- struct libssh2_knownhost *host;
enum curl_khmatch keymatch;
curl_sshkeycallback func =
data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
@@ -562,13 +558,19 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
default: /* unknown return codes will equal reject */
/* FALLTHROUGH */
case CURLKHSTAT_REJECT:
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
/* FALLTHROUGH */
case CURLKHSTAT_DEFER:
/* DEFER means bail out but keep the SSH_HOSTKEY state */
result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
break;
+ case CURLKHSTAT_FINE_REPLACE:
+ /* remove old host+key that doesn't match */
+ if(host)
+ libssh2_knownhost_del(sshc->kh, host);
+ /*FALLTHROUGH*/
case CURLKHSTAT_FINE:
+ /*FALLTHROUGH*/
case CURLKHSTAT_FINE_ADD_TO_FILE:
/* proceed */
if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
@@ -583,7 +585,8 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
if(addrc)
infof(data, "Warning adding the known host %s failed!\n",
conn->host.name);
- else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
+ else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE ||
+ rc == CURLKHSTAT_FINE_REPLACE) {
/* now we write the entire in-memory list of known hosts to the
known_hosts file */
int wrc =
@@ -600,15 +603,15 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
}
}
#else /* HAVE_LIBSSH2_KNOWNHOST_API */
- (void)conn;
+ (void)data;
#endif
return result;
}
-static CURLcode ssh_check_fingerprint(struct connectdata *conn)
+static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
char md5buffer[33];
@@ -635,7 +638,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
else
failf(data,
"Denied establishing ssh session: md5 fingerprint not available");
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
return sshc->actualcode;
}
@@ -643,14 +646,14 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
/* as we already matched, we skip the check for known hosts */
return CURLE_OK;
}
- return ssh_knownhost(conn);
+ return ssh_knownhost(data);
}
/*
* ssh_force_knownhost_key_type() will check the known hosts file and try to
* force a specific public key type from the server if an entry is found.
*/
-static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
@@ -678,8 +681,8 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
= "ssh-dss";
const char *hostkey_method = NULL;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
struct libssh2_knownhost* store = NULL;
const char *kh_name_end = NULL;
size_t kh_name_size = 0;
@@ -754,18 +757,18 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
hostkey_method = hostkey_method_ssh_dss;
break;
case LIBSSH2_KNOWNHOST_KEY_RSA1:
- failf(data, "Found host key type RSA1 which is not supported\n");
+ failf(data, "Found host key type RSA1 which is not supported");
return CURLE_SSH;
default:
- failf(data, "Unknown host key type: %i\n",
+ failf(data, "Unknown host key type: %i",
(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
return CURLE_SSH;
}
infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method);
result = libssh2_session_error_to_CURLE(
- libssh2_session_method_pref(
- sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
+ libssh2_session_method_pref(
+ sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
}
else {
infof(data, "Did not find host %s in %s\n",
@@ -785,11 +788,11 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
* meaning it wants to be called again when the socket is ready
*/
-static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
+static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *sftp_scp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *sshp = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc = LIBSSH2_ERROR_NONE;
@@ -800,7 +803,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*block = 0; /* we're not blocking by default */
do {
-
switch(sshc->state) {
case SSH_INIT:
sshc->secondCreateDirs = 0;
@@ -811,13 +813,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
non-blocking */
libssh2_session_set_blocking(sshc->ssh_session, 0);
- result = ssh_force_knownhost_key_type(conn);
+ result = ssh_force_knownhost_key_type(data);
if(result) {
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
+ sshc->actualcode = result;
break;
}
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
@@ -830,12 +833,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_FAILED_INIT;
break;
}
- state(conn, SSH_HOSTKEY);
+ state(data, SSH_HOSTKEY);
/* FALLTHROUGH */
case SSH_HOSTKEY:
@@ -844,9 +847,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* against our known hosts. How that is handled (reading from file,
* whatever) is up to us.
*/
- result = ssh_check_fingerprint(conn);
+ result = ssh_check_fingerprint(data);
if(!result)
- state(conn, SSH_AUTHLIST);
+ state(data, SSH_AUTHLIST);
/* ssh_check_fingerprint sets state appropriately on error */
break;
@@ -869,14 +872,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(libssh2_userauth_authenticated(sshc->ssh_session)) {
sshc->authed = TRUE;
infof(data, "SSH user accepted with no authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
ssherr = libssh2_session_last_errno(sshc->ssh_session);
if(ssherr == LIBSSH2_ERROR_EAGAIN)
rc = LIBSSH2_ERROR_EAGAIN;
else {
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
}
break;
@@ -884,7 +887,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "SSH authentication methods available: %s\n",
sshc->authlist);
- state(conn, SSH_AUTH_PKEY_INIT);
+ state(data, SSH_AUTH_PKEY_INIT);
break;
case SSH_AUTH_PKEY_INIT:
@@ -956,7 +959,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(out_of_memory || sshc->rsa == NULL) {
Curl_safefree(sshc->rsa);
Curl_safefree(sshc->rsa_pub);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -969,10 +972,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
- state(conn, SSH_AUTH_PKEY);
+ state(data, SSH_AUTH_PKEY);
}
else {
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
}
break;
@@ -995,14 +998,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == 0) {
sshc->authed = TRUE;
infof(data, "Initialized SSH public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
infof(data, "SSH public key authentication failed: %s\n", err_msg);
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1010,10 +1013,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_PASS_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
(strstr(sshc->authlist, "password") != NULL)) {
- state(conn, SSH_AUTH_PASS);
+ state(data, SSH_AUTH_PASS);
}
else {
- state(conn, SSH_AUTH_HOST_INIT);
+ state(data, SSH_AUTH_HOST_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1030,10 +1033,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == 0) {
sshc->authed = TRUE;
infof(data, "Initialized password authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
- state(conn, SSH_AUTH_HOST_INIT);
+ state(data, SSH_AUTH_HOST_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1041,15 +1044,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_HOST_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
(strstr(sshc->authlist, "hostbased") != NULL)) {
- state(conn, SSH_AUTH_HOST);
+ state(data, SSH_AUTH_HOST);
}
else {
- state(conn, SSH_AUTH_AGENT_INIT);
+ state(data, SSH_AUTH_AGENT_INIT);
}
break;
case SSH_AUTH_HOST:
- state(conn, SSH_AUTH_AGENT_INIT);
+ state(data, SSH_AUTH_AGENT_INIT);
break;
case SSH_AUTH_AGENT_INIT:
@@ -1065,7 +1068,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(!sshc->ssh_agent) {
infof(data, "Could not create agent object\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
break;
}
}
@@ -1075,16 +1078,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
if(rc < 0) {
infof(data, "Failure connecting to agent\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
else {
- state(conn, SSH_AUTH_AGENT_LIST);
+ state(data, SSH_AUTH_AGENT_LIST);
}
}
else
#endif /* HAVE_LIBSSH2_AGENT_API */
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
break;
case SSH_AUTH_AGENT_LIST:
@@ -1095,11 +1098,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
if(rc < 0) {
infof(data, "Failure requesting identities to agent\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
else {
- state(conn, SSH_AUTH_AGENT);
+ state(data, SSH_AUTH_AGENT);
sshc->sshagent_prev_identity = NULL;
}
#endif
@@ -1137,10 +1140,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_NONE) {
sshc->authed = TRUE;
infof(data, "Agent based authentication successful\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
#endif
@@ -1149,10 +1152,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_KEY_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
&& (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
- state(conn, SSH_AUTH_KEY);
+ state(data, SSH_AUTH_KEY);
}
else {
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
break;
@@ -1170,13 +1173,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->authed = TRUE;
infof(data, "Initialized keyboard interactive authentication\n");
}
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
case SSH_AUTH_DONE:
if(!sshc->authed) {
failf(data, "Authentication failure");
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_LOGIN_DENIED;
break;
}
@@ -1186,17 +1189,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
infof(data, "Authentication complete\n");
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
conn->sockfd = sock;
conn->writesockfd = CURL_SOCKET_BAD;
if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
break;
}
infof(data, "SSH CONNECT phase done\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_INIT:
@@ -1215,11 +1218,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
failf(data, "Failure initializing sftp session: %s", err_msg);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_FAILED_INIT;
break;
}
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
break;
case SSH_SFTP_REALPATH:
@@ -1239,11 +1242,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
tempHome[rc] = '\0';
sshc->homedir = strdup(tempHome);
if(!sshc->homedir) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ data->state.most_recent_ftp_entrypath = sshc->homedir;
}
else {
/* Return the error type */
@@ -1255,9 +1258,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
a time-out or similar */
result = CURLE_SSH;
sshc->actualcode = result;
- DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
+ DEBUGF(infof(data, "error = %lu makes libcurl = %d\n",
sftperr, (int)result));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
}
@@ -1266,25 +1269,25 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
since the homedir will remain the same between request but the
working path will not. */
DEBUGF(infof(data, "SSH CONNECT phase done\n"));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_QUOTE_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
@@ -1292,10 +1295,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->set.postquote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.postquote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -1326,29 +1329,28 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(strcasecompare("pwd", cmd)) {
/* output debug output if that is requested */
char *tmp = aprintf("257 \"%s\" is current directory.\n",
- sftp_scp->path);
+ sshp->path);
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
- }
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
+
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
using ordinary FTP. */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
else
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
{
@@ -1360,7 +1362,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(cp == NULL) {
failf(data, "Syntax error command '%s'. Missing parameter!",
cmd);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1376,7 +1378,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Out of memory");
else
failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
@@ -1390,7 +1392,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
if(strncasecompare(cmd, "chgrp ", 6) ||
strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6) ) {
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -1402,13 +1406,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
else
failf(data, "Syntax error in %s: Bad second parameter", cmd);
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- state(conn, SSH_SFTP_QUOTE_STAT);
+ memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+ state(data, SSH_SFTP_QUOTE_STAT);
break;
}
if(strncasecompare(cmd, "ln ", 3) ||
@@ -1424,17 +1428,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data,
"Syntax error in ln/symlink: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
break;
}
else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
- state(conn, SSH_SFTP_QUOTE_MKDIR);
+ state(data, SSH_SFTP_QUOTE_MKDIR);
break;
}
else if(strncasecompare(cmd, "rename ", 7)) {
@@ -1448,26 +1452,26 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
else
failf(data, "Syntax error in rename: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_QUOTE_RENAME);
+ state(data, SSH_SFTP_QUOTE_RENAME);
break;
}
else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
- state(conn, SSH_SFTP_QUOTE_RMDIR);
+ state(data, SSH_SFTP_QUOTE_RMDIR);
break;
}
else if(strncasecompare(cmd, "rm ", 3)) {
- state(conn, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_UNLINK);
break;
}
#ifdef HAS_STATVFS_SUPPORT
else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(conn, SSH_SFTP_QUOTE_STATVFS);
+ state(data, SSH_SFTP_QUOTE_STATVFS);
break;
}
#endif
@@ -1475,7 +1479,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1490,15 +1494,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->quote_item = sshc->quote_item->next;
if(sshc->quote_item) {
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
if(sshc->nextstate != SSH_NO_STATE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_NO_STATE;
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
}
break;
@@ -1526,7 +1530,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
curlx_uztoui(strlen(sshc->quote_path2)),
LIBSSH2_SFTP_STAT,
- &sshc->quote_attrs);
+ &sshp->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -1536,7 +1540,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1545,51 +1549,79 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* Now set the new attributes... */
if(strncasecompare(cmd, "chgrp", 5)) {
- sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
- if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
else if(strncasecompare(cmd, "chmod", 5)) {
- sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
/* permissions are octal */
- if(sshc->quote_attrs.permissions == 0 &&
+ if(sshp->quote_attrs.permissions == 0 &&
!ISDIGIT(sshc->quote_path1[0])) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
else if(strncasecompare(cmd, "chown", 5)) {
- sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
- if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
+ else if(strncasecompare(cmd, "atime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect access date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ sshp->quote_attrs.atime = (unsigned long)date;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
+ }
+ else if(strncasecompare(cmd, "mtime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect modification date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ sshp->quote_attrs.mtime = (unsigned long)date;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
+ }
/* Now send the completed structure... */
- state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ state(data, SSH_SFTP_QUOTE_SETSTAT);
break;
}
@@ -1597,7 +1629,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
curlx_uztoui(strlen(sshc->quote_path2)),
LIBSSH2_SFTP_SETSTAT,
- &sshc->quote_attrs);
+ &sshp->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -1607,12 +1639,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -1630,12 +1662,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_MKDIR:
@@ -1650,12 +1682,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RENAME:
@@ -1676,12 +1708,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RMDIR:
@@ -1695,12 +1727,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_UNLINK:
@@ -1713,12 +1745,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
#ifdef HAS_STATVFS_SUPPORT
@@ -1737,7 +1769,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1758,30 +1790,30 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
statvfs.f_namemax);
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
#endif
case SSH_SFTP_GETINFO:
{
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
}
@@ -1790,8 +1822,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -1800,18 +1832,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->info.filetime = attrs.mtime;
}
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
- if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ if(sshp->path[strlen(sshp->path)-1] == '/')
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
@@ -1828,8 +1860,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from != 0) {
LIBSSH2_SFTP_ATTRIBUTES attrs;
if(data->state.resume_from < 0) {
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -1855,12 +1887,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
flags, data->set.new_file_perms,
LIBSSH2_SFTP_OPENFILE);
@@ -1878,7 +1910,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
if(sshc->secondCreateDirs) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
failf(data, "Creating the dir/file failed: %s",
@@ -1889,14 +1921,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(sftperr == LIBSSH2_FX_FAILURE) ||
(sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
(data->set.ftp_create_missing_dirs &&
- (strlen(sftp_scp->path) > 1))) {
+ (strlen(sshp->path) > 1))) {
/* try to create the path remotely */
rc = 0; /* clear rc and continue */
sshc->secondCreateDirs = 1;
- state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ state(data, SSH_SFTP_CREATE_DIRS_INIT);
break;
}
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
if(!sshc->actualcode) {
@@ -1906,7 +1938,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_SSH;
sftperr = LIBSSH2_FX_OK;
}
- failf(data, "Upload failed: %s (%d/%d)",
+ failf(data, "Upload failed: %s (%lu/%d)",
sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_strerror(sftperr):"ssh error",
sftperr, rc);
@@ -1975,7 +2007,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
@@ -1993,18 +2025,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
}
case SSH_SFTP_CREATE_DIRS_INIT:
- if(strlen(sftp_scp->path) > 1) {
- sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
- state(conn, SSH_SFTP_CREATE_DIRS);
+ if(strlen(sshp->path) > 1) {
+ sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
+ state(data, SSH_SFTP_CREATE_DIRS);
}
else {
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -2013,17 +2045,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->slash_pos) {
*sshc->slash_pos = 0;
- infof(data, "Creating directory '%s'\n", sftp_scp->path);
- state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ infof(data, "Creating directory '%s'\n", sshp->path);
+ state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
/* 'mode' - parameter is preliminary - default to 0644 */
- rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
data->set.new_directory_perms);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -2041,19 +2073,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(sftperr != LIBSSH2_FX_FAILURE) &&
(sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
result = sftp_libssh2_error_to_CURLE(sftperr);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
rc = 0; /* clear rc and continue */
}
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
break;
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2062,9 +2094,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* listing
*/
sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
- sftp_scp->path,
+ sshp->path,
curlx_uztoui(
- strlen(sftp_scp->path)),
+ strlen(sshp->path)),
0, 0, LIBSSH2_SFTP_OPENDIR);
if(!sshc->sftp_handle) {
if(libssh2_session_last_errno(sshc->ssh_session) ==
@@ -2075,51 +2107,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open directory for reading: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
- sshc->readdir_filename = malloc(PATH_MAX + 1);
- if(!sshc->readdir_filename) {
- state(conn, SSH_SFTP_CLOSE);
+ sshp->readdir_filename = malloc(PATH_MAX + 1);
+ if(!sshp->readdir_filename) {
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- sshc->readdir_longentry = malloc(PATH_MAX + 1);
- if(!sshc->readdir_longentry) {
- Curl_safefree(sshc->readdir_filename);
- state(conn, SSH_SFTP_CLOSE);
+ sshp->readdir_longentry = malloc(PATH_MAX + 1);
+ if(!sshp->readdir_longentry) {
+ Curl_safefree(sshp->readdir_filename);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- Curl_dyn_init(&sshc->readdir, PATH_MAX * 2);
- state(conn, SSH_SFTP_READDIR);
+ Curl_dyn_init(&sshp->readdir, PATH_MAX * 2);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
- sshc->readdir_filename,
+ sshp->readdir_filename,
PATH_MAX,
- sshc->readdir_longentry,
+ sshp->readdir_longentry,
PATH_MAX,
- &sshc->readdir_attrs);
+ &sshp->readdir_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
if(rc > 0) {
readdir_len = (size_t) rc;
- sshc->readdir_filename[readdir_len] = '\0';
+ sshp->readdir_filename[readdir_len] = '\0';
if(data->set.ftp_list_only) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
- sshc->readdir_filename,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ sshp->readdir_filename,
readdir_len);
if(!result)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)"\n", 1);
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
/* since this counts what we send to the client, we include the
@@ -2127,39 +2159,37 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->req.bytecount += readdir_len + 1;
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_IN, sshc->readdir_filename,
- readdir_len);
- Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
- }
+ Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename,
+ readdir_len);
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
}
else {
- result = Curl_dyn_add(&sshc->readdir, sshc->readdir_longentry);
+ result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
if(!result) {
- if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
- ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
LIBSSH2_SFTP_S_IFLNK)) {
- Curl_dyn_init(&sshc->readdir_link, PATH_MAX);
- result = Curl_dyn_add(&sshc->readdir_link, sftp_scp->path);
- state(conn, SSH_SFTP_READDIR_LINK);
+ Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
+ result = Curl_dyn_add(&sshp->readdir_link, sshp->path);
+ state(data, SSH_SFTP_READDIR_LINK);
if(!result)
break;
}
else {
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
}
}
sshc->actualcode = result;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
break;
}
}
else if(rc == 0) {
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_READDIR_DONE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_READDIR_DONE);
break;
}
else if(rc < 0) {
@@ -2169,9 +2199,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Could not open remote file for reading: %s :: %d",
sftp_libssh2_strerror(sftperr),
libssh2_session_last_errno(sshc->ssh_session));
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_CLOSE);
break;
}
break;
@@ -2179,55 +2209,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_LINK:
rc =
libssh2_sftp_symlink_ex(sshc->sftp_session,
- Curl_dyn_ptr(&sshc->readdir_link),
- (int)Curl_dyn_len(&sshc->readdir_link),
- sshc->readdir_filename,
+ Curl_dyn_ptr(&sshp->readdir_link),
+ (int)Curl_dyn_len(&sshp->readdir_link),
+ sshp->readdir_filename,
PATH_MAX, LIBSSH2_SFTP_READLINK);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- readdir_len = (size_t) rc;
- Curl_dyn_free(&sshc->readdir_link);
+ Curl_dyn_free(&sshp->readdir_link);
/* append filename and extra output */
- result = Curl_dyn_addf(&sshc->readdir, " -> %s", sshc->readdir_filename);
+ result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
if(result) {
sshc->readdir_line = NULL;
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
case SSH_SFTP_READDIR_BOTTOM:
- result = Curl_dyn_addn(&sshc->readdir, "\n", 1);
+ result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
if(!result)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&sshc->readdir),
- Curl_dyn_len(&sshc->readdir));
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&sshp->readdir),
+ Curl_dyn_len(&sshp->readdir));
if(!result) {
-
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_IN,
- Curl_dyn_ptr(&sshc->readdir),
- Curl_dyn_len(&sshc->readdir));
- }
- data->req.bytecount += Curl_dyn_len(&sshc->readdir);
+ Curl_debug(data, CURLINFO_DATA_IN,
+ Curl_dyn_ptr(&sshp->readdir),
+ Curl_dyn_len(&sshp->readdir));
+ data->req.bytecount += Curl_dyn_len(&sshp->readdir);
}
if(result) {
- Curl_dyn_free(&sshc->readdir);
- state(conn, SSH_STOP);
+ Curl_dyn_free(&sshp->readdir);
+ state(data, SSH_STOP);
}
else {
- Curl_dyn_reset(&sshc->readdir);
- state(conn, SSH_SFTP_READDIR);
+ Curl_dyn_reset(&sshp->readdir);
+ state(data, SSH_SFTP_READDIR);
}
break;
@@ -2238,12 +2264,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
sshc->sftp_handle = NULL;
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_DOWNLOAD_INIT:
@@ -2251,8 +2277,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* Work on getting the specified file
*/
sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_FXF_READ, data->set.new_file_perms,
LIBSSH2_SFTP_OPENFILE);
if(!sshc->sftp_handle) {
@@ -2264,20 +2290,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open remote file for reading: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
break;
case SSH_SFTP_DOWNLOAD_STAT:
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -2302,14 +2328,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME;
}
- if(conn->data->state.use_range) {
+ if(data->state.use_range) {
curl_off_t from, to;
char *ptr;
char *ptr2;
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
@@ -2340,7 +2366,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
size = to - from + 1;
}
- SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
+ SFTP_SEEK(sshc->sftp_handle, from);
}
data->req.size = size;
data->req.maxdownload = size;
@@ -2383,7 +2409,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -2399,11 +2425,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -2422,7 +2448,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->sftp_handle = NULL;
}
- Curl_safefree(sftp_scp->path);
+ Curl_safefree(sshp->path);
DEBUGF(infof(data, "SFTP DONE done\n"));
@@ -2431,11 +2457,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
SSH_SFTP_CLOSE to pass the correct result back */
if(sshc->nextstate != SSH_NO_STATE &&
sshc->nextstate != SSH_SFTP_CLOSE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_SFTP_CLOSE;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
}
break;
@@ -2470,16 +2496,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
Curl_safefree(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
break;
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2487,13 +2513,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
}
- state(conn, SSH_SCP_UPLOAD_INIT);
+ state(data, SSH_SCP_UPLOAD_INIT);
}
else {
- state(conn, SSH_SCP_DOWNLOAD_INIT);
+ state(data, SSH_SCP_DOWNLOAD_INIT);
}
break;
@@ -2505,7 +2531,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* directory in the path.
*/
sshc->ssh_channel =
- SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
+ SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
data->state.infilesize);
if(!sshc->ssh_channel) {
int ssh_err;
@@ -2519,8 +2545,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0));
- failf(conn->data, "%s", err_msg);
- state(conn, SSH_SCP_CHANNEL_FREE);
+ failf(data, "%s", err_msg);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
/* Map generic errors to upload failed */
if(sshc->actualcode == CURLE_SSH ||
@@ -2538,7 +2564,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = result;
}
else {
@@ -2551,7 +2577,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_OUT;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -2573,12 +2599,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
struct stat sb;
memset(&sb, 0, sizeof(struct stat));
sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
- sftp_scp->path, &sb);
+ sshp->path, &sb);
#else
libssh2_struct_stat sb;
memset(&sb, 0, sizeof(libssh2_struct_stat));
sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
- sftp_scp->path, &sb);
+ sshp->path, &sb);
#endif
if(!sshc->ssh_channel) {
@@ -2594,8 +2620,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0));
- failf(conn->data, "%s", err_msg);
- state(conn, SSH_SCP_CHANNEL_FREE);
+ failf(data, "%s", err_msg);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
break;
}
@@ -2614,19 +2640,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->cselect_bits = CURL_CSELECT_IN;
if(result) {
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = result;
}
else
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
case SSH_SCP_DONE:
if(data->set.upload)
- state(conn, SSH_SCP_SEND_EOF);
+ state(data, SSH_SCP_SEND_EOF);
else
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
@@ -2643,7 +2669,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc, err_msg);
}
}
- state(conn, SSH_SCP_WAIT_EOF);
+ state(data, SSH_SCP_WAIT_EOF);
break;
case SSH_SCP_WAIT_EOF:
@@ -2659,7 +2685,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
}
}
- state(conn, SSH_SCP_WAIT_CLOSE);
+ state(data, SSH_SCP_WAIT_CLOSE);
break;
case SSH_SCP_WAIT_CLOSE:
@@ -2675,7 +2701,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
}
}
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
@@ -2695,9 +2721,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
DEBUGF(infof(data, "SCP DONE phase complete\n"));
#if 0 /* PREV */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
#endif
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
break;
@@ -2735,9 +2761,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
Curl_safefree(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
break;
case SSH_SESSION_FREE:
@@ -2805,11 +2831,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
Curl_safefree(sshc->homedir);
-
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
Curl_safefree(sshc->readdir_line);
- Curl_dyn_free(&sshc->readdir);
/* the code we are about to return */
result = sshc->actualcode;
@@ -2819,7 +2841,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_QUIT:
@@ -2827,7 +2849,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2844,11 +2866,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int ssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int ssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
int bitmap = GETSOCK_BLANK;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
@@ -2859,32 +2882,8 @@ static int ssh_perform_getsock(const struct connectdata *conn,
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
return bitmap;
-#else
- /* if we don't know the direction we can use the generic *_getsock()
- function even for the protocol_connect and doing states */
- return Curl_single_getsock(conn, sock);
-#endif
-}
-
-/* Generic function called by the multi interface to figure out what socket(s)
- to wait for and for what actions during the DOING and PROTOCONNECT states*/
-static int ssh_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
-#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
- (void)conn;
- (void)sock;
- /* if we don't know any direction we can just play along as we used to and
- not provide any sensible info */
- return GETSOCK_BLANK;
-#else
- /* if we know the direction we can use the generic *_getsock() function even
- for the protocol_connect and doing states */
- return ssh_perform_getsock(conn, sock);
-#endif
}
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
/*
* When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
* function is used to figure out in what direction and stores this info so
@@ -2892,8 +2891,9 @@ static int ssh_getsock(struct connectdata *conn,
* function in all cases so that when it _doesn't_ return EAGAIN we can
* restore the default wait bits.
*/
-static void ssh_block2waitfor(struct connectdata *conn, bool block)
+static void ssh_block2waitfor(struct Curl_easy *data, bool block)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
int dir = 0;
if(block) {
@@ -2909,46 +2909,43 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
the original set */
conn->waitfor = sshc->orig_waitfor;
}
-#else
- /* no libssh2 directional support so we simply don't know */
-#define ssh_block2waitfor(x,y) Curl_nop_stmt
-#endif
/* called repeatedly until done from multi.c */
-static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
do {
- result = ssh_statemach_act(conn, &block);
+ result = ssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */
} while(!result && !*done && !block);
- ssh_block2waitfor(conn, block);
+ ssh_block2waitfor(data, block);
return result;
}
-static CURLcode ssh_block_statemach(struct connectdata *conn,
- bool duringconnect)
+static CURLcode ssh_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool duringconnect)
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = ssh_statemach_act(conn, &block);
+ result = ssh_statemach_act(data, &block);
if(result)
break;
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -2961,7 +2958,6 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
if(block) {
int dir = libssh2_session_block_directions(sshc->ssh_session);
curl_socket_t sock = conn->sock[FIRSTSOCKET];
@@ -2975,8 +2971,6 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
(void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
left>1000?1000:left);
}
-#endif
-
}
return result;
@@ -2985,11 +2979,13 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
/*
* SSH setup and connection
*/
-static CURLcode ssh_setup_connection(struct connectdata *conn)
+static CURLcode ssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -2999,36 +2995,83 @@ static CURLcode ssh_setup_connection(struct connectdata *conn)
static Curl_recv scp_recv, sftp_recv;
static Curl_send scp_send, sftp_send;
+#ifndef CURL_DISABLE_PROXY
+static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
+ size_t length, int flags, void **abstract)
+{
+ struct Curl_easy *data = (struct Curl_easy *)*abstract;
+ ssize_t nread;
+ CURLcode result;
+ struct connectdata *conn = data->conn;
+ Curl_recv *backup = conn->recv[0];
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void)flags;
+
+ /* swap in the TLS reader function for this call only, and then swap back
+ the SSH one again */
+ conn->recv[0] = ssh->tls_recv;
+ result = Curl_read(data, sock, buffer, length, &nread);
+ conn->recv[0] = backup;
+ if(result == CURLE_AGAIN)
+ return -EAGAIN; /* magic return code for libssh2 */
+ else if(result)
+ return -1; /* generic error */
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
+ return nread;
+}
+
+static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
+ size_t length, int flags, void **abstract)
+{
+ struct Curl_easy *data = (struct Curl_easy *)*abstract;
+ ssize_t nwrite;
+ CURLcode result;
+ struct connectdata *conn = data->conn;
+ Curl_send *backup = conn->send[0];
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void)flags;
+
+ /* swap in the TLS writer function for this call only, and then swap back
+ the SSH one again */
+ conn->send[0] = ssh->tls_send;
+ result = Curl_write(data, sock, buffer, length, &nwrite);
+ conn->send[0] = backup;
+ if(result == CURLE_AGAIN)
+ return -EAGAIN; /* magic return code for libssh2 */
+ else if(result)
+ return -1; /* error */
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
+ return nwrite;
+}
+#endif
+
/*
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time.
*/
-static CURLcode ssh_connect(struct connectdata *conn, bool *done)
+static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
{
#ifdef CURL_LIBSSH2_DEBUG
curl_socket_t sock;
#endif
- struct ssh_conn *ssh;
+ struct SSHPROTO *sshp = data->req.p.ssh;
+ struct ssh_conn *sshc;
CURLcode result;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- ssh_setup_connection(conn);
+ if(!sshp) {
+ 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
function to make the re-use checks properly be able to check this bit. */
connkeep(conn, "SSH default");
- if(conn->handler->protocol & CURLPROTO_SCP) {
- conn->recv[FIRSTSOCKET] = scp_recv;
- conn->send[FIRSTSOCKET] = scp_send;
- }
- else {
- conn->recv[FIRSTSOCKET] = sftp_recv;
- conn->send[FIRSTSOCKET] = sftp_send;
- }
- ssh = &conn->proto.sshc;
+ sshc = &conn->proto.sshc;
#ifdef CURL_LIBSSH2_DEBUG
if(conn->user) {
@@ -3040,17 +3083,72 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
sock = conn->sock[FIRSTSOCKET];
#endif /* CURL_LIBSSH2_DEBUG */
- ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
- my_libssh2_free,
- my_libssh2_realloc, conn);
- if(ssh->ssh_session == NULL) {
+ sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
+ my_libssh2_free,
+ my_libssh2_realloc, data);
+ if(sshc->ssh_session == NULL) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
}
+#ifndef CURL_DISABLE_PROXY
+ if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
+ /*
+ * This crazy union dance is here to avoid assigning a void pointer a
+ * function pointer as it is invalid C. The problem is of course that
+ * libssh2 has such an API...
+ */
+ union receive {
+ void *recvp;
+ ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
+ };
+ union transfer {
+ void *sendp;
+ ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
+ };
+ union receive sshrecv;
+ union transfer sshsend;
+
+ sshrecv.recvptr = ssh_tls_recv;
+ sshsend.sendptr = ssh_tls_send;
+
+ infof(data, "Uses HTTPS proxy!\n");
+ /*
+ Setup libssh2 callbacks to make it read/write TLS from the socket.
+
+ ssize_t
+ recvcb(libssh2_socket_t sock, void *buffer, size_t length,
+ int flags, void **abstract);
+
+ ssize_t
+ sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
+ int flags, void **abstract);
+
+ */
+ libssh2_session_callback_set(sshc->ssh_session,
+ LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
+ libssh2_session_callback_set(sshc->ssh_session,
+ LIBSSH2_CALLBACK_SEND, sshsend.sendp);
+
+ /* Store the underlying TLS recv/send function pointers to be used when
+ reading from the proxy */
+ sshc->tls_recv = conn->recv[FIRSTSOCKET];
+ sshc->tls_send = conn->send[FIRSTSOCKET];
+ }
+
+#endif /* CURL_DISABLE_PROXY */
+ if(conn->handler->protocol & CURLPROTO_SCP) {
+ conn->recv[FIRSTSOCKET] = scp_recv;
+ conn->send[FIRSTSOCKET] = scp_send;
+ }
+ else {
+ conn->recv[FIRSTSOCKET] = sftp_recv;
+ conn->send[FIRSTSOCKET] = sftp_send;
+ }
+
if(data->set.ssh_compression) {
#if LIBSSH2_VERSION_NUM >= 0x010208
- if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
+ if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
#endif
infof(data, "Failed to enable compression for ssh session\n");
}
@@ -3058,14 +3156,14 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
int rc;
- ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
- if(!ssh->kh) {
- libssh2_session_free(ssh->ssh_session);
+ sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
+ if(!sshc->kh) {
+ libssh2_session_free(sshc->ssh_session);
return CURLE_FAILED_INIT;
}
/* read all known hosts from there */
- rc = libssh2_knownhost_readfile(ssh->kh,
+ rc = libssh2_knownhost_readfile(sshc->kh,
data->set.str[STRING_SSH_KNOWNHOSTS],
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(rc < 0)
@@ -3075,13 +3173,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
#ifdef CURL_LIBSSH2_DEBUG
- libssh2_trace(ssh->ssh_session, ~0);
+ libssh2_trace(sshc->ssh_session, ~0);
infof(data, "SSH socket: %d\n", (int)sock);
#endif /* CURL_LIBSSH2_DEBUG */
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
- result = ssh_multi_statemach(conn, done);
+ result = ssh_multi_statemach(data, done);
return result;
}
@@ -3096,40 +3194,41 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
*/
static
-CURLcode scp_perform(struct connectdata *conn,
- bool *connected,
- bool *dophase_done)
+CURLcode scp_perform(struct Curl_easy *data,
+ bool *connected,
+ bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SCP_TRANS_INIT);
+ state(data, SSH_SCP_TRANS_INIT);
/* run the state-machine */
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode scp_doing(struct connectdata *conn,
- bool *dophase_done)
+static CURLcode scp_doing(struct Curl_easy *data,
+ bool *dophase_done)
{
CURLcode result;
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -3139,11 +3238,11 @@ static CURLcode scp_doing(struct connectdata *conn,
* separate ones but this way means less duplicated code.
*/
-static CURLcode ssh_do(struct connectdata *conn, bool *done)
+static CURLcode ssh_do(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -3160,9 +3259,9 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = scp_perform(conn, &connected, done);
+ result = scp_perform(data, &connected, done);
else
- result = sftp_perform(conn, &connected, done);
+ result = sftp_perform(data, &connected, done);
return result;
}
@@ -3170,18 +3269,20 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
CURLcode result = CURLE_OK;
- struct ssh_conn *ssh = &conn->proto.sshc;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void) dead_connection;
- if(ssh->ssh_session) {
+ if(sshc->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(data, conn, FALSE);
}
return result;
@@ -3189,51 +3290,56 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *sftp_scp = conn->data->req.protop;
+ struct SSHPROTO *sshp = data->req.p.ssh;
+ struct connectdata *conn = data->conn;
if(!status) {
/* run the state-machine */
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(data, conn, FALSE);
}
else
result = status;
- if(sftp_scp)
- Curl_safefree(sftp_scp->path);
- if(Curl_pgrsDone(conn))
+ Curl_safefree(sshp->path);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ Curl_dyn_free(&sshp->readdir);
+
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
-static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void)premature; /* not used */
if(!status)
- state(conn, SSH_SCP_DONE);
+ state(data, SSH_SCP_DONE);
- return ssh_done(conn, status);
+ return ssh_done(data, status);
}
-static ssize_t scp_send(struct connectdata *conn, int sockindex,
+static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_write() returns int! */
- nwrite = (ssize_t)
- libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
+ nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3247,17 +3353,18 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return nwrite;
}
-static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_read() returns int */
- nread = (ssize_t)
- libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
+ nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
@@ -3280,39 +3387,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = ssh_multi_statemach(conn, dophase_done);
+ CURLcode result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -3320,53 +3427,56 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
CURLcode result = CURLE_OK;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void) dead_connection;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
- if(conn->proto.sshc.ssh_session) {
+ if(sshc->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = ssh_block_statemach(conn, FALSE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = ssh_block_statemach(data, conn, FALSE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
if(!status) {
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!premature && conn->data->set.postquote && !conn->bits.retry)
+ if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
}
- return ssh_done(conn, status);
+ return ssh_done(data, status);
}
/* return number of sent bytes */
-static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
- ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
- but is changed to ssize_t in 0.15. These days we don't
- support libssh2 0.15*/
+ ssize_t nwrite;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex;
- nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
+ nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3384,15 +3494,17 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex;
- nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
+ nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
diff --git a/Utilities/cmcurl/lib/vssh/ssh.h b/Utilities/cmcurl/lib/vssh/ssh.h
index 9e49993e9..52e1ee6c2 100644
--- a/Utilities/cmcurl/lib/vssh/ssh.h
+++ b/Utilities/cmcurl/lib/vssh/ssh.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -111,6 +111,17 @@ typedef enum {
struct. */
struct SSHPROTO {
char *path; /* the path we operate on */
+#ifdef USE_LIBSSH2
+ struct dynbuf readdir_link;
+ struct dynbuf readdir;
+ char *readdir_filename;
+ char *readdir_longentry;
+
+ LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
+
+ /* Here's a set of struct members used by the SFTP_READDIR state */
+ LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
+#endif
};
/* ssh_conn is used for struct connection-oriented data in the connectdata
@@ -123,6 +134,8 @@ struct ssh_conn {
char *rsa_pub; /* path name */
char *rsa; /* path name */
bool authed; /* the connection has been authenticated fine */
+ bool acceptfail; /* used by the SFTP_QUOTE (continue if
+ quote command fails) */
sshstate state; /* always use ssh.c:state() to change state! */
sshstate nextstate; /* the state to goto after stopping */
CURLcode actualcode; /* the actual error code */
@@ -130,8 +143,6 @@ struct ssh_conn {
char *quote_path1; /* two generic pointers for the QUOTE stuff */
char *quote_path2;
- bool acceptfail; /* used by the SFTP_QUOTE (continue if
- quote command fails) */
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */
char *readdir_line;
@@ -140,9 +151,8 @@ struct ssh_conn {
int secondCreateDirs; /* counter use by the code to see if the
second attempt has been made to change
to/create a directory */
- char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
-
int orig_waitfor; /* default READ/WRITE bits wait for */
+ char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
#if defined(USE_LIBSSH)
char *readdir_linkPath;
@@ -168,20 +178,17 @@ struct ssh_conn {
const char *readdir_longentry;
char *readdir_tmp;
#elif defined(USE_LIBSSH2)
- struct dynbuf readdir_link;
- struct dynbuf readdir;
- char *readdir_filename;
- char *readdir_longentry;
-
- LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
-
- /* Here's a set of struct members used by the SFTP_READDIR state */
- LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
LIBSSH2_SFTP_HANDLE *sftp_handle;
+#ifndef CURL_DISABLE_PROXY
+ /* for HTTPS proxy storage */
+ Curl_recv *tls_recv;
+ Curl_send *tls_send;
+#endif
+
#ifdef HAVE_LIBSSH2_AGENT_API
LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */
struct libssh2_agent_publickey *sshagent_identity,
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.c b/Utilities/cmcurl/lib/vssh/wolfssh.c
index dcbbab6c3..6020180a5 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.c
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -45,27 +45,30 @@
#include "curl_memory.h"
#include "memdebug.h"
-static CURLcode wssh_connect(struct connectdata *conn, bool *done);
-static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done);
-static CURLcode wssh_do(struct connectdata *conn, bool *done);
+static CURLcode wssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done);
+static CURLcode wssh_do(struct Curl_easy *data, bool *done);
#if 0
-static CURLcode wscp_done(struct connectdata *conn,
+static CURLcode wscp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode wscp_doing(struct connectdata *conn,
+static CURLcode wscp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode wscp_disconnect(struct connectdata *conn,
+static CURLcode wscp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
#endif
-static CURLcode wsftp_done(struct connectdata *conn,
+static CURLcode wsftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode wsftp_doing(struct connectdata *conn,
+static CURLcode wsftp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead);
-static int wssh_getsock(struct connectdata *conn,
+static CURLcode wsftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead);
+static int wssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock);
-static int wssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
-static CURLcode wssh_setup_connection(struct connectdata *conn);
+static CURLcode wssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
#if 0
/*
@@ -84,7 +87,7 @@ const struct Curl_handler Curl_handler_scp = {
wssh_getsock, /* proto_getsock */
wssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- wssh_perform_getsock, /* perform_getsock */
+ wssh_getsock, /* perform_getsock */
wscp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
@@ -112,12 +115,13 @@ const struct Curl_handler Curl_handler_sftp = {
wssh_getsock, /* proto_getsock */
wssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- wssh_perform_getsock, /* perform_getsock */
+ wssh_getsock, /* perform_getsock */
wsftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -126,8 +130,9 @@ const struct Curl_handler Curl_handler_sftp = {
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void state(struct connectdata *conn, sshstate nowstate)
+static void state(struct Curl_easy *data, sshstate nowstate)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
@@ -198,7 +203,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
if(sshc->state != nowstate) {
- infof(conn->data, "wolfssh %p state change from %s to %s\n",
+ infof(data, "wolfssh %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
@@ -206,11 +211,11 @@ static void state(struct connectdata *conn, sshstate nowstate)
sshc->state = nowstate;
}
-static ssize_t wscp_send(struct connectdata *conn, int sockindex,
+static ssize_t wscp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite = 0;
- (void)conn;
+ (void)data;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)mem;
(void)len;
@@ -219,11 +224,11 @@ static ssize_t wscp_send(struct connectdata *conn, int sockindex,
return nwrite;
}
-static ssize_t wscp_recv(struct connectdata *conn, int sockindex,
+static ssize_t wscp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread = 0;
- (void)conn;
+ (void)data;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)mem;
(void)len;
@@ -233,9 +238,10 @@ static ssize_t wscp_recv(struct connectdata *conn, int sockindex,
}
/* return number of sent bytes */
-static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
+static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
word32 offset[2];
int rc;
@@ -262,11 +268,11 @@ static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
return -1;
}
if(rc < 0) {
- failf(conn->data, "wolfSSH_SFTP_SendWritePacket returned %d\n", rc);
+ failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc);
return -1;
}
DEBUGASSERT(rc == (int)len);
- infof(conn->data, "sent %zd bytes SFTP from offset %zd\n",
+ infof(data, "sent %zd bytes SFTP from offset %zd\n",
len, sshc->offset);
sshc->offset += len;
return (ssize_t)rc;
@@ -276,10 +282,11 @@ static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
int rc;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
word32 offset[2];
(void)sockindex;
@@ -307,7 +314,7 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
DEBUGASSERT(rc <= (int)len);
if(rc < 0) {
- failf(conn->data, "wolfSSH_SFTP_SendReadPacket returned %d\n", rc);
+ failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc);
return -1;
}
sshc->offset += len;
@@ -318,11 +325,13 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
/*
* SSH setup and connection
*/
-static CURLcode wssh_setup_connection(struct connectdata *conn)
+static CURLcode wssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -336,28 +345,28 @@ static int userauth(byte authtype,
WS_UserAuthData* authdata,
void *ctx)
{
- struct connectdata *conn = ctx;
- DEBUGF(infof(conn->data, "wolfssh callback: type %s\n",
+ struct Curl_easy *data = ctx;
+ DEBUGF(infof(data, "wolfssh callback: type %s\n",
authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" :
"PUBLICCKEY"));
if(authtype == WOLFSSH_USERAUTH_PASSWORD) {
- authdata->sf.password.password = (byte *)conn->passwd;
- authdata->sf.password.passwordSz = (word32) strlen(conn->passwd);
+ authdata->sf.password.password = (byte *)data->conn->passwd;
+ authdata->sf.password.passwordSz = (word32) strlen(data->conn->passwd);
}
return 0;
}
-static CURLcode wssh_connect(struct connectdata *conn, bool *done)
+static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- wssh_setup_connection(conn);
+ if(!data->req.p.ssh)
+ wssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
@@ -392,7 +401,7 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
/* set callback for authentication */
wolfSSH_SetUserAuth(sshc->ctx, userauth);
- wolfSSH_SetUserAuthCtx(sshc->ssh_session, conn);
+ wolfSSH_SetUserAuthCtx(sshc->ssh_session, data);
rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock);
if(rc) {
@@ -406,11 +415,11 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
*done = TRUE;
if(conn->handler->protocol & CURLPROTO_SCP)
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
else
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
- return wssh_multi_statemach(conn, done);
+ return wssh_multi_statemach(data, done);
error:
wolfSSH_free(sshc->ssh_session);
wolfSSH_CTX_free(sshc->ctx);
@@ -424,12 +433,12 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
* wants to be called again when the socket is ready
*/
-static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
+static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *sftp_scp = data->req.protop;
+ struct SSHPROTO *sftp_scp = data->req.p.ssh;
WS_SFTPNAME *name;
int rc = 0;
*block = FALSE; /* we're not blocking by default */
@@ -437,7 +446,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
do {
switch(sshc->state) {
case SSH_INIT:
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
rc = wolfSSH_connect(sshc->ssh_session);
@@ -454,11 +463,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
return CURLE_OK;
}
else if(rc != WS_SUCCESS) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_SSH;
}
infof(data, "wolfssh connected!\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_STOP:
break;
@@ -479,7 +488,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
}
else if(rc == WS_SUCCESS) {
infof(data, "wolfssh SFTP connected!\n");
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
}
else {
failf(data, "wolfssh SFTP connect error %d", rc);
@@ -510,45 +519,45 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "wolfssh SFTP realpath succeeded!\n");
}
wolfSSH_SFTPNAME_list_free(name);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_OK;
}
failf(data, "wolfssh SFTP realpath %d", rc);
return CURLE_SSH;
case SSH_SFTP_QUOTE_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sftp_scp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
case SSH_SFTP_UPLOAD_INIT: {
@@ -583,7 +592,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;
memset(&createattrs, 0, sizeof(createattrs));
@@ -611,7 +620,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "wolfssh SFTP upload open failed: %d", rc);
return CURLE_SSH;
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
/* If we have a restart point then we need to seek to the correct
position. */
@@ -676,7 +685,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
@@ -694,7 +703,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
}
@@ -717,7 +726,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
}
else if(rc == WS_SUCCESS) {
infof(data, "wolfssh SFTP open succeeded!\n");
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
return CURLE_OK;
}
@@ -762,7 +771,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
/* We cannot seek with wolfSSH so resuming and range requests are not
possible */
- if(conn->data->state.use_range || data->state.resume_from) {
+ if(data->state.use_range || data->state.resume_from) {
infof(data, "wolfSSH cannot do range/seek on SFTP\n");
return CURLE_BAD_DOWNLOAD_RESUME;
}
@@ -772,7 +781,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -788,11 +797,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
}
@@ -813,7 +822,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
return CURLE_OK;
}
else if(rc == WS_SUCCESS) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_OK;
}
@@ -823,10 +832,10 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
/* FALLTHROUGH */
case SSH_SFTP_READDIR:
name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path);
@@ -853,11 +862,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
data->set.ftp_list_only ?
name->fName : name->lName);
if(line == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
line, strlen(line));
free(line);
if(result) {
@@ -867,7 +876,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
name = name->next;
}
wolfSSH_SFTPNAME_list_free(origname);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return result;
}
failf(data, "wolfssh SFTP ls failed: %d", rc);
@@ -877,7 +886,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->homedir);
wolfSSH_free(sshc->ssh_session);
wolfSSH_CTX_free(sshc->ctx);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_OK;
default:
break;
@@ -887,19 +896,20 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
}
/* called repeatedly until done from multi.c */
-static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
do {
- result = wssh_statemach_act(conn, &block);
+ result = wssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */
if(*done) {
- DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n"));
+ DEBUGF(infof(data, "wssh_statemach_act says DONE\n"));
}
} while(!result && !*done && !block);
@@ -907,37 +917,38 @@ static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done)
}
static
-CURLcode wscp_perform(struct connectdata *conn,
+CURLcode wscp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
- (void)conn;
+ (void)data;
(void)connected;
(void)dophase_done;
return CURLE_OK;
}
static
-CURLcode wsftp_perform(struct connectdata *conn,
+CURLcode wsftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = wssh_multi_statemach(conn, dophase_done);
+ result = wssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -946,11 +957,11 @@ CURLcode wsftp_perform(struct connectdata *conn,
/*
* The DO function is generic for both protocols.
*/
-static CURLcode wssh_do(struct connectdata *conn, bool *done)
+static CURLcode wssh_do(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -965,31 +976,31 @@ static CURLcode wssh_do(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = wscp_perform(conn, &connected, done);
+ result = wscp_perform(data, &connected, done);
else
- result = wsftp_perform(conn, &connected, done);
+ result = wsftp_perform(data, &connected, done);
return result;
}
-static CURLcode wssh_block_statemach(struct connectdata *conn,
+static CURLcode wssh_block_statemach(struct Curl_easy *data,
bool disconnect)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = wssh_statemach_act(conn, &block);
+ result = wssh_statemach_act(data, &block);
if(result)
break;
if(!disconnect) {
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -1024,29 +1035,29 @@ static CURLcode wssh_block_statemach(struct connectdata *conn,
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode wssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode wssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *sftp_scp = conn->data->req.protop;
+ struct SSHPROTO *sftp_scp = data->req.p.ssh;
if(!status) {
/* run the state-machine */
- result = wssh_block_statemach(conn, FALSE);
+ result = wssh_block_statemach(data, FALSE);
}
else
result = status;
if(sftp_scp)
Curl_safefree(sftp_scp->path);
- if(Curl_pgrsDone(conn))
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
#if 0
-static CURLcode wscp_done(struct connectdata *conn,
+static CURLcode wscp_done(struct Curl_easy *data,
CURLcode code, bool premature)
{
CURLcode result = CURLE_OK;
@@ -1057,7 +1068,7 @@ static CURLcode wscp_done(struct connectdata *conn,
return result;
}
-static CURLcode wscp_doing(struct connectdata *conn,
+static CURLcode wscp_doing(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
@@ -1067,9 +1078,11 @@ static CURLcode wscp_doing(struct connectdata *conn,
return result;
}
-static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode wscp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
CURLcode result = CURLE_OK;
+ (void)data;
(void)conn;
(void)dead_connection;
@@ -1077,54 +1090,52 @@ static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)
}
#endif
-static CURLcode wsftp_done(struct connectdata *conn,
+static CURLcode wsftp_done(struct Curl_easy *data,
CURLcode code, bool premature)
{
(void)premature;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
- return wssh_done(conn, code);
+ return wssh_done(data, code);
}
-static CURLcode wsftp_doing(struct connectdata *conn,
+static CURLcode wsftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = wssh_multi_statemach(conn, dophase_done);
+ CURLcode result = wssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
-static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead)
+static CURLcode wsftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead)
{
CURLcode result = CURLE_OK;
(void)dead;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = wssh_block_statemach(conn, TRUE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = wssh_block_statemach(data, TRUE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static int wssh_getsock(struct connectdata *conn,
+static int wssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock)
{
- return wssh_perform_getsock(conn, sock);
-}
-
-static int wssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
-{
int bitmap = GETSOCK_BLANK;
int dir = conn->waitfor;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
if(dir == KEEP_RECV)
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.h b/Utilities/cmcurl/lib/vssh/wolfssh.h
index a9b9a3b09..7b6ac489a 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.h
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
index 44e7406e8..29b08c0e6 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.c
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) 2019 - 2021, Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -294,9 +294,9 @@ static const br_x509_class x509_vtable = {
x509_get_pkey
};
-static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->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);
@@ -349,8 +349,8 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
- failf(data, "error setting certificate verify locations:\n"
- " CAfile: %s\n", ssl_cafile);
+ failf(data, "error setting certificate verify locations."
+ " CAfile: %s", ssl_cafile);
return ret;
}
infof(data, "error setting certificate verify locations,"
@@ -374,12 +374,12 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
if(SSL_SET_OPTION(primary.sessionid)) {
void *session;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &session, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &session, NULL, sockindex)) {
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
infof(data, "BearSSL: re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
if(conn->bits.tls_enable_alpn) {
@@ -429,10 +429,10 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex,
+static CURLcode bearssl_run_until(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
unsigned target)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
curl_socket_t sockfd = conn->sock[sockindex];
@@ -507,14 +507,15 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex,
}
}
-static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CURLcode ret;
- ret = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
+ ret = bearssl_run_until(data, conn, sockindex,
+ BR_SSL_SENDAPP | BR_SSL_RECVAPP);
if(ret == CURLE_AGAIN)
return CURLE_OK;
if(ret == CURLE_OK) {
@@ -527,9 +528,9 @@ static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex)
return ret;
}
-static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CURLcode ret;
@@ -552,7 +553,7 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
conn->negnpn = CURL_HTTP_VERSION_1_1;
else
infof(data, "ALPN, unrecognized protocol %s\n", protocol);
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else
@@ -568,12 +569,13 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
if(!session)
return CURLE_OUT_OF_MEMORY;
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &oldsession, NULL, sockindex));
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn,
+ &oldsession, NULL, sockindex));
if(incache)
- Curl_ssl_delsessionid(conn, oldsession);
- ret = Curl_ssl_addsessionid(conn, session, 0, sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_delsessionid(data, oldsession);
+ ret = Curl_ssl_addsessionid(data, conn, session, 0, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(ret) {
free(session);
return CURLE_OUT_OF_MEMORY;
@@ -585,17 +587,17 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
+static ssize_t bearssl_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
unsigned char *app;
size_t applen;
for(;;) {
- *err = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP);
+ *err = bearssl_run_until(data, conn, sockindex, BR_SSL_SENDAPP);
if (*err != CURLE_OK)
return -1;
app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
@@ -618,15 +620,16 @@ static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
}
}
-static ssize_t bearssl_recv(struct connectdata *conn, int sockindex,
+static ssize_t bearssl_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t len, CURLcode *err)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
unsigned char *app;
size_t applen;
- *err = bearssl_run_until(conn, sockindex, BR_SSL_RECVAPP);
+ *err = bearssl_run_until(data, conn, sockindex, BR_SSL_RECVAPP);
if(*err != CURLE_OK)
return -1;
app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
@@ -640,13 +643,13 @@ static ssize_t bearssl_recv(struct connectdata *conn, int sockindex,
return applen;
}
-static CURLcode bearssl_connect_common(struct connectdata *conn,
+static CURLcode bearssl_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode ret;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -659,7 +662,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
}
if(ssl_connect_1 == connssl->connecting_state) {
- ret = bearssl_connect_step1(conn, sockindex);
+ ret = bearssl_connect_step1(data, conn, sockindex);
if(ret)
return ret;
}
@@ -712,7 +715,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- ret = bearssl_connect_step2(conn, sockindex);
+ ret = bearssl_connect_step2(data, conn, sockindex);
if(ret || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -721,7 +724,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
}
if(ssl_connect_3 == connssl->connecting_state) {
- ret = bearssl_connect_step3(conn, sockindex);
+ ret = bearssl_connect_step3(data, conn, sockindex);
if(ret)
return ret;
}
@@ -741,21 +744,21 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static size_t Curl_bearssl_version(char *buffer, size_t size)
+static size_t bearssl_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "BearSSL");
}
-static bool Curl_bearssl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool bearssl_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
struct ssl_backend_data *backend = connssl->backend;
return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
}
-static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
+static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
static br_hmac_drbg_context ctx;
static bool seeded = FALSE;
@@ -774,12 +777,13 @@ static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode ret;
bool done = FALSE;
- ret = bearssl_connect_common(conn, sockindex, FALSE, &done);
+ ret = bearssl_connect_common(data, conn, sockindex, FALSE, &done);
if(ret)
return ret;
@@ -788,20 +792,22 @@ static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode Curl_bearssl_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode bearssl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return bearssl_connect_common(conn, sockindex, TRUE, done);
+ return bearssl_connect_common(data, conn, sockindex, TRUE, done);
}
-static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *bearssl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
return &backend->ctx;
}
-static void Curl_bearssl_close(struct connectdata *conn, int sockindex)
+static void bearssl_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;
@@ -809,35 +815,22 @@ static void Curl_bearssl_close(struct connectdata *conn, int sockindex)
if(backend->active) {
br_ssl_engine_close(&backend->ctx.eng);
- (void)bearssl_run_until(conn, sockindex, BR_SSL_CLOSED);
+ (void)bearssl_run_until(data, conn, sockindex, BR_SSL_CLOSED);
}
for(i = 0; i < backend->anchors_len; ++i)
free(backend->anchors[i].dn.data);
free(backend->anchors);
}
-static void Curl_bearssl_session_free(void *ptr)
+static void bearssl_session_free(void *ptr)
{
free(ptr);
}
-static CURLcode Curl_bearssl_md5sum(unsigned char *input,
- size_t inputlen,
- unsigned char *md5sum,
- size_t md5len UNUSED_PARAM)
-{
- br_md5_context ctx;
-
- br_md5_init(&ctx);
- br_md5_update(&ctx, input, inputlen);
- br_md5_out(&ctx, md5sum);
- return CURLE_OK;
-}
-
-static CURLcode Curl_bearssl_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len UNUSED_PARAM)
+static CURLcode bearssl_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
{
br_sha256_context ctx;
@@ -854,24 +847,23 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_init,
Curl_none_cleanup,
- Curl_bearssl_version,
+ bearssl_version,
Curl_none_check_cxn,
Curl_none_shutdown,
- Curl_bearssl_data_pending,
- Curl_bearssl_random,
+ bearssl_data_pending,
+ bearssl_random,
Curl_none_cert_status_request,
- Curl_bearssl_connect,
- Curl_bearssl_connect_nonblocking,
- Curl_bearssl_get_internals,
- Curl_bearssl_close,
+ bearssl_connect,
+ bearssl_connect_nonblocking,
+ bearssl_get_internals,
+ bearssl_close,
Curl_none_close_all,
- Curl_bearssl_session_free,
+ bearssl_session_free,
Curl_none_set_engine,
Curl_none_set_engine_default,
Curl_none_engines_list,
Curl_none_false_start,
- Curl_bearssl_md5sum,
- Curl_bearssl_sha256sum
+ bearssl_sha256sum
};
#endif /* USE_BEARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.h b/Utilities/cmcurl/lib/vtls/bearssl.h
index 5f94922b9..d72b7d0e2 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.h
+++ b/Utilities/cmcurl/lib/vtls/bearssl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) 2019 - 2020, Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 0538e4a46..9b5f649f7 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -301,10 +301,9 @@ static CURLcode set_callback(struct Curl_easy *data,
}
-static CURLcode set_ciphers(struct connectdata *conn,
+static CURLcode set_ciphers(struct Curl_easy *data,
gsk_handle h, unsigned int *protoflags)
{
- struct Curl_easy *data = conn->data;
const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
const char *clp;
const struct gskit_cipher *ctp;
@@ -435,7 +434,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
}
-static int Curl_gskit_init(void)
+static int gskit_init(void)
{
/* No initialisation needed. */
@@ -443,7 +442,7 @@ static int Curl_gskit_init(void)
}
-static void Curl_gskit_cleanup(void)
+static void gskit_cleanup(void)
{
/* Nothing to do. */
}
@@ -587,11 +586,11 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
}
-static void close_one(struct ssl_connect_data *connssl,
+static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
struct connectdata *conn, int sockindex)
{
if(BACKEND->handle) {
- gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
+ gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
"gsk_secure_soc_close()", 0);
/* Last chance to drain output. */
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
@@ -612,10 +611,10 @@ static void close_one(struct ssl_connect_data *connssl,
static ssize_t gskit_send(struct connectdata *conn, int sockindex,
- const void *mem, size_t len, CURLcode *curlcode)
+ const void *mem, size_t len, CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
CURLcode cc = CURLE_SEND_ERROR;
int written;
@@ -636,11 +635,11 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
}
-static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
- size_t buffersize, CURLcode *curlcode)
+static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf,
+ size_t buffersize, CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
- struct Curl_easy *data = conn->data;
int nread;
CURLcode cc = CURLE_RECV_ERROR;
@@ -664,9 +663,8 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
}
static CURLcode
-set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
+set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
long i = ssl_version;
@@ -696,16 +694,16 @@ set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
return CURLE_OK;
}
-static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->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(cert);
+ 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:
@@ -798,7 +796,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
- result = set_ssl_version_min_max(&protoflags, conn);
+ result = set_ssl_version_min_max(&protoflags, data);
if(result != CURLE_OK)
return result;
break;
@@ -832,7 +830,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
BACKEND->localfd: conn->sock[sockindex]);
if(!result)
- result = set_ciphers(conn, BACKEND->handle, &protoflags);
+ result = set_ciphers(data, BACKEND->handle, &protoflags);
if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER;
@@ -915,15 +913,15 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
/* Error: rollback. */
- close_one(connssl, conn, sockindex);
+ close_one(connssl, data, conn, sockindex);
return result;
}
-static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
+static CURLcode gskit_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool nonblocking)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
Qso_OverlappedIO_t cstat;
struct timeval stmv;
@@ -971,9 +969,9 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
}
-static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
const gsk_cert_data_elem *cdev;
int cdec;
@@ -1016,7 +1014,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
}
/* Verify host. */
- result = Curl_verifyhost(conn, cert, certend);
+ result = Curl_verifyhost(data, conn, cert, certend);
if(result)
return result;
@@ -1031,7 +1029,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
return result;
if(cert) {
- result = Curl_extract_certinfo(conn, 0, cert, certend);
+ result = Curl_extract_certinfo(data, 0, cert, certend);
if(result)
return result;
}
@@ -1059,10 +1057,10 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
}
-static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
+static CURLcode gskit_connect_common(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool nonblocking, bool *done)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
timediff_t timeout_ms;
CURLcode result = CURLE_OK;
@@ -1082,7 +1080,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = CURLE_OPERATION_TIMEDOUT;
}
else
- result = gskit_connect_step1(conn, sockindex);
+ result = gskit_connect_step1(data, conn, sockindex);
}
/* Handle handshake pipelining. */
@@ -1101,7 +1099,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = CURLE_OPERATION_TIMEDOUT;
}
else
- result = gskit_connect_step2(conn, sockindex, nonblocking);
+ result = gskit_connect_step2(data, conn, sockindex, nonblocking);
}
/* Handle handshake pipelining. */
@@ -1111,10 +1109,10 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
/* Step 3: gather certificate info, verify host. */
if(!result && connssl->connecting_state == ssl_connect_3)
- result = gskit_connect_step3(conn, sockindex);
+ result = gskit_connect_step3(data, conn, sockindex);
if(result)
- close_one(connssl, conn, sockindex);
+ close_one(connssl, data, conn, sockindex);
else if(connssl->connecting_state == ssl_connect_done) {
connssl->state = ssl_connection_complete;
connssl->connecting_state = ssl_connect_1;
@@ -1127,25 +1125,27 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
}
-static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode gskit_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
CURLcode result;
- result = gskit_connect_common(conn, sockindex, TRUE, done);
+ result = gskit_connect_common(data, conn, sockindex, TRUE, done);
if(*done || result)
conn->ssl[sockindex].connecting_state = ssl_connect_1;
return result;
}
-static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done;
conn->ssl[sockindex].connecting_state = ssl_connect_1;
- result = gskit_connect_common(conn, sockindex, FALSE, &done);
+ result = gskit_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -1155,17 +1155,18 @@ static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
}
-static void Curl_gskit_close(struct connectdata *conn, int sockindex)
+static void gskit_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- close_one(&conn->ssl[sockindex], conn, sockindex);
- close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
+ close_one(&conn->ssl[sockindex], data, conn, sockindex);
+ close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
}
-static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+static int gskit_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
int what;
int rc;
char buf[120];
@@ -1178,7 +1179,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
return 0;
#endif
- close_one(connssl, conn, sockindex);
+ close_one(connssl, data, conn, sockindex);
rc = 0;
what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT);
@@ -1219,13 +1220,13 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
}
-static size_t Curl_gskit_version(char *buffer, size_t size)
+static size_t gskit_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "GSKit");
}
-static int Curl_gskit_check_cxn(struct connectdata *cxn)
+static int gskit_check_cxn(struct connectdata *cxn)
{
struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
int err;
@@ -1247,8 +1248,8 @@ static int Curl_gskit_check_cxn(struct connectdata *cxn)
return -1; /* connection status unknown */
}
-static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *gskit_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
(void)info;
return BACKEND->handle;
@@ -1262,18 +1263,18 @@ const struct Curl_ssl Curl_ssl_gskit = {
sizeof(struct ssl_backend_data),
- Curl_gskit_init, /* init */
- Curl_gskit_cleanup, /* cleanup */
- Curl_gskit_version, /* version */
- Curl_gskit_check_cxn, /* check_cxn */
- Curl_gskit_shutdown, /* shutdown */
+ gskit_init, /* init */
+ gskit_cleanup, /* cleanup */
+ gskit_version, /* version */
+ gskit_check_cxn, /* check_cxn */
+ gskit_shutdown, /* shutdown */
Curl_none_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_gskit_connect, /* connect */
- Curl_gskit_connect_nonblocking, /* connect_nonblocking */
- Curl_gskit_get_internals, /* get_internals */
- Curl_gskit_close, /* close_one */
+ gskit_connect, /* connect */
+ gskit_connect_nonblocking, /* connect_nonblocking */
+ gskit_get_internals, /* get_internals */
+ gskit_close, /* close_one */
Curl_none_close_all, /* close_all */
/* No session handling for GSKit */
Curl_none_session_free, /* session_free */
@@ -1281,7 +1282,6 @@ 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 */
- Curl_none_md5sum, /* md5sum */
NULL /* sha256sum */
};
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index b06b5e17d..202df7e07 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/lib/vtls/gskit.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 16b0bd6cb..3ddee1974 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -81,43 +81,43 @@ static bool gtls_inited = FALSE;
struct ssl_backend_data {
gnutls_session_t session;
gnutls_certificate_credentials_t cred;
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
gnutls_srp_client_credentials_t srp_client_cred;
#endif
};
-static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
+static ssize_t gtls_push(void *s, const void *buf, size_t len)
{
curl_socket_t sock = *(curl_socket_t *)s;
ssize_t ret = swrite(sock, buf, len);
return ret;
}
-static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
+static ssize_t gtls_pull(void *s, void *buf, size_t len)
{
curl_socket_t sock = *(curl_socket_t *)s;
ssize_t ret = sread(sock, buf, len);
return ret;
}
-static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
+static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len)
{
return gnutls_record_send((gnutls_session_t) s, buf, len);
}
-static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
+static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len)
{
return gnutls_record_recv((gnutls_session_t) s, buf, len);
}
-/* Curl_gtls_init()
+/* gtls_init()
*
* Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
* are not thread-safe and thus this function itself is not thread-safe and
* must only be called from within curl_global_init() to keep the thread
* situation under control!
*/
-static int Curl_gtls_init(void)
+static int gtls_init(void)
{
int ret = 1;
if(!gtls_inited) {
@@ -131,7 +131,7 @@ static int Curl_gtls_init(void)
return ret;
}
-static void Curl_gtls_cleanup(void)
+static void gtls_cleanup(void)
{
if(gtls_inited) {
gnutls_global_deinit();
@@ -200,12 +200,12 @@ static void unload_file(gnutls_datum_t data)
/* this function does a SSL/TLS (re-)handshake */
-static CURLcode handshake(struct connectdata *conn,
+static CURLcode handshake(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool duringconnect,
bool nonblocking)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
gnutls_session_t session = backend->session;
@@ -304,7 +304,7 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
return GNUTLS_X509_FMT_PEM;
if(strcasecompare(type, "DER"))
return GNUTLS_X509_FMT_DER;
- return -1;
+ return GNUTLS_X509_FMT_PEM; /* default to PEM */
}
#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
@@ -314,9 +314,9 @@ 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 connectdata *conn)
+set_ssl_version_min_max(const char **prioritylist, struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
@@ -379,10 +379,10 @@ set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
}
static CURLcode
-gtls_connect_step1(struct connectdata *conn,
+gtls_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
unsigned int init_flags;
@@ -399,15 +399,8 @@ gtls_connect_step1(struct connectdata *conn,
#endif
const char *prioritylist;
const char *err = NULL;
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- const char * const hostname = conn->host.name;
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
@@ -415,7 +408,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_OK;
if(!gtls_inited)
- Curl_gtls_init();
+ gtls_init();
/* Initialize certverifyresult to OK */
*certverifyresult = 0;
@@ -434,7 +427,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
@@ -575,7 +568,7 @@ gtls_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
+ CURLcode result = set_ssl_version_min_max(&prioritylist, data);
if(result != CURLE_OK)
return result;
break;
@@ -588,7 +581,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
@@ -610,7 +603,7 @@ gtls_connect_step1(struct connectdata *conn,
else {
#endif
rc = gnutls_priority_set_direct(session, prioritylist, &err);
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
}
#endif
@@ -645,7 +638,7 @@ gtls_connect_step1(struct connectdata *conn,
gnutls_alpn_set_protocols(session, protocols, cur, 0);
}
- if(SSL_SET_OPTION(cert)) {
+ if(SSL_SET_OPTION(primary.clientcert)) {
if(SSL_SET_OPTION(key_passwd)) {
const unsigned int supported_key_encryption_algorithms =
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
@@ -654,9 +647,9 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_PKCS_USE_PBES2_AES_256;
rc = gnutls_certificate_set_x509_key_file2(
backend->cred,
- SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(primary.clientcert),
SSL_SET_OPTION(key) ?
- SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
do_file_type(SSL_SET_OPTION(cert_type)),
SSL_SET_OPTION(key_passwd),
supported_key_encryption_algorithms);
@@ -670,9 +663,9 @@ gtls_connect_step1(struct connectdata *conn,
else {
if(gnutls_certificate_set_x509_key_file(
backend->cred,
- SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(primary.clientcert),
SSL_SET_OPTION(key) ?
- SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
do_file_type(SSL_SET_OPTION(cert_type)) ) !=
GNUTLS_E_SUCCESS) {
failf(data, "error reading X.509 key or certificate file");
@@ -681,7 +674,7 @@ gtls_connect_step1(struct connectdata *conn,
}
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
/* put the credentials to the current session */
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
@@ -705,16 +698,16 @@ gtls_connect_step1(struct connectdata *conn,
#ifndef CURL_DISABLE_PROXY
if(conn->proxy_ssl[sockindex].use) {
transport_ptr = conn->proxy_ssl[sockindex].backend->session;
- gnutls_transport_push = Curl_gtls_push_ssl;
- gnutls_transport_pull = Curl_gtls_pull_ssl;
+ gnutls_transport_push = gtls_push_ssl;
+ gnutls_transport_pull = gtls_pull_ssl;
}
else
#endif
{
/* file descriptor for the socket */
transport_ptr = &conn->sock[sockindex];
- gnutls_transport_push = Curl_gtls_push;
- gnutls_transport_pull = Curl_gtls_pull;
+ gnutls_transport_push = gtls_push;
+ gnutls_transport_pull = gtls_pull;
}
/* set the connection handle */
@@ -738,15 +731,16 @@ gtls_connect_step1(struct connectdata *conn,
void *ssl_sessionid;
size_t ssl_idsize;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn,
+ &ssl_sessionid, &ssl_idsize, sockindex)) {
/* we got a session id, use it! */
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
return CURLE_OK;
@@ -814,7 +808,8 @@ static Curl_recv gtls_recv;
static Curl_send gtls_send;
static CURLcode
-gtls_connect_step3(struct connectdata *conn,
+gtls_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
unsigned int cert_list_size;
@@ -827,7 +822,6 @@ gtls_connect_step3(struct connectdata *conn,
size_t size;
time_t certclock;
const char *ptr;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
gnutls_session_t session = backend->session;
@@ -839,15 +833,8 @@ gtls_connect_step3(struct connectdata *conn,
unsigned int bits;
gnutls_protocol_t version = gnutls_protocol_get_version(session);
#endif
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- const char * const hostname = conn->host.name;
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -868,7 +855,7 @@ gtls_connect_step3(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifypeer) ||
SSL_CONN_CONFIG(verifyhost) ||
SSL_SET_OPTION(issuercert)) {
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL
&& !SSL_CONN_CONFIG(verifypeer)
@@ -881,7 +868,7 @@ gtls_connect_step3(struct connectdata *conn,
failf(data, "failed to get server cert");
*certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
return CURLE_PEER_FAILED_VERIFICATION;
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
}
#endif
}
@@ -899,7 +886,7 @@ gtls_connect_step3(struct connectdata *conn,
const char *beg = (const char *) chainp[i].data;
const char *end = beg + chainp[i].size;
- result = Curl_extract_certinfo(conn, i, beg, end);
+ result = Curl_extract_certinfo(data, i, beg, end);
if(result)
return result;
}
@@ -1128,22 +1115,15 @@ gtls_connect_step3(struct connectdata *conn,
}
#endif
if(!rc) {
-#ifndef CURL_DISABLE_PROXY
- const char * const dispname = SSL_IS_PROXY() ?
- conn->http_proxy.host.dispname : conn->host.dispname;
-#else
- const char * const dispname = conn->host.dispname;
-#endif
-
if(SSL_CONN_CONFIG(verifyhost)) {
failf(data, "SSL: certificate subject name (%s) does not match "
- "target host name '%s'", certname, dispname);
+ "target host name '%s'", certname, SSL_HOST_DISPNAME());
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "\t common name: %s (does not match '%s')\n",
- certname, dispname);
+ certname, SSL_HOST_DISPNAME());
}
else
infof(data, "\t common name: %s (matched)\n", certname);
@@ -1246,13 +1226,18 @@ gtls_connect_step3(struct connectdata *conn,
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
showtime(data, "expire date", certclock);
+
+ gnutls_free(certfields.data);
}
rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
if(rc)
infof(data, "Failed to get certificate issuer\n");
- else
+ else {
infof(data, "\t issuer: %s\n", certfields.data);
+
+ gnutls_free(certfields.data);
+ }
#endif
gnutls_x509_crt_deinit(x509_cert);
@@ -1279,7 +1264,7 @@ gtls_connect_step3(struct connectdata *conn,
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
@@ -1306,19 +1291,19 @@ gtls_connect_step3(struct connectdata *conn,
/* extract session ID to the allocated buffer */
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, &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 */
- Curl_ssl_delsessionid(conn, ssl_sessionid);
+ Curl_ssl_delsessionid(data, ssl_sessionid);
}
/* store this session id */
- result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
- sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ result = Curl_ssl_addsessionid(data, conn, connect_sessionid,
+ connect_idsize, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(result) {
free(connect_sessionid);
result = CURLE_OUT_OF_MEMORY;
@@ -1342,7 +1327,8 @@ gtls_connect_step3(struct connectdata *conn,
'ssl_connect_2_writing' (waiting to be able to write).
*/
static CURLcode
-gtls_connect_common(struct connectdata *conn,
+gtls_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
@@ -1352,19 +1338,19 @@ gtls_connect_common(struct connectdata *conn,
/* Initiate the connection, if not already done */
if(ssl_connect_1 == connssl->connecting_state) {
- rc = gtls_connect_step1(conn, sockindex);
+ rc = gtls_connect_step1(data, conn, sockindex);
if(rc)
return rc;
}
- rc = handshake(conn, sockindex, TRUE, nonblocking);
+ rc = handshake(data, conn, sockindex, TRUE, nonblocking);
if(rc)
/* handshake() sets its own error message with failf() */
return rc;
/* Finish connecting once the handshake is done */
if(ssl_connect_1 == connssl->connecting_state) {
- rc = gtls_connect_step3(conn, sockindex);
+ rc = gtls_connect_step3(data, conn, sockindex);
if(rc)
return rc;
}
@@ -1374,18 +1360,20 @@ gtls_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return gtls_connect_common(conn, sockindex, TRUE, done);
+ return gtls_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
+static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = gtls_connect_common(conn, sockindex, FALSE, &done);
+ result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -1394,8 +1382,8 @@ static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static bool Curl_gtls_data_pending(const struct connectdata *conn,
- int connindex)
+static bool gtls_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
bool res = FALSE;
@@ -1415,12 +1403,13 @@ static bool Curl_gtls_data_pending(const struct connectdata *conn,
return res;
}
-static ssize_t gtls_send(struct connectdata *conn,
+static ssize_t gtls_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
ssize_t rc = gnutls_record_send(backend->session, mem, len);
@@ -1448,7 +1437,7 @@ static void close_one(struct ssl_connect_data *connssl)
gnutls_certificate_free_credentials(backend->cred);
backend->cred = NULL;
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(backend->srp_client_cred) {
gnutls_srp_free_client_credentials(backend->srp_client_cred);
backend->srp_client_cred = NULL;
@@ -1456,8 +1445,10 @@ static void close_one(struct ssl_connect_data *connssl)
#endif
}
-static void Curl_gtls_close(struct connectdata *conn, int sockindex)
+static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
+ (void) data;
close_one(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
close_one(&conn->proxy_ssl[sockindex]);
@@ -1468,12 +1459,12 @@ static void Curl_gtls_close(struct connectdata *conn, int sockindex)
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
+static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
int retval = 0;
- struct Curl_easy *data = conn->data;
#ifndef CURL_DISABLE_FTP
/* This has only been tested on the proftpd server, and the mod_tls code
@@ -1530,7 +1521,7 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
}
gnutls_certificate_free_credentials(backend->cred);
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL)
gnutls_srp_free_client_credentials(backend->srp_client_cred);
@@ -1542,12 +1533,13 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
return retval;
}
-static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
+static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
ssize_t ret;
@@ -1561,7 +1553,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
if(ret == GNUTLS_E_REHANDSHAKE) {
/* BLOCKING call, this is bad but a work-around for now. Fixing this "the
proper way" takes a whole lot of work. */
- CURLcode result = handshake(conn, num, FALSE, FALSE);
+ CURLcode result = handshake(data, conn, num, FALSE, FALSE);
if(result)
/* handshake() writes error message on its own */
*curlcode = result;
@@ -1571,7 +1563,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
}
if(ret < 0) {
- failf(conn->data, "GnuTLS recv error (%d): %s",
+ failf(data, "GnuTLS recv error (%d): %s",
(int)ret, gnutls_strerror((int)ret));
*curlcode = CURLE_RECV_ERROR;
@@ -1581,18 +1573,18 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
return ret;
}
-static void Curl_gtls_session_free(void *ptr)
+static void gtls_session_free(void *ptr)
{
free(ptr);
}
-static size_t Curl_gtls_version(char *buffer, size_t size)
+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 Curl_gtls_seed(struct Curl_easy *data)
+static int gtls_seed(struct Curl_easy *data)
{
/* we have the "SSL is seeded" boolean static to prevent multiple
time-consuming seedings in vain */
@@ -1610,8 +1602,8 @@ static int Curl_gtls_seed(struct Curl_easy *data)
#endif
/* data might be NULL! */
-static CURLcode Curl_gtls_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode gtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
int rc;
@@ -1620,36 +1612,16 @@ static CURLcode Curl_gtls_random(struct Curl_easy *data,
return rc?CURLE_FAILED_INIT:CURLE_OK;
#elif defined(USE_GNUTLS)
if(data)
- Curl_gtls_seed(data); /* Initiate the seed if not already done */
+ gtls_seed(data); /* Initiate the seed if not already done */
gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
#endif
return CURLE_OK;
}
-static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
-#if defined(USE_GNUTLS_NETTLE)
- struct md5_ctx MD5pw;
- md5_init(&MD5pw);
- md5_update(&MD5pw, (unsigned int)tmplen, tmp);
- md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
-#elif defined(USE_GNUTLS)
- gcry_md_hd_t MD5pw;
- gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
- gcry_md_write(MD5pw, tmp, tmplen);
- memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
- gcry_md_close(MD5pw);
-#endif
- return CURLE_OK;
-}
-
-static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
#if defined(USE_GNUTLS_NETTLE)
struct sha256_ctx SHA256pw;
@@ -1666,12 +1638,12 @@ static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
return CURLE_OK;
}
-static bool Curl_gtls_cert_status_request(void)
+static bool gtls_cert_status_request(void)
{
return TRUE;
}
-static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
+static void *gtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
@@ -1689,26 +1661,25 @@ const struct Curl_ssl Curl_ssl_gnutls = {
sizeof(struct ssl_backend_data),
- Curl_gtls_init, /* init */
- Curl_gtls_cleanup, /* cleanup */
- Curl_gtls_version, /* version */
+ gtls_init, /* init */
+ gtls_cleanup, /* cleanup */
+ gtls_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_gtls_shutdown, /* shutdown */
- Curl_gtls_data_pending, /* data_pending */
- Curl_gtls_random, /* random */
- Curl_gtls_cert_status_request, /* cert_status_request */
- Curl_gtls_connect, /* connect */
- Curl_gtls_connect_nonblocking, /* connect_nonblocking */
- Curl_gtls_get_internals, /* get_internals */
- Curl_gtls_close, /* close_one */
+ gtls_shutdown, /* shutdown */
+ gtls_data_pending, /* data_pending */
+ gtls_random, /* random */
+ gtls_cert_status_request, /* cert_status_request */
+ gtls_connect, /* connect */
+ gtls_connect_nonblocking, /* connect_nonblocking */
+ gtls_get_internals, /* get_internals */
+ gtls_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_gtls_session_free, /* session_free */
+ gtls_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 */
- Curl_gtls_md5sum, /* md5sum */
- Curl_gtls_sha256sum /* sha256sum */
+ gtls_sha256sum /* sha256sum */
};
#endif /* USE_GNUTLS */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index 780fc109d..1a146a3a9 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/keylog.c b/Utilities/cmcurl/lib/vtls/keylog.c
index 70d22ecf0..a45945f8f 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.c
+++ b/Utilities/cmcurl/lib/vtls/keylog.c
@@ -9,7 +9,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/keylog.h b/Utilities/cmcurl/lib/vtls/keylog.h
index c6b99db93..63626da90 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.h
+++ b/Utilities/cmcurl/lib/vtls/keylog.h
@@ -11,7 +11,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 545f824c6..fc3a948d1 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -31,6 +31,9 @@
#ifdef USE_MBEDTLS
+/* Define this to enable lots of debugging for mbedTLS */
+/* #define MBEDTLS_DEBUG */
+
#include <mbedtls/version.h>
#if MBEDTLS_VERSION_NUMBER >= 0x02040000
#include <mbedtls/net_sockets.h>
@@ -46,6 +49,12 @@
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/sha256.h>
+#if MBEDTLS_VERSION_MAJOR >= 2
+# ifdef MBEDTLS_DEBUG
+# include <mbedtls/debug.h>
+# endif
+#endif
+
#include "urldata.h"
#include "sendf.h"
#include "inet_pton.h"
@@ -113,9 +122,6 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
#endif /* THREADING_SUPPORT */
-/* Define this to enable lots of debugging for mbedTLS */
-#undef MBEDTLS_DEBUG
-
#ifdef MBEDTLS_DEBUG
static void mbed_debug(void *context, int level, const char *f_name,
int line_nb, const char *line)
@@ -190,9 +196,9 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
}
static CURLcode
-set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
@@ -235,16 +241,15 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
}
static CURLcode
-mbed_connect_step1(struct connectdata *conn,
+mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->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);
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
- char * const ssl_cert = SSL_SET_OPTION(cert);
+ 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 :
@@ -274,7 +279,7 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
#else
@@ -287,7 +292,7 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
#endif /* THREADING_SUPPORT */
@@ -421,7 +426,7 @@ mbed_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
@@ -457,17 +462,17 @@ mbed_connect_step1(struct connectdata *conn,
if(SSL_SET_OPTION(primary.sessionid)) {
void *old_session = NULL;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &old_session, NULL, sockindex)) {
ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
if(ret) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
infof(data, "mbedTLS re-using session\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
mbedtls_ssl_conf_ca_chain(&backend->config,
@@ -535,11 +540,10 @@ mbed_connect_step1(struct connectdata *conn,
}
static CURLcode
-mbed_connect_step2(struct connectdata *conn,
+mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
int ret;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const mbedtls_x509_crt *peercert;
@@ -695,7 +699,7 @@ mbed_connect_step2(struct connectdata *conn,
else {
infof(data, "ALPN, server did not agree to a protocol\n");
}
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -707,13 +711,12 @@ mbed_connect_step2(struct connectdata *conn,
}
static CURLcode
-mbed_connect_step3(struct connectdata *conn,
+mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
CURLcode retcode = CURLE_OK;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = conn->data;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
@@ -738,12 +741,13 @@ mbed_connect_step3(struct connectdata *conn,
}
/* If there's already a matching session in the cache, delete it */
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex))
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
- retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ retcode = Curl_ssl_addsessionid(data, conn,
+ our_ssl_sessionid, 0, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(retcode) {
mbedtls_ssl_session_free(our_ssl_sessionid);
free(our_ssl_sessionid);
@@ -757,16 +761,16 @@ mbed_connect_step3(struct connectdata *conn,
return CURLE_OK;
}
-static ssize_t mbed_send(struct connectdata *conn, int sockindex,
+static ssize_t mbed_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
int ret = -1;
- ret = mbedtls_ssl_write(&backend->ssl,
- (unsigned char *)mem, len);
+ ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
if(ret < 0) {
*curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
@@ -777,15 +781,18 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex,
return ret;
}
-static void Curl_mbedtls_close_all(struct Curl_easy *data)
+static void mbedtls_close_all(struct Curl_easy *data)
{
(void)data;
}
-static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
+static void mbedtls_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;
+
+ (void) data;
mbedtls_pk_free(&backend->pk);
mbedtls_x509_crt_free(&backend->clicert);
mbedtls_x509_crt_free(&backend->cacert);
@@ -798,16 +805,16 @@ static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
#endif /* THREADING_SUPPORT */
}
-static ssize_t mbed_recv(struct connectdata *conn, int num,
+static ssize_t mbed_recv(struct Curl_easy *data, int num,
char *buf, size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
int ret = -1;
ssize_t len = -1;
- memset(buf, 0, buffersize);
ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
buffersize);
@@ -825,13 +832,13 @@ static ssize_t mbed_recv(struct connectdata *conn, int num,
return len;
}
-static void Curl_mbedtls_session_free(void *ptr)
+static void mbedtls_session_free(void *ptr)
{
mbedtls_ssl_session_free(ptr);
free(ptr);
}
-static size_t Curl_mbedtls_version(char *buffer, size_t size)
+static size_t mbedtls_version(char *buffer, size_t size)
{
#ifdef MBEDTLS_VERSION_C
/* if mbedtls_version_get_number() is available it is better */
@@ -843,8 +850,8 @@ static size_t Curl_mbedtls_version(char *buffer, size_t size)
#endif
}
-static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode mbedtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(MBEDTLS_CTR_DRBG_C)
int ret = -1;
@@ -862,7 +869,7 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n",
+ failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s",
-ret, errorbuf);
}
else {
@@ -872,7 +879,7 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
}
@@ -893,13 +900,13 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
}
static CURLcode
-mbed_connect_common(struct connectdata *conn,
+mbed_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode retcode;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -920,7 +927,7 @@ mbed_connect_common(struct connectdata *conn,
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
- retcode = mbed_connect_step1(conn, sockindex);
+ retcode = mbed_connect_step1(data, conn, sockindex);
if(retcode)
return retcode;
}
@@ -975,7 +982,7 @@ mbed_connect_common(struct connectdata *conn,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- retcode = mbed_connect_step2(conn, sockindex);
+ retcode = mbed_connect_step2(data, conn, sockindex);
if(retcode || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -985,7 +992,7 @@ mbed_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- retcode = mbed_connect_step3(conn, sockindex);
+ retcode = mbed_connect_step3(data, conn, sockindex);
if(retcode)
return retcode;
}
@@ -1005,19 +1012,21 @@ mbed_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode mbedtls_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return mbed_connect_common(conn, sockindex, TRUE, done);
+ return mbed_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
+static CURLcode mbedtls_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode retcode;
bool done = FALSE;
- retcode = mbed_connect_common(conn, sockindex, FALSE, &done);
+ retcode = mbed_connect_common(data, conn, sockindex, FALSE, &done);
if(retcode)
return retcode;
@@ -1030,28 +1039,28 @@ static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
* return 0 error initializing SSL
* return 1 SSL initialized successfully
*/
-static int Curl_mbedtls_init(void)
+static int mbedtls_init(void)
{
return Curl_mbedtlsthreadlock_thread_setup();
}
-static void Curl_mbedtls_cleanup(void)
+static void mbedtls_cleanup(void)
{
(void)Curl_mbedtlsthreadlock_thread_cleanup();
}
-static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
- int sockindex)
+static bool mbedtls_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 mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
}
-static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len UNUSED_PARAM)
+static CURLcode mbedtls_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
#if MBEDTLS_VERSION_NUMBER < 0x02070000
@@ -1064,8 +1073,8 @@ static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
return CURLE_OK;
}
-static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
@@ -1081,26 +1090,25 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
sizeof(struct ssl_backend_data),
- Curl_mbedtls_init, /* init */
- Curl_mbedtls_cleanup, /* cleanup */
- Curl_mbedtls_version, /* version */
+ mbedtls_init, /* init */
+ mbedtls_cleanup, /* cleanup */
+ mbedtls_version, /* version */
Curl_none_check_cxn, /* check_cxn */
Curl_none_shutdown, /* shutdown */
- Curl_mbedtls_data_pending, /* data_pending */
- Curl_mbedtls_random, /* random */
+ mbedtls_data_pending, /* data_pending */
+ mbedtls_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_mbedtls_connect, /* connect */
- Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
- Curl_mbedtls_get_internals, /* get_internals */
- Curl_mbedtls_close, /* close_one */
- Curl_mbedtls_close_all, /* close_all */
- Curl_mbedtls_session_free, /* session_free */
+ mbedtls_connect, /* connect */
+ mbedtls_connect_nonblocking, /* connect_nonblocking */
+ mbedtls_get_internals, /* get_internals */
+ mbedtls_close, /* close_one */
+ mbedtls_close_all, /* close_all */
+ mbedtls_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 */
- Curl_none_md5sum, /* md5sum */
- Curl_mbedtls_sha256sum /* sha256sum */
+ mbedtls_sha256sum /* sha256sum */
};
#endif /* USE_MBEDTLS */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index 0cc64b399..1abd331ea 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -7,12 +7,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
index 4d672f106..473f5171e 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
@@ -10,7 +10,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
index 96a787d1a..e40dfc8d6 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
@@ -12,7 +12,7 @@
*
* 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.c b/Utilities/cmcurl/lib/vtls/mesalink.c
index 7132bdfd2..b6d1005ec 100644
--- a/Utilities/cmcurl/lib/vtls/mesalink.c
+++ b/Utilities/cmcurl/lib/vtls/mesalink.c
@@ -6,11 +6,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -89,10 +89,10 @@ static int do_file_type(const char *type)
* layer and do all necessary magic.
*/
static CURLcode
-mesalink_connect_step1(struct connectdata *conn, int sockindex)
+mesalink_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
char *ciphers;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct in_addr addr4;
#ifdef ENABLE_IPV6
@@ -158,8 +158,8 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
SSL_CONN_CONFIG(CApath))) {
if(SSL_CONN_CONFIG(verifypeer)) {
failf(data,
- "error setting certificate verify locations:\n"
- " CAfile: %s\n CApath: %s",
+ "error setting certificate verify locations: "
+ " CAfile: %s CApath: %s",
SSL_CONN_CONFIG(CAfile) ?
SSL_CONN_CONFIG(CAfile) : "none",
SSL_CONN_CONFIG(CApath) ?
@@ -173,20 +173,18 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
else {
infof(data, "successfully set certificate verify locations:\n");
}
- infof(data,
- " CAfile: %s\n"
- " CApath: %s\n",
- SSL_CONN_CONFIG(CAfile)?
- SSL_CONN_CONFIG(CAfile): "none",
- SSL_CONN_CONFIG(CApath)?
- SSL_CONN_CONFIG(CApath): "none");
+ infof(data, " CAfile: %s\n",
+ SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none");
+ infof(data, " CApath: %s\n",
+ SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): "none");
}
- if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+ if(SSL_SET_OPTION(primary.clientcert) && SSL_SET_OPTION(key)) {
int file_type = do_file_type(SSL_SET_OPTION(cert_type));
- if(SSL_CTX_use_certificate_chain_file(BACKEND->ctx, SSL_SET_OPTION(cert),
- file_type) != 1) {
+ if(SSL_CTX_use_certificate_chain_file(BACKEND->ctx,
+ SSL_SET_OPTION(primary.clientcert),
+ file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
return CURLE_SSL_CONNECT_ERROR;
@@ -262,11 +260,11 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, 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(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(
data,
"SSL: SSL_set_session failed: %s",
@@ -276,7 +274,7 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
#endif /* MESALINK_HAVE_SESSION */
@@ -290,10 +288,10 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
}
static CURLcode
-mesalink_connect_step2(struct connectdata *conn, int sockindex)
+mesalink_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
int ret = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
conn->recv[sockindex] = mesalink_recv;
@@ -350,27 +348,28 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
our_ssl_sessionid = SSL_get_session(BACKEND->handle);
- Curl_ssl_sessionid_lock(conn);
+ Curl_ssl_sessionid_lock(data);
incache =
- !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex));
+ !(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(conn, old_ssl_sessionid);
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
}
if(!incache) {
result = Curl_ssl_addsessionid(
- conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
+ data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
if(result) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "failed to store ssl session");
return result;
}
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
#endif /* MESALINK_HAVE_SESSION */
@@ -380,9 +379,10 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
}
static ssize_t
-mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
+mesalink_send(struct Curl_easy *data, int sockindex, const void *mem,
size_t len, CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
char error_buffer[MESALINK_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
@@ -397,7 +397,7 @@ mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data,
+ failf(data,
"SSL write: %s, errno %d",
ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
SOCKERRNO);
@@ -409,10 +409,12 @@ mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
}
static void
-Curl_mesalink_close(struct connectdata *conn, int sockindex)
+mesalink_close(struct Curl_easy *data, struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ (void) data;
+
if(BACKEND->handle) {
(void)SSL_shutdown(BACKEND->handle);
SSL_free(BACKEND->handle);
@@ -425,9 +427,10 @@ Curl_mesalink_close(struct connectdata *conn, int sockindex)
}
static ssize_t
-mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
+mesalink_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
char error_buffer[MESALINK_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
@@ -446,7 +449,7 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data,
+ failf(data,
"SSL read: %s, errno %d",
ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
SOCKERRNO);
@@ -458,13 +461,13 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
}
static size_t
-Curl_mesalink_version(char *buffer, size_t size)
+mesalink_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
}
static int
-Curl_mesalink_init(void)
+mesalink_init(void)
{
return (SSL_library_init() == SSL_SUCCESS);
}
@@ -474,11 +477,14 @@ Curl_mesalink_init(void)
* socket open (CCC - Clear Command Channel)
*/
static int
-Curl_mesalink_shutdown(struct connectdata *conn, int sockindex)
+mesalink_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ (void) data;
+
if(BACKEND->handle) {
SSL_free(BACKEND->handle);
BACKEND->handle = NULL;
@@ -487,11 +493,10 @@ Curl_mesalink_shutdown(struct connectdata *conn, int sockindex)
}
static CURLcode
-mesalink_connect_common(struct connectdata *conn, int sockindex,
- bool nonblocking, bool *done)
+mesalink_connect_common(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool nonblocking, bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -513,7 +518,7 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OPERATION_TIMEDOUT;
}
- result = mesalink_connect_step1(conn, sockindex);
+ result = mesalink_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -570,7 +575,7 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = mesalink_connect_step2(conn, sockindex);
+ result = mesalink_connect_step2(data, conn, sockindex);
if(result ||
(nonblocking && (ssl_connect_2 == connssl->connecting_state ||
@@ -602,19 +607,20 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
}
static CURLcode
-Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex,
- bool *done)
+mesalink_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool *done)
{
- return mesalink_connect_common(conn, sockindex, TRUE, done);
+ return mesalink_connect_common(data, conn, sockindex, TRUE, done);
}
static CURLcode
-Curl_mesalink_connect(struct connectdata *conn, int sockindex)
+mesalink_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = mesalink_connect_common(conn, sockindex, FALSE, &done);
+ result = mesalink_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -624,8 +630,8 @@ Curl_mesalink_connect(struct connectdata *conn, int sockindex)
}
static void *
-Curl_mesalink_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+mesalink_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
(void)info;
return BACKEND->handle;
@@ -638,26 +644,25 @@ const struct Curl_ssl Curl_ssl_mesalink = {
sizeof(struct ssl_backend_data),
- Curl_mesalink_init, /* init */
- Curl_none_cleanup, /* cleanup */
- Curl_mesalink_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
- Curl_mesalink_shutdown, /* shutdown */
- Curl_none_data_pending, /* data_pending */
- Curl_none_random, /* random */
+ mesalink_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ mesalink_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ mesalink_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_mesalink_connect, /* connect */
- Curl_mesalink_connect_nonblocking, /* connect_nonblocking */
- Curl_mesalink_get_internals, /* get_internals */
- Curl_mesalink_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 */
- Curl_none_md5sum, /* md5sum */
- NULL /* sha256sum */
+ mesalink_connect, /* connect */
+ mesalink_connect_nonblocking, /* connect_nonblocking */
+ mesalink_get_internals, /* get_internals */
+ mesalink_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 */
};
#endif
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.h b/Utilities/cmcurl/lib/vtls/mesalink.h
index 54cb94ad3..03f520c1d 100644
--- a/Utilities/cmcurl/lib/vtls/mesalink.h
+++ b/Utilities/cmcurl/lib/vtls/mesalink.h
@@ -7,12 +7,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com>
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 0f0d1ee6c..e5ab71cdf 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -83,7 +83,7 @@ struct ssl_backend_data {
PRFileDesc *handle;
char *client_nickname;
struct Curl_easy *data;
- struct curl_llist obj_list;
+ struct Curl_llist obj_list;
PK11GenericObject *obj_clicert;
};
@@ -91,14 +91,14 @@ static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
static PRLock *nss_trustload_lock = NULL;
-static struct curl_llist nss_crl_list;
+static struct Curl_llist nss_crl_list;
static NSSInitContext *nss_context = NULL;
static volatile int initialized = 0;
/* type used to wrap pointers as list nodes */
struct ptr_list_wrap {
void *ptr;
- struct curl_llist_element node;
+ struct Curl_llist_element node;
};
struct cipher_s {
@@ -430,7 +430,7 @@ static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
}
/* wrap 'ptr' as list node and tail-insert into 'list' */
-static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
+static CURLcode insert_wrapped_ptr(struct Curl_llist *list, void *ptr)
{
struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
if(!wrap)
@@ -443,7 +443,7 @@ static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
* the call succeeds, append the object handle to the list of objects so that
- * the object can be destroyed in Curl_nss_close(). */
+ * the object can be destroyed in nss_close(). */
static CURLcode nss_create_object(struct ssl_connect_data *connssl,
CK_OBJECT_CLASS obj_class,
const char *filename, bool cacert)
@@ -508,7 +508,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl,
/* Destroy the NSS object whose handle is given by ptr. This function is
* a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
- * NSS objects in Curl_nss_close() */
+ * NSS objects in nss_close() */
static void nss_destroy_object(void *user, void *ptr)
{
struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
@@ -587,7 +587,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
return CURLE_SSL_CRL_BADFILE;
}
- /* store the CRL item so that we can free it in Curl_nss_cleanup() */
+ /* store the CRL item so that we can free it in nss_cleanup() */
if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
if(SECSuccess == CERT_UncacheCRL(db, crl_der))
SECITEM_FreeItem(crl_der, PR_TRUE);
@@ -665,14 +665,13 @@ fail:
return CURLE_SSL_CRL_BADFILE;
}
-static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
- char *key_file)
+static CURLcode nss_load_key(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, char *key_file)
{
PK11SlotInfo *slot, *tmp;
SECStatus status;
CURLcode result;
struct ssl_connect_data *ssl = conn->ssl;
- struct Curl_easy *data = conn->data;
(void)sockindex; /* unused */
@@ -701,15 +700,15 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
}
-static int display_error(struct connectdata *conn, PRInt32 err,
+static int display_error(struct Curl_easy *data, PRInt32 err,
const char *filename)
{
switch(err) {
case SEC_ERROR_BAD_PASSWORD:
- failf(conn->data, "Unable to load client key: Incorrect password");
+ failf(data, "Unable to load client key: Incorrect password");
return 1;
case SEC_ERROR_UNKNOWN_CERT:
- failf(conn->data, "Unable to load certificate %s", filename);
+ failf(data, "Unable to load certificate %s", filename);
return 1;
default:
break;
@@ -717,17 +716,16 @@ static int display_error(struct connectdata *conn, PRInt32 err,
return 0; /* The caller will print a generic error */
}
-static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
- char *cert_file, char *key_file)
+static CURLcode cert_stuff(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, char *cert_file, char *key_file)
{
- struct Curl_easy *data = conn->data;
CURLcode result;
if(cert_file) {
result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
if(result) {
const PRErrorCode err = PR_GetError();
- if(!display_error(conn, err, cert_file)) {
+ if(!display_error(data, err, cert_file)) {
const char *err_name = nss_error_to_name(err);
failf(data, "unable to load client cert: %d (%s)", err, err_name);
}
@@ -738,13 +736,13 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
if(key_file || (is_file(cert_file))) {
if(key_file)
- result = nss_load_key(conn, sockindex, key_file);
+ result = nss_load_key(data, conn, sockindex, key_file);
else
/* In case the cert file also has the key */
- result = nss_load_key(conn, sockindex, cert_file);
+ result = nss_load_key(data, conn, sockindex, cert_file);
if(result) {
const PRErrorCode err = PR_GetError();
- if(!display_error(conn, err, key_file)) {
+ if(!display_error(data, err, key_file)) {
const char *err_name = nss_error_to_name(err);
failf(data, "unable to load client key: %d (%s)", err, err_name);
}
@@ -771,7 +769,8 @@ static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
PRBool isServer)
{
- struct connectdata *conn = (struct connectdata *)arg;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
#ifdef SSL_ENABLE_OCSP_STAPLING
if(SSL_CONN_CONFIG(verifystatus)) {
@@ -779,12 +778,12 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
if(!csa) {
- failf(conn->data, "Invalid OCSP response");
+ failf(data, "Invalid OCSP response");
return SECFailure;
}
if(csa->len == 0) {
- failf(conn->data, "No OCSP response received");
+ failf(data, "No OCSP response received");
return SECFailure;
}
@@ -794,14 +793,14 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
);
if(cacheResult != SECSuccess) {
- failf(conn->data, "Invalid OCSP response");
+ failf(data, "Invalid OCSP response");
return cacheResult;
}
}
#endif
if(!SSL_CONN_CONFIG(verifypeer)) {
- infof(conn->data, "skipping SSL peer certificate verification\n");
+ infof(data, "skipping SSL peer certificate verification\n");
return SECSuccess;
}
@@ -813,7 +812,8 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
*/
static void HandshakeCallback(PRFileDesc *sock, void *arg)
{
- struct connectdata *conn = (struct connectdata*) arg;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
unsigned int buflenmax = 50;
unsigned char buf[50];
unsigned int buflen;
@@ -833,15 +833,15 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
#endif
case SSL_NEXT_PROTO_NO_SUPPORT:
case SSL_NEXT_PROTO_NO_OVERLAP:
- infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n");
+ infof(data, "ALPN/NPN, server did not agree to a protocol\n");
return;
#ifdef SSL_ENABLE_ALPN
case SSL_NEXT_PROTO_SELECTED:
- infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf);
+ infof(data, "ALPN, server accepted to use %.*s\n", buflen, buf);
break;
#endif
case SSL_NEXT_PROTO_NEGOTIATED:
- infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf);
+ infof(data, "NPN, server accepted to use %.*s\n", buflen, buf);
break;
}
@@ -856,7 +856,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
!memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
conn->negnpn = CURL_HTTP_VERSION_1_1;
}
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
}
@@ -865,8 +865,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
PRBool *canFalseStart)
{
- struct connectdata *conn = client_data;
- struct Curl_easy *data = conn->data;
+ struct Curl_easy *data = (struct Curl_easy *)client_data;
SSLChannelInfo channelInfo;
SSLCipherSuiteInfo cipherInfo;
@@ -949,7 +948,7 @@ static void display_cert_info(struct Curl_easy *data,
PR_Free(common_name);
}
-static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
+static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
{
CURLcode result = CURLE_OK;
SSLChannelInfo channel;
@@ -965,16 +964,16 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
channel.cipherSuite) {
if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
&suite, sizeof(suite)) == SECSuccess) {
- infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
+ infof(data, "SSL connection using %s\n", suite.cipherSuiteName);
}
}
cert = SSL_PeerCertificate(sock);
if(cert) {
- infof(conn->data, "Server certificate:\n");
+ infof(data, "Server certificate:\n");
- if(!conn->data->set.ssl.certinfo) {
- display_cert_info(conn->data, cert);
+ if(!data->set.ssl.certinfo) {
+ display_cert_info(data, cert);
CERT_DestroyCertificate(cert);
}
else {
@@ -995,10 +994,10 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
}
}
- result = Curl_ssl_init_certinfo(conn->data, i);
+ result = Curl_ssl_init_certinfo(data, i);
if(!result) {
for(i = 0; cert; cert = cert2) {
- result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
+ result = Curl_extract_certinfo(data, i++, (char *)cert->derCert.data,
(char *)cert->derCert.data +
cert->derCert.len);
if(result)
@@ -1021,18 +1020,13 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
{
- struct connectdata *conn = (struct connectdata *)arg;
- struct Curl_easy *data = conn->data;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
PRErrorCode err = PR_GetError();
CERTCertificate *cert;
/* remember the cert verification result */
-#ifndef CURL_DISABLE_PROXY
- if(SSL_IS_PROXY())
- data->set.proxy_ssl.certverifyresult = err;
- else
-#endif
- data->set.ssl.certverifyresult = err;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = err;
if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
/* we are asked not to verify the host name */
@@ -1340,7 +1334,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
infof(data, "Initializing NSS with certpath: %s\n", certpath);
nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
- NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
+ NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
free(certpath);
if(nss_context != NULL)
@@ -1365,7 +1359,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
}
/* data might be NULL */
-static CURLcode nss_init(struct Curl_easy *data)
+static CURLcode nss_setup(struct Curl_easy *data)
{
char *cert_dir;
struct_stat st;
@@ -1374,7 +1368,7 @@ static CURLcode nss_init(struct Curl_easy *data)
if(initialized)
return CURLE_OK;
- /* list of all CRL items we need to destroy in Curl_nss_cleanup() */
+ /* list of all CRL items we need to destroy in nss_cleanup() */
Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);
/* First we check if $SSL_DIR points to a valid dir */
@@ -1428,7 +1422,7 @@ static CURLcode nss_init(struct Curl_easy *data)
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
-static int Curl_nss_init(void)
+static int nss_init(void)
{
/* curl_global_init() is not thread-safe so this test is ok */
if(nss_initlock == NULL) {
@@ -1456,14 +1450,14 @@ CURLcode Curl_nss_force_init(struct Curl_easy *data)
}
PR_Lock(nss_initlock);
- result = nss_init(data);
+ result = nss_setup(data);
PR_Unlock(nss_initlock);
return result;
}
/* Global cleanup */
-static void Curl_nss_cleanup(void)
+static void nss_cleanup(void)
{
/* This function isn't required to be threadsafe and this is only done
* as a safety feature.
@@ -1503,7 +1497,7 @@ static void Curl_nss_cleanup(void)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-static int Curl_nss_check_cxn(struct connectdata *conn)
+static int nss_check_cxn(struct connectdata *conn)
{
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
struct ssl_backend_data *backend = connssl->backend;
@@ -1522,7 +1516,7 @@ static int Curl_nss_check_cxn(struct connectdata *conn)
return -1; /* connection status unknown */
}
-static void nss_close(struct ssl_connect_data *connssl)
+static void close_one(struct ssl_connect_data *connssl)
{
/* before the cleanup, check whether we are using a client certificate */
struct ssl_backend_data *backend = connssl->backend;
@@ -1552,7 +1546,8 @@ static void nss_close(struct ssl_connect_data *connssl)
/*
* This function is called when an SSL connection is closed.
*/
-static void Curl_nss_close(struct connectdata *conn, int sockindex)
+static void nss_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
@@ -1560,6 +1555,7 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex)
#endif
struct ssl_backend_data *backend = connssl->backend;
+ (void)data;
if(backend->handle
#ifndef CURL_DISABLE_PROXY
|| connssl_proxy->backend->handle
@@ -1578,9 +1574,9 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex)
a double close leading to crash. */
connssl_proxy->backend->handle = NULL;
- nss_close(connssl_proxy);
+ close_one(connssl_proxy);
#endif
- nss_close(connssl);
+ close_one(connssl);
}
/* return true if NSS can provide error code (and possibly msg) for the
@@ -1616,10 +1612,10 @@ static bool is_cc_error(PRInt32 err)
static Curl_recv nss_recv;
static Curl_send nss_send;
-static CURLcode nss_load_ca_certificates(struct connectdata *conn,
+static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
const char *cafile = SSL_CONN_CONFIG(CAfile);
const char *capath = SSL_CONN_CONFIG(CApath);
bool use_trust_module;
@@ -1631,9 +1627,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
if(capath && !capath[0])
capath = NULL;
- infof(data, " CAfile: %s\n CApath: %s\n",
- cafile ? cafile : "none",
- capath ? capath : "none");
+ infof(data, " CAfile: %s\n", cafile ? cafile : "none");
+ infof(data, " CApath: %s\n", capath ? capath : "none");
/* load libnssckbi.so if no other trust roots were specified */
use_trust_module = !cafile && !capath;
@@ -1673,7 +1668,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
if(!dir)
return CURLE_SSL_CACERT_BADFILE;
- while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
+ while((entry =
+ PR_ReadDir(dir, (PRDirFlags)(PR_SKIP_BOTH | PR_SKIP_HIDDEN)))) {
char *fullpath = aprintf("%s/%s", capath, entry->name);
if(!fullpath) {
PR_CloseDir(dir);
@@ -1824,26 +1820,20 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
return CURLE_OK;
}
-static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
+static CURLcode nss_setup_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
PRFileDesc *model = NULL;
PRFileDesc *nspr_io = NULL;
PRFileDesc *nspr_io_stub = NULL;
PRBool ssl_no_cache;
PRBool ssl_cbc_random_iv;
- struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CURLcode result;
bool second_layer = FALSE;
SSLVersionRange sslver_supported;
-#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
SSLVersionRange sslver = {
SSL_LIBRARY_VERSION_TLS_1_0, /* min */
@@ -1860,11 +1850,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
backend->data = data;
- /* list of all NSS objects we need to destroy in Curl_nss_close() */
+ /* list of all NSS objects we need to destroy in nss_do_close() */
Curl_llist_init(&backend->obj_list, nss_destroy_object);
PR_Lock(nss_initlock);
- result = nss_init(conn->data);
+ result = nss_setup(data);
if(result) {
PR_Unlock(nss_initlock);
goto error;
@@ -1944,25 +1934,20 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
* verify peer */
- if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
+ if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, data) != SECSuccess)
goto error;
/* not checked yet */
-#ifndef CURL_DISABLE_PROXY
- if(SSL_IS_PROXY())
- data->set.proxy_ssl.certverifyresult = 0;
- else
-#endif
- data->set.ssl.certverifyresult = 0;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = 0;
- if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
+ if(SSL_BadCertHook(model, BadCertHandler, data) != SECSuccess)
goto error;
- if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
+ if(SSL_HandshakeCallback(model, HandshakeCallback, data) != SECSuccess)
goto error;
{
- const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
+ const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex);
if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
/* not a fatal error because we are not going to verify the peer */
infof(data, "warning: CA certificates failed to load\n");
@@ -1981,14 +1966,15 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
}
- if(SSL_SET_OPTION(cert)) {
- char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
+ if(SSL_SET_OPTION(primary.clientcert)) {
+ char *nickname = dup_nickname(data, SSL_SET_OPTION(primary.clientcert));
if(nickname) {
/* we are not going to use libnsspem.so to read the client cert */
backend->obj_clicert = NULL;
}
else {
- CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
+ CURLcode rv = cert_stuff(data, conn, sockindex,
+ SSL_SET_OPTION(primary.clientcert),
SSL_SET_OPTION(key));
if(rv) {
/* failf() is already done in cert_stuff() */
@@ -2086,7 +2072,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback,
- conn) != SECSuccess)
+ data) != SECSuccess)
goto error;
}
#endif
@@ -2124,11 +2110,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
/* propagate hostname to the TLS layer */
- if(SSL_SetURL(backend->handle, hostname) != SECSuccess)
+ if(SSL_SetURL(backend->handle, SSL_HOST_NAME()) != SECSuccess)
goto error;
/* prevent NSS from re-using the session for a different hostname */
- if(SSL_SetSockPeerID(backend->handle, hostname) != SECSuccess)
+ if(SSL_SetSockPeerID(backend->handle, SSL_HOST_NAME()) != SECSuccess)
goto error;
return CURLE_OK;
@@ -2140,25 +2126,13 @@ error:
return nss_fail_connect(connssl, data, result);
}
-static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
+static CURLcode nss_do_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_SSL_CONNECT_ERROR;
PRUint32 timeout;
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
- const char * const pinnedpubkey = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
- const char * const pinnedpubkey =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#endif
-
/* check timeout situation */
const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
@@ -2174,14 +2148,14 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
/* blocking direction is updated by nss_update_connecting_state() */
return CURLE_AGAIN;
- else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
+ else if(SSL_SET_OPTION(certverifyresult) == SSL_ERROR_BAD_CERT_DOMAIN)
result = CURLE_PEER_FAILED_VERIFICATION;
- else if(*certverifyresult != 0)
+ else if(SSL_SET_OPTION(certverifyresult) != 0)
result = CURLE_PEER_FAILED_VERIFICATION;
goto error;
}
- result = display_conn_info(conn, backend->handle);
+ result = display_conn_info(data, backend->handle);
if(result)
goto error;
@@ -2204,7 +2178,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
}
}
- result = cmp_peer_pubkey(connssl, pinnedpubkey);
+ result = cmp_peer_pubkey(connssl, SSL_PINNED_PUB_KEY());
if(result)
/* status already printed */
goto error;
@@ -2215,11 +2189,11 @@ error:
return nss_fail_connect(connssl, data, result);
}
-static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
+static CURLcode nss_connect_common(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool *done)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
const bool blocking = (done == NULL);
CURLcode result;
@@ -2230,7 +2204,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
}
if(connssl->connecting_state == ssl_connect_1) {
- result = nss_setup_connect(conn, sockindex);
+ result = nss_setup_connect(data, conn, sockindex);
if(result)
/* we do not expect CURLE_AGAIN from nss_setup_connect() */
return result;
@@ -2243,7 +2217,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
if(result)
return result;
- result = nss_do_connect(conn, sockindex);
+ result = nss_do_connect(data, conn, sockindex);
switch(result) {
case CURLE_OK:
break;
@@ -2276,30 +2250,33 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OK;
}
-static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+static CURLcode nss_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- return nss_connect_common(conn, sockindex, /* blocking */ NULL);
+ return nss_connect_common(data, conn, sockindex, /* blocking */ NULL);
}
-static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode nss_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return nss_connect_common(conn, sockindex, done);
+ return nss_connect_common(data, conn, sockindex, done);
}
-static ssize_t nss_send(struct connectdata *conn, /* connection data */
+static ssize_t nss_send(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
const void *mem, /* send this data */
size_t len, /* amount to write */
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
ssize_t rc;
/* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */
- backend->data = conn->data;
+ backend->data = data;
rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
if(rc < 0) {
@@ -2309,10 +2286,10 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
else {
/* print the error number and error string */
const char *err_name = nss_error_to_name(err);
- infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
+ infof(data, "SSL write: error %d (%s)\n", err, err_name);
/* print a human-readable message describing the error if available */
- nss_print_error_message(conn->data, err);
+ nss_print_error_message(data, err);
*curlcode = (is_cc_error(err))
? CURLE_SSL_CERTPROBLEM
@@ -2325,19 +2302,20 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
return rc; /* number of bytes */
}
-static ssize_t nss_recv(struct connectdata *conn, /* connection data */
+static ssize_t nss_recv(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
- char *buf, /* store read data here */
- size_t buffersize, /* max amount to read */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
ssize_t nread;
/* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */
- backend->data = conn->data;
+ backend->data = data;
nread = PR_Recv(backend->handle, buf, (int)buffersize, 0,
PR_INTERVAL_NO_WAIT);
@@ -2350,10 +2328,10 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
else {
/* print the error number and error string */
const char *err_name = nss_error_to_name(err);
- infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
+ infof(data, "SSL read: errno %d (%s)\n", err, err_name);
/* print a human-readable message describing the error if available */
- nss_print_error_message(conn->data, err);
+ nss_print_error_message(data, err);
*curlcode = (is_cc_error(err))
? CURLE_SSL_CERTPROBLEM
@@ -2366,9 +2344,9 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
return nread;
}
-static size_t Curl_nss_version(char *buffer, size_t size)
+static size_t nss_version(char *buffer, size_t size)
{
- return msnprintf(buffer, size, "NSS/%s", NSS_VERSION);
+ return msnprintf(buffer, size, "NSS/%s", NSS_GetVersion());
}
/* data might be NULL */
@@ -2379,9 +2357,9 @@ static int Curl_nss_seed(struct Curl_easy *data)
}
/* data might be NULL */
-static CURLcode Curl_nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode nss_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
Curl_nss_seed(data); /* Initiate the seed if not already done */
@@ -2392,28 +2370,10 @@ static CURLcode Curl_nss_random(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
- PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
- unsigned int MD5out;
-
- if(!MD5pw)
- return CURLE_NOT_BUILT_IN;
-
- PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
- PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
- PK11_DestroyContext(MD5pw, PR_TRUE);
-
- return CURLE_OK;
-}
-
-static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static CURLcode nss_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
unsigned int SHA256out;
@@ -2428,7 +2388,7 @@ static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
return CURLE_OK;
}
-static bool Curl_nss_cert_status_request(void)
+static bool nss_cert_status_request(void)
{
#ifdef SSL_ENABLE_OCSP_STAPLING
return TRUE;
@@ -2437,7 +2397,7 @@ static bool Curl_nss_cert_status_request(void)
#endif
}
-static bool Curl_nss_false_start(void)
+static bool nss_false_start(void)
{
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
return TRUE;
@@ -2446,7 +2406,7 @@ static bool Curl_nss_false_start(void)
#endif
}
-static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
+static void *nss_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
@@ -2464,28 +2424,27 @@ const struct Curl_ssl Curl_ssl_nss = {
sizeof(struct ssl_backend_data),
- Curl_nss_init, /* init */
- Curl_nss_cleanup, /* cleanup */
- Curl_nss_version, /* version */
- Curl_nss_check_cxn, /* check_cxn */
+ nss_init, /* init */
+ nss_cleanup, /* cleanup */
+ nss_version, /* version */
+ nss_check_cxn, /* check_cxn */
/* NSS has no shutdown function provided and thus always fail */
Curl_none_shutdown, /* shutdown */
Curl_none_data_pending, /* data_pending */
- Curl_nss_random, /* random */
- Curl_nss_cert_status_request, /* cert_status_request */
- Curl_nss_connect, /* connect */
- Curl_nss_connect_nonblocking, /* connect_nonblocking */
- Curl_nss_get_internals, /* get_internals */
- Curl_nss_close, /* close_one */
+ nss_random, /* random */
+ nss_cert_status_request, /* cert_status_request */
+ nss_connect, /* connect */
+ nss_connect_nonblocking, /* connect_nonblocking */
+ nss_get_internals, /* get_internals */
+ nss_close, /* close_one */
Curl_none_close_all, /* close_all */
/* NSS has its own session ID cache */
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_nss_false_start, /* false_start */
- Curl_nss_md5sum, /* md5sum */
- Curl_nss_sha256sum /* sha256sum */
+ nss_false_start, /* false_start */
+ nss_sha256sum /* sha256sum */
};
#endif /* USE_NSS */
diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index 41e51b021..37b364647 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 1685a4aa4..784d9f70e 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -34,6 +34,13 @@
/* Wincrypt must be included before anything that could include OpenSSL. */
#if defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
+/* Undefine wincrypt conflicting symbols for BoringSSL. */
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
#endif
#include "urldata.h"
@@ -193,6 +200,10 @@
!defined(OPENSSL_IS_BORINGSSL))
#define HAVE_SSL_CTX_SET_CIPHERSUITES
#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+/* SET_EC_CURVES available under the same preconditions: see
+ * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
+ */
+#define HAVE_SSL_CTX_SET_EC_CURVES
#endif
#if defined(LIBRESSL_VERSION_NUMBER)
@@ -214,6 +225,14 @@
"ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
#endif
+#ifdef HAVE_OPENSSL_SRP
+/* the function exists */
+#ifdef USE_TLS_SRP
+/* the functionality is not disabled */
+#define USE_OPENSSL_SRP
+#endif
+#endif
+
struct ssl_backend_data {
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
@@ -343,6 +362,18 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
return buf;
}
+/* Return an extra data index for the transfer data.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_ssl_data_index(void)
+{
+ static int ssl_ex_data_data_index = -1;
+ if(ssl_ex_data_data_index < 0) {
+ ssl_ex_data_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ }
+ return ssl_ex_data_data_index;
+}
+
/* Return an extra data index for the connection data.
* This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
*/
@@ -391,7 +422,7 @@ static bool rand_enough(void)
return (0 != RAND_status()) ? TRUE : FALSE;
}
-static CURLcode Curl_ossl_seed(struct Curl_easy *data)
+static CURLcode ossl_seed(struct Curl_easy *data)
{
/* we have the "SSL is seeded" boolean static to prevent multiple
time-consuming seedings in vain */
@@ -553,8 +584,7 @@ static bool is_pkcs11_uri(const char *string)
#endif
-static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
- const char *engine);
+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,
@@ -681,7 +711,7 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
}
static
-int cert_stuff(struct connectdata *conn,
+int cert_stuff(struct Curl_easy *data,
SSL_CTX* ctx,
char *cert_file,
BIO *cert_bio,
@@ -691,7 +721,6 @@ int cert_stuff(struct connectdata *conn,
const char *key_type,
char *key_passwd)
{
- struct Curl_easy *data = conn->data;
char error_buffer[256];
bool check_privkey = TRUE;
@@ -754,7 +783,7 @@ int cert_stuff(struct connectdata *conn,
* cert_file is a PKCS#11 URI */
if(!data->state.engine) {
if(is_pkcs11_uri(cert_file)) {
- if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
return 0;
}
}
@@ -953,7 +982,7 @@ int cert_stuff(struct connectdata *conn,
* key_file is a PKCS#11 URI */
if(!data->state.engine) {
if(is_pkcs11_uri(key_file)) {
- if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
return 0;
}
}
@@ -1065,9 +1094,6 @@ int cert_stuff(struct connectdata *conn,
/* returns non-zero on failure */
static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
{
-#if 0
- return X509_NAME_oneline(a, buf, size);
-#else
BIO *bio_out = BIO_new(BIO_s_mem());
BUF_MEM *biomem;
int rc;
@@ -1089,7 +1115,6 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
BIO_free(bio_out);
return !rc;
-#endif
}
/**
@@ -1098,8 +1123,23 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
-static int Curl_ossl_init(void)
+static int ossl_init(void)
{
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER)
+ const uint64_t flags =
+#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN
+ /* not present in BoringSSL */
+ OPENSSL_INIT_ENGINE_ALL_BUILTIN |
+#endif
+#ifdef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
+ OPENSSL_INIT_NO_LOAD_CONFIG |
+#else
+ OPENSSL_INIT_LOAD_CONFIG |
+#endif
+ 0;
+ OPENSSL_init_ssl(flags, NULL);
+#else
OPENSSL_load_builtin_modules();
#ifdef USE_OPENSSL_ENGINE
@@ -1118,10 +1158,6 @@ static int Curl_ossl_init(void)
CONF_MFLAGS_IGNORE_MISSING_FILE);
#endif
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
- /* OpenSSL 1.1.0+ takes care of initialization itself */
-#else
/* Lets get nice error messages */
SSL_load_error_strings();
@@ -1135,14 +1171,15 @@ static int Curl_ossl_init(void)
Curl_tls_keylog_open();
/* Initialize the extra data indexes */
- if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0)
+ if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_conn_index() < 0 ||
+ ossl_get_ssl_sockindex_index() < 0)
return 0;
return 1;
}
/* Global cleanup */
-static void Curl_ossl_cleanup(void)
+static void ossl_cleanup(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
!defined(LIBRESSL_VERSION_NUMBER)
@@ -1186,7 +1223,7 @@ static void Curl_ossl_cleanup(void)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-static int Curl_ossl_check_cxn(struct connectdata *conn)
+static int ossl_check_cxn(struct connectdata *conn)
{
/* SSL_peek takes data out of the raw recv buffer without peeking so we use
recv MSG_PEEK instead. Bug #795 */
@@ -1232,8 +1269,7 @@ static int Curl_ossl_check_cxn(struct connectdata *conn)
/* Selects an OpenSSL crypto engine
*/
-static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
- const char *engine)
+static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine)
{
#ifdef USE_OPENSSL_ENGINE
ENGINE *e;
@@ -1263,7 +1299,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
char buf[256];
ENGINE_free(e);
- failf(data, "Failed to initialise SSL Engine '%s':\n%s",
+ failf(data, "Failed to initialise SSL Engine '%s': %s",
engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
return CURLE_SSL_ENGINE_INITFAILED;
}
@@ -1278,7 +1314,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
/* Sets engine as default for all SSL operations
*/
-static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
+static CURLcode ossl_set_engine_default(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
@@ -1300,7 +1336,7 @@ static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
/* Return list of OpenSSL crypto engine names.
*/
-static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
+static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
{
struct curl_slist *list = NULL;
#ifdef USE_OPENSSL_ENGINE
@@ -1320,7 +1356,7 @@ static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
return list;
}
-static void ossl_close(struct ssl_connect_data *connssl)
+static void ossl_closeone(struct ssl_connect_data *connssl)
{
struct ssl_backend_data *backend = connssl->backend;
if(backend->handle) {
@@ -1339,11 +1375,13 @@ static void ossl_close(struct ssl_connect_data *connssl)
/*
* This function is called when an SSL connection is closed.
*/
-static void Curl_ossl_close(struct connectdata *conn, int sockindex)
+static void ossl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- ossl_close(&conn->ssl[sockindex]);
+ (void) data;
+ ossl_closeone(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
- ossl_close(&conn->proxy_ssl[sockindex]);
+ ossl_closeone(&conn->proxy_ssl[sockindex]);
#endif
}
@@ -1351,11 +1389,11 @@ static void Curl_ossl_close(struct connectdata *conn, int sockindex)
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
+static int ossl_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
char buf[256]; /* We will use this for the OpenSSL error buffer, so it has
to be at least 256 bytes long. */
unsigned long sslerror;
@@ -1407,7 +1445,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
sslerror = ERR_get_error();
- failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
(sslerror ?
ossl_strerror(sslerror, buf, sizeof(buf)) :
SSL_ERROR_to_str(err)),
@@ -1452,7 +1490,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
return retval;
}
-static void Curl_ossl_session_free(void *ptr)
+static void ossl_session_free(void *ptr)
{
/* free the ID */
SSL_SESSION_free(ptr);
@@ -1462,7 +1500,7 @@ static void Curl_ossl_session_free(void *ptr)
* This function is called when the 'data' struct is going away. Close
* down everything and free all resources!
*/
-static void Curl_ossl_close_all(struct Curl_easy *data)
+static void ossl_close_all(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
@@ -1556,12 +1594,12 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
in the certificate and must exactly match the IP in the URI.
*/
-static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
+static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
size_t addrlen = 0;
- struct Curl_easy *data = conn->data;
STACK_OF(GENERAL_NAME) *altnames;
#ifdef ENABLE_IPV6
struct in6_addr addr;
@@ -1571,16 +1609,8 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
CURLcode result = CURLE_OK;
bool dNSName = FALSE; /* if a dNSName field exists in the cert */
bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
-#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;
-#else
- /* disabled proxy support */
- const char * const hostname = conn->host.name;
- const char * const dispname = conn->host.dispname;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ const char * const dispname = SSL_HOST_DISPNAME();
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip &&
@@ -1764,19 +1794,23 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
-static CURLcode verifystatus(struct connectdata *conn,
+static CURLcode verifystatus(struct Curl_easy *data,
struct ssl_connect_data *connssl)
{
int i, ocsp_status;
unsigned char *status;
const unsigned char *p;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
OCSP_RESPONSE *rsp = NULL;
OCSP_BASICRESP *br = NULL;
X509_STORE *st = NULL;
STACK_OF(X509) *ch = NULL;
struct ssl_backend_data *backend = connssl->backend;
+ X509 *cert;
+ OCSP_CERTID *id = NULL;
+ int cert_status, crl_reason;
+ ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ int ret;
long len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status);
@@ -1845,43 +1879,63 @@ static CURLcode verifystatus(struct connectdata *conn,
goto end;
}
- for(i = 0; i < OCSP_resp_count(br); i++) {
- int cert_status, crl_reason;
- OCSP_SINGLERESP *single = NULL;
-
- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ /* Compute the certificate's ID */
+ cert = SSL_get_peer_certificate(backend->handle);
+ if(!cert) {
+ failf(data, "Error getting peer certificate");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- single = OCSP_resp_get0(br, i);
- if(!single)
- continue;
+ for(i = 0; i < sk_X509_num(ch); i++) {
+ X509 *issuer = sk_X509_value(ch, i);
+ if(X509_check_issued(issuer, cert) == X509_V_OK) {
+ id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
+ break;
+ }
+ }
+ X509_free(cert);
- cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
- &thisupd, &nextupd);
+ if(!id) {
+ failf(data, "Error computing OCSP ID");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
- failf(data, "OCSP response has expired");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
+ /* Find the single OCSP response corresponding to the certificate ID */
+ ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
+ &thisupd, &nextupd);
+ OCSP_CERTID_free(id);
+ if(ret != 1) {
+ failf(data, "Could not find certificate ID in OCSP response");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- infof(data, "SSL certificate status: %s (%d)\n",
- OCSP_cert_status_str(cert_status), cert_status);
+ /* Validate the corresponding single OCSP response */
+ if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
+ failf(data, "OCSP response has expired");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- switch(cert_status) {
- case V_OCSP_CERTSTATUS_GOOD:
- break;
+ infof(data, "SSL certificate status: %s (%d)\n",
+ OCSP_cert_status_str(cert_status), cert_status);
- case V_OCSP_CERTSTATUS_REVOKED:
- result = CURLE_SSL_INVALIDCERTSTATUS;
+ switch(cert_status) {
+ case V_OCSP_CERTSTATUS_GOOD:
+ break;
- failf(data, "SSL certificate revocation reason: %s (%d)",
- OCSP_crl_reason_str(crl_reason), crl_reason);
- goto end;
+ case V_OCSP_CERTSTATUS_REVOKED:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ failf(data, "SSL certificate revocation reason: %s (%d)",
+ OCSP_crl_reason_str(crl_reason), crl_reason);
+ goto end;
- case V_OCSP_CERTSTATUS_UNKNOWN:
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ default:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
}
end:
@@ -2163,15 +2217,15 @@ select_next_proto_cb(SSL *ssl,
const unsigned char *in, unsigned int inlen,
void *arg)
{
- struct connectdata *conn = (struct connectdata*) arg;
-
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
(void)ssl;
#ifdef USE_NGHTTP2
- if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+ 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(conn->data, "NPN, negotiated HTTP2 (%s)\n",
+ infof(data, "NPN, negotiated HTTP2 (%s)\n",
NGHTTP2_PROTO_VERSION_ID);
conn->negnpn = CURL_HTTP_VERSION_2;
return SSL_TLSEXT_ERR_OK;
@@ -2180,12 +2234,12 @@ select_next_proto_cb(SSL *ssl,
if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
ALPN_HTTP_1_1_LENGTH)) {
- infof(conn->data, "NPN, negotiated HTTP1.1\n");
+ infof(data, "NPN, negotiated HTTP1.1\n");
conn->negnpn = CURL_HTTP_VERSION_1_1;
return SSL_TLSEXT_ERR_OK;
}
- infof(conn->data, "NPN, no overlap, use HTTP1.1\n");
+ infof(data, "NPN, no overlap, use HTTP1.1\n");
*out = (unsigned char *)ALPN_HTTP_1_1;
*outlen = ALPN_HTTP_1_1_LENGTH;
conn->negnpn = CURL_HTTP_VERSION_1_1;
@@ -2316,16 +2370,14 @@ typedef long ctx_option_t;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
static CURLcode
set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
- struct connectdata *conn, int sockindex)
+ struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
-#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION)
- /* convoluted #if condition just to avoid compiler warnings on unused
- variable */
- struct Curl_easy *data = conn->data;
-#endif
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ (void) data; /* In case it's unused. */
+
switch(ssl_version) {
case CURL_SSLVERSION_TLSv1_3:
#ifdef TLS1_3_VERSION
@@ -2400,17 +2452,18 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
struct Curl_easy *data;
int sockindex;
curl_socket_t *sockindex_ptr;
+ int data_idx = ossl_get_ssl_data_index();
int connectdata_idx = ossl_get_ssl_conn_index();
int sockindex_idx = ossl_get_ssl_sockindex_index();
- if(connectdata_idx < 0 || sockindex_idx < 0)
+ if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0)
return 0;
conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
if(!conn)
return 0;
- data = conn->data;
+ data = (struct Curl_easy *) SSL_get_ex_data(ssl, data_idx);
/* The sockindex has been stored as a pointer to an array element */
sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
@@ -2420,19 +2473,19 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
bool incache;
void *old_ssl_sessionid = NULL;
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL,
sockindex));
if(incache) {
if(old_ssl_sessionid != ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
}
if(!incache) {
- if(!Curl_ssl_addsessionid(conn, ssl_sessionid,
+ if(!Curl_ssl_addsessionid(data, conn, ssl_sessionid,
0 /* unknown size */, sockindex)) {
/* the session has been put into the session cache */
res = 1;
@@ -2440,17 +2493,17 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
else
failf(data, "failed to store ssl session");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
return res;
}
-static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
char *ciphers;
- struct Curl_easy *data = conn->data;
SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
X509_LOOKUP *lookup = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
@@ -2459,12 +2512,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
-#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();
#ifdef ENABLE_IPV6
struct in6_addr addr;
@@ -2472,18 +2520,12 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
struct in_addr addr;
#endif
#endif
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
const long int ssl_version = SSL_CONN_CONFIG(version);
-#ifdef USE_TLS_SRP
+#ifdef USE_OPENSSL_SRP
const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
#endif
- char * const ssl_cert = SSL_SET_OPTION(cert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(cert_blob);
+ char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_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_capath = SSL_CONN_CONFIG(CApath);
@@ -2496,11 +2538,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
/* Make funny stuff to get random input */
- result = Curl_ossl_seed(data);
+ result = ossl_seed(data);
if(result)
return result;
- *certverifyresult = !X509_V_OK;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = !X509_V_OK;
/* check to see if we've been told to use an explicit SSL/TLS version */
@@ -2524,7 +2566,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
failf(data, OSSL_PACKAGE " was built without SSLv2 support");
return CURLE_NOT_BUILT_IN;
#else
-#ifdef USE_TLS_SRP
+#ifdef USE_OPENSSL_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP)
return CURLE_SSL_CONNECT_ERROR;
#endif
@@ -2537,7 +2579,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
failf(data, OSSL_PACKAGE " was built without SSLv3 support");
return CURLE_NOT_BUILT_IN;
#else
-#ifdef USE_TLS_SRP
+#ifdef USE_OPENSSL_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP)
return CURLE_SSL_CONNECT_ERROR;
#endif
@@ -2682,7 +2724,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
result = set_ssl_version_min_max(backend->ctx, conn);
#else
- result = set_ssl_version_min_max_legacy(&ctx_options, conn, sockindex);
+ result = set_ssl_version_min_max_legacy(&ctx_options, data, conn,
+ sockindex);
#endif
if(result != CURLE_OK)
return result;
@@ -2697,7 +2740,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_NPN
if(conn->bits.tls_enable_npn)
- SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, conn);
+ SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data);
#endif
#ifdef HAS_ALPN
@@ -2735,33 +2778,33 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
BIO *ssl_cert_bio = NULL;
BIO *ssl_key_bio = NULL;
- int result_cert_stuff;
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)
- return CURLE_SSL_CERTPROBLEM;
+ result = CURLE_OUT_OF_MEMORY;
}
- if(SSL_SET_OPTION(key_blob)) {
+ 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)
- return CURLE_SSL_CERTPROBLEM;
+ result = CURLE_OUT_OF_MEMORY;
}
- result_cert_stuff = cert_stuff(conn, backend->ctx,
+ if(!result &&
+ !cert_stuff(data, backend->ctx,
ssl_cert, ssl_cert_bio, ssl_cert_type,
SSL_SET_OPTION(key), ssl_key_bio,
- SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd));
+ 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_cert_stuff) {
+ if(result)
/* failf() is already done in cert_stuff() */
- return CURLE_SSL_CERTPROBLEM;
- }
+ return result;
}
ciphers = SSL_CONN_CONFIG(cipher_list);
@@ -2793,7 +2836,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
SSL_CTX_set_post_handshake_auth(backend->ctx, 1);
#endif
-#ifdef USE_TLS_SRP
+#ifdef HAVE_SSL_CTX_SET_EC_CURVES
+ {
+ char *curves = SSL_CONN_CONFIG(curves);
+ if(curves) {
+ if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
+ failf(data, "failed setting curves list: '%s'", curves);
+ return CURLE_SSL_CIPHER;
+ }
+ }
+ }
+#endif
+
+#ifdef USE_OPENSSL_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP) {
char * const ssl_username = SSL_SET_OPTION(username);
@@ -2910,7 +2965,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
good for all uses. If it returns zero, the certificate has no
valid uses." */
- if(GetLastError() != CRYPT_E_NOT_FOUND)
+ if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
continue;
}
else {
@@ -2970,7 +3025,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
{
if(ssl_cafile) {
if(!SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
- if(verifypeer) {
+ if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate file: %s", ssl_cafile);
return CURLE_SSL_CACERT_BADFILE;
@@ -2978,11 +3033,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Continue with a warning if no certificate verif is required. */
infof(data, "error setting certificate file, continuing anyway\n");
}
- infof(data, " CAfile: %s\n", ssl_cafile);
+ infof(data, " CAfile: %s\n", ssl_cafile);
}
if(ssl_capath) {
if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
- if(verifypeer) {
+ if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate path: %s", ssl_capath);
return CURLE_SSL_CACERT_BADFILE;
@@ -2990,7 +3045,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Continue with a warning if no certificate verif is required. */
infof(data, "error setting certificate path, continuing anyway\n");
}
- infof(data, " CApath: %s\n", ssl_capath);
+ infof(data, " CApath: %s\n", ssl_capath);
}
}
#else
@@ -3000,8 +3055,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:\n"
- " CAfile: %s\n CApath: %s",
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
ssl_cafile ? ssl_cafile : "none",
ssl_capath ? ssl_capath : "none");
return CURLE_SSL_CACERT_BADFILE;
@@ -3015,11 +3070,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Everything is fine. */
infof(data, "successfully set certificate verify locations:\n");
}
- infof(data,
- " CAfile: %s\n"
- " CApath: %s\n",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
+ infof(data, " CAfile: %s\n", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s\n", ssl_capath ? ssl_capath : "none");
}
#endif
@@ -3137,30 +3189,43 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif
- sni &&
- !SSL_set_tlsext_host_name(backend->handle, hostname))
- infof(data, "WARNING: failed to configure server name indication (SNI) "
- "TLS extension\n");
+ sni) {
+ size_t nlen = strlen(hostname);
+ if((long)nlen >= data->set.buffer_size)
+ /* this is seriously messed up */
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* RFC 6066 section 3 says the SNI field is case insensitive, but browsers
+ send the data lowercase and subsequently there are now numerous servers
+ out there that don't work unless the name is lowercased */
+ Curl_strntolower(data->state.buffer, hostname, nlen);
+ data->state.buffer[nlen] = 0;
+ if(!SSL_set_tlsext_host_name(backend->handle, data->state.buffer))
+ infof(data, "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+ }
#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();
- if(connectdata_idx >= 0 && sockindex_idx >= 0) {
+ 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(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, 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(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "SSL: SSL_set_session failed: %s",
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)));
@@ -3169,7 +3234,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
#ifndef CURL_DISABLE_PROXY
@@ -3196,17 +3261,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
int err;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -3265,12 +3324,13 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
reason = ERR_GET_REASON(errdetail);
if((lib == ERR_LIB_SSL) &&
- (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
+ ((reason == SSL_R_CERTIFICATE_VERIFY_FAILED) ||
+ (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) {
result = CURLE_PEER_FAILED_VERIFICATION;
lerr = SSL_get_verify_result(backend->handle);
if(lerr != X509_V_OK) {
- *certverifyresult = lerr;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = lerr;
msnprintf(error_buffer, sizeof(error_buffer),
"SSL certificate problem: %s",
X509_verify_cert_error_string(lerr));
@@ -3292,12 +3352,10 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+ const char * const hostname = SSL_HOST_NAME();
#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
char extramsg[80]="";
@@ -3351,7 +3409,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -3457,14 +3515,12 @@ typedef size_t numcert_t;
typedef int numcert_t;
#endif
-static CURLcode get_cert_chain(struct connectdata *conn,
+static CURLcode get_cert_chain(struct Curl_easy *data,
struct ssl_connect_data *connssl)
-
{
CURLcode result;
STACK_OF(X509) *sk;
int i;
- struct Curl_easy *data = conn->data;
numcert_t numcerts;
BIO *mem;
struct ssl_backend_data *backend = connssl->backend;
@@ -3739,31 +3795,25 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
* We check certificates to authenticate the server; otherwise we risk
* man-in-the-middle attack.
*/
-static CURLcode servercert(struct connectdata *conn,
+static CURLcode servercert(struct Curl_easy *data,
+ struct connectdata *conn,
struct ssl_connect_data *connssl,
bool strict)
{
CURLcode result = CURLE_OK;
int rc;
long lerr;
- struct Curl_easy *data = conn->data;
X509 *issuer;
BIO *fp = NULL;
char error_buffer[256]="";
char buffer[2048];
const char *ptr;
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
BIO *mem = BIO_new(BIO_s_mem());
struct ssl_backend_data *backend = connssl->backend;
if(data->set.ssl.certinfo)
/* we've been asked to gather certificate info! */
- (void)get_cert_chain(conn, connssl);
+ (void)get_cert_chain(data, connssl);
backend->server_cert = SSL_get_peer_certificate(backend->handle);
if(!backend->server_cert) {
@@ -3799,7 +3849,7 @@ static CURLcode servercert(struct connectdata *conn,
BIO_free(mem);
if(SSL_CONN_CONFIG(verifyhost)) {
- result = verifyhost(conn, backend->server_cert);
+ result = verifyhost(data, conn, backend->server_cert);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3878,9 +3928,9 @@ static CURLcode servercert(struct connectdata *conn,
X509_free(issuer);
}
- lerr = *certverifyresult = SSL_get_verify_result(backend->handle);
-
- if(*certverifyresult != X509_V_OK) {
+ lerr = SSL_get_verify_result(backend->handle);
+ SSL_SET_OPTION_LVALUE(certverifyresult) = lerr;
+ if(lerr != X509_V_OK) {
if(SSL_CONN_CONFIG(verifypeer)) {
/* We probably never reach this, because SSL_connect() will fail
and we return earlier if verifypeer is set? */
@@ -3901,7 +3951,7 @@ static CURLcode servercert(struct connectdata *conn,
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
if(SSL_CONN_CONFIG(verifystatus)) {
- result = verifystatus(conn, connssl);
+ result = verifystatus(data, connssl);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3929,7 +3979,8 @@ static CURLcode servercert(struct connectdata *conn,
return result;
}
-static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -3943,8 +3994,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
* operations.
*/
- result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
- SSL_CONN_CONFIG(verifyhost)));
+ result = servercert(data, conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
+ SSL_CONN_CONFIG(verifyhost)));
if(!result)
connssl->connecting_state = ssl_connect_done;
@@ -3955,13 +4006,13 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
static Curl_recv ossl_recv;
static Curl_send ossl_send;
-static CURLcode ossl_connect_common(struct connectdata *conn,
+static CURLcode ossl_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
int what;
@@ -3982,7 +4033,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- result = ossl_connect_step1(conn, sockindex);
+ result = ossl_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -4034,7 +4085,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- result = ossl_connect_step2(conn, sockindex);
+ result = ossl_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -4044,7 +4095,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = ossl_connect_step3(conn, sockindex);
+ result = ossl_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -4064,19 +4115,21 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode ossl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ bool *done)
{
- return ossl_connect_common(conn, sockindex, TRUE, done);
+ return ossl_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = ossl_connect_common(conn, sockindex, FALSE, &done);
+ result = ossl_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -4085,8 +4138,8 @@ static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static bool Curl_ossl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool ossl_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
if(connssl->backend->handle && SSL_pending(connssl->backend->handle))
@@ -4101,9 +4154,9 @@ static bool Curl_ossl_data_pending(const struct connectdata *conn,
return FALSE;
}
-static size_t Curl_ossl_version(char *buffer, size_t size);
+static size_t ossl_version(char *buffer, size_t size);
-static ssize_t ossl_send(struct connectdata *conn,
+static ssize_t ossl_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
@@ -4116,6 +4169,7 @@ static ssize_t ossl_send(struct connectdata *conn,
unsigned long sslerror;
int memlen;
int rc;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -4147,7 +4201,7 @@ static ssize_t ossl_send(struct connectdata *conn,
strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
error_buffer[sizeof(error_buffer) - 1] = '\0';
}
- failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
error_buffer, sockerr);
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -4164,18 +4218,17 @@ static ssize_t ossl_send(struct connectdata *conn,
#endif
) {
char ver[120];
- Curl_ossl_version(ver, 120);
- failf(conn->data, "Error: %s does not support double SSL tunneling.",
- ver);
+ ossl_version(ver, 120);
+ failf(data, "Error: %s does not support double SSL tunneling.", ver);
}
else
- failf(conn->data, "SSL_write() error: %s",
+ failf(data, "SSL_write() error: %s",
ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR;
return -1;
}
/* a true error */
- failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
SSL_ERROR_to_str(err), SOCKERRNO);
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -4184,7 +4237,7 @@ static ssize_t ossl_send(struct connectdata *conn,
return (ssize_t)rc; /* number of bytes */
}
-static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
+static ssize_t ossl_recv(struct Curl_easy *data, /* transfer */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
@@ -4194,6 +4247,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
unsigned long sslerror;
ssize_t nread;
int buffsize;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
@@ -4237,7 +4291,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
error_buffer[sizeof(error_buffer) - 1] = '\0';
}
- failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
return -1;
@@ -4259,7 +4313,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
msnprintf(error_buffer, sizeof(error_buffer),
"Connection closed abruptly");
}
- failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d"
+ failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d"
" (Fatal because this is a curl debug build)",
error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
@@ -4271,7 +4325,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
return nread;
}
-static size_t Curl_ossl_version(char *buffer, size_t size)
+static size_t ossl_version(char *buffer, size_t size)
{
#ifdef LIBRESSL_VERSION_NUMBER
#if LIBRESSL_VERSION_NUMBER < 0x2070100fL
@@ -4342,12 +4396,12 @@ static size_t Curl_ossl_version(char *buffer, size_t size)
}
/* can be called with data == NULL */
-static CURLcode Curl_ossl_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode ossl_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
int rc;
if(data) {
- if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
+ if(ossl_seed(data)) /* Initiate the seed if not already done */
return CURLE_FAILED_INIT; /* couldn't seed for some reason */
}
else {
@@ -4359,35 +4413,20 @@ static CURLcode Curl_ossl_random(struct Curl_easy *data,
return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
}
-static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum /* output */,
- size_t unused)
-{
- EVP_MD_CTX *mdctx;
- unsigned int len = 0;
- (void) unused;
-
- mdctx = EVP_MD_CTX_create();
- EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
- EVP_DigestUpdate(mdctx, tmp, tmplen);
- EVP_DigestFinal_ex(mdctx, md5sum, &len);
- EVP_MD_CTX_destroy(mdctx);
- return CURLE_OK;
-}
-
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
EVP_MD_CTX *mdctx;
unsigned int len = 0;
(void) unused;
mdctx = EVP_MD_CTX_create();
- EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
+ if(!mdctx)
+ return CURLE_OUT_OF_MEMORY;
+ EVP_DigestInit(mdctx, EVP_sha256());
EVP_DigestUpdate(mdctx, tmp, tmplen);
EVP_DigestFinal_ex(mdctx, sha256sum, &len);
EVP_MD_CTX_destroy(mdctx);
@@ -4395,7 +4434,7 @@ static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
}
#endif
-static bool Curl_ossl_cert_status_request(void)
+static bool ossl_cert_status_request(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
@@ -4405,8 +4444,8 @@ static bool Curl_ossl_cert_status_request(void)
#endif
}
-static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info)
+static void *ossl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
{
/* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
struct ssl_backend_data *backend = connssl->backend;
@@ -4428,29 +4467,28 @@ const struct Curl_ssl Curl_ssl_openssl = {
sizeof(struct ssl_backend_data),
- Curl_ossl_init, /* init */
- Curl_ossl_cleanup, /* cleanup */
- Curl_ossl_version, /* version */
- Curl_ossl_check_cxn, /* check_cxn */
- Curl_ossl_shutdown, /* shutdown */
- Curl_ossl_data_pending, /* data_pending */
- Curl_ossl_random, /* random */
- Curl_ossl_cert_status_request, /* cert_status_request */
- Curl_ossl_connect, /* connect */
- Curl_ossl_connect_nonblocking, /* connect_nonblocking */
- Curl_ossl_get_internals, /* get_internals */
- Curl_ossl_close, /* close_one */
- Curl_ossl_close_all, /* close_all */
- Curl_ossl_session_free, /* session_free */
- Curl_ossl_set_engine, /* set_engine */
- Curl_ossl_set_engine_default, /* set_engine_default */
- Curl_ossl_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
- Curl_ossl_md5sum, /* md5sum */
+ ossl_init, /* init */
+ ossl_cleanup, /* cleanup */
+ ossl_version, /* version */
+ ossl_check_cxn, /* check_cxn */
+ ossl_shutdown, /* shutdown */
+ ossl_data_pending, /* data_pending */
+ ossl_random, /* random */
+ ossl_cert_status_request, /* cert_status_request */
+ ossl_connect, /* connect */
+ ossl_connect_nonblocking, /* connect_nonblocking */
+ ossl_get_internals, /* get_internals */
+ ossl_close, /* close_one */
+ ossl_close_all, /* close_all */
+ ossl_session_free, /* session_free */
+ ossl_set_engine, /* set_engine */
+ ossl_set_engine_default, /* set_engine_default */
+ ossl_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
- Curl_ossl_sha256sum /* sha256sum */
+ ossl_sha256sum /* sha256sum */
#else
- NULL /* sha256sum */
+ NULL /* sha256sum */
#endif
};
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index 114dc4bae..2f6e1b2db 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 1c1432d75..0668f98f2 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -5,13 +5,13 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -142,7 +142,8 @@
static Curl_recv schannel_recv;
static Curl_send schannel_send;
-static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
const char *pinnedpubkey);
static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
@@ -162,9 +163,9 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
}
static CURLcode
-set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
+set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
long i = ssl_version;
@@ -346,6 +347,8 @@ set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
}
#ifdef HAS_CLIENT_CERT_PATH
+
+/* Function allocates memory for store_path only if CURLE_OK is returned */
static CURLcode
get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
TCHAR **thumbprint)
@@ -388,25 +391,25 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
if(sep == NULL)
return CURLE_SSL_CERTPROBLEM;
+ *thumbprint = sep + 1;
+ if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
+ return CURLE_SSL_CERTPROBLEM;
+
*sep = TEXT('\0');
*store_path = _tcsdup(store_path_start);
*sep = TEXT('\\');
if(*store_path == NULL)
return CURLE_OUT_OF_MEMORY;
- *thumbprint = sep + 1;
- if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
- return CURLE_SSL_CERTPROBLEM;
-
return CURLE_OK;
}
#endif
static CURLcode
-schannel_connect_step1(struct connectdata *conn, int sockindex)
+schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
ssize_t written = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SecBuffer outbuf;
SecBufferDesc outbuf_desc;
@@ -418,7 +421,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
SCHANNEL_CRED schannel_cred;
PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
- struct curl_schannel_cred *old_cred = NULL;
+ struct Curl_schannel_cred *old_cred = NULL;
struct in_addr addr;
#ifdef ENABLE_IPV6
struct in6_addr addr6;
@@ -491,8 +494,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
/* check for an existing re-usable credential handle */
if(SSL_SET_OPTION(primary.sessionid)) {
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn,
+ (void **)&old_cred, NULL, sockindex)) {
BACKEND->cred = old_cred;
DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));
@@ -502,7 +506,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"schannel: incremented credential handle refcount = %d\n",
BACKEND->cred->refcount));
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
if(!BACKEND->cred) {
@@ -561,7 +565,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- result = set_ssl_version_min_max(&schannel_cred, conn);
+ result = set_ssl_version_min_max(&schannel_cred, data, conn);
if(result != CURLE_OK)
return result;
break;
@@ -588,7 +592,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_CLIENT_CERT_PATH
/* client certificate */
- if(data->set.ssl.cert || data->set.ssl.cert_blob) {
+ if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
DWORD cert_store_name = 0;
TCHAR *cert_store_path = NULL;
TCHAR *cert_thumbprint_str = NULL;
@@ -598,27 +602,28 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
FILE *fInCert = NULL;
void *certdata = NULL;
size_t certsize = 0;
- bool blob = data->set.ssl.cert_blob != NULL;
+ bool blob = data->set.ssl.primary.cert_blob != NULL;
TCHAR *cert_path = NULL;
if(blob) {
- certdata = data->set.ssl.cert_blob->data;
- certsize = data->set.ssl.cert_blob->len;
+ certdata = data->set.ssl.primary.cert_blob->data;
+ certsize = data->set.ssl.primary.cert_blob->len;
}
else {
- cert_path = curlx_convert_UTF8_to_tchar(data->set.ssl.cert);
+ cert_path = curlx_convert_UTF8_to_tchar(
+ data->set.ssl.primary.clientcert);
if(!cert_path)
return CURLE_OUT_OF_MEMORY;
result = get_cert_location(cert_path, &cert_store_name,
&cert_store_path, &cert_thumbprint_str);
- if(result && (data->set.ssl.cert[0]!='\0'))
- fInCert = fopen(data->set.ssl.cert, "rb");
+ if(result && (data->set.ssl.primary.clientcert[0]!='\0'))
+ fInCert = fopen(data->set.ssl.primary.clientcert, "rb");
if(result && !fInCert) {
failf(data, "schannel: Failed to get certificate location"
" or file for %s",
- data->set.ssl.cert);
+ data->set.ssl.primary.clientcert);
curlx_unicodefree(cert_path);
return result;
}
@@ -628,7 +633,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
(!strcasecompare(data->set.ssl.cert_type, "P12"))) {
failf(data, "schannel: certificate format compatibility error "
" for %s",
- blob ? "(memory blob)" : data->set.ssl.cert);
+ blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
curlx_unicodefree(cert_path);
return CURLE_SSL_CERTPROBLEM;
}
@@ -643,7 +648,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
size_t pwd_len = 0;
int str_w_len = 0;
const char *cert_showfilename_error = blob ?
- "(memory blob)" : data->set.ssl.cert;
+ "(memory blob)" : data->set.ssl.primary.clientcert;
curlx_unicodefree(cert_path);
if(fInCert) {
long cert_tell = 0;
@@ -664,7 +669,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
fclose(fInCert);
if(!continue_reading) {
failf(data, "schannel: Failed to read cert file %s",
- data->set.ssl.cert);
+ data->set.ssl.primary.clientcert);
free(certdata);
return CURLE_SSL_CERTPROBLEM;
}
@@ -771,15 +776,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
CertCloseStore(cert_store, 0);
}
#else
- if(data->set.ssl.cert) {
+ if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
failf(data, "schannel: client cert support not built in");
return CURLE_NOT_BUILT_IN;
}
#endif
/* allocate memory for the re-usable credential handle */
- BACKEND->cred = (struct curl_schannel_cred *)
- calloc(1, sizeof(struct curl_schannel_cred));
+ BACKEND->cred = (struct Curl_schannel_cred *)
+ calloc(1, sizeof(struct Curl_schannel_cred));
if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory");
@@ -893,8 +898,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
ISC_REQ_STREAM;
/* allocate memory for the security context handle */
- BACKEND->ctxt = (struct curl_schannel_ctxt *)
- calloc(1, sizeof(struct curl_schannel_ctxt));
+ BACKEND->ctxt = (struct Curl_schannel_ctxt *)
+ calloc(1, sizeof(struct Curl_schannel_ctxt));
if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
@@ -953,7 +958,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"sending %lu bytes...\n", outbuf.cbBuffer));
/* send initial handshake data which is now stored in output buffer */
- result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
outbuf.cbBuffer, &written);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
@@ -977,11 +982,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
static CURLcode
-schannel_connect_step2(struct connectdata *conn, int sockindex)
+schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
int i;
ssize_t nread = -1, written = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned char *reallocated_buffer;
SecBuffer outbuf[3];
@@ -1150,7 +1155,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
"sending %lu bytes...\n", outbuf[i].cbBuffer));
/* send handshake token to server */
- result = Curl_write_plain(conn, conn->sock[sockindex],
+ result = Curl_write_plain(data, conn->sock[sockindex],
outbuf[i].pvBuffer, outbuf[i].cbBuffer,
&written);
if((result != CURLE_OK) ||
@@ -1178,6 +1183,10 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
failf(data, "schannel: SNI or certificate check failed: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
return CURLE_PEER_FAILED_VERIFICATION;
+ case SEC_E_UNTRUSTED_ROOT:
+ failf(data, "schannel: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_PEER_FAILED_VERIFICATION;
/*
case SEC_E_INVALID_HANDLE:
case SEC_E_INVALID_TOKEN:
@@ -1245,7 +1254,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
if(pubkey_ptr) {
- result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
+ result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr);
if(result) {
failf(data, "SSL: public key does not match pinned public key!");
return result;
@@ -1254,7 +1263,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
#ifdef HAS_MANUAL_VERIFY_API
if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
- return Curl_verify_certificate(conn, sockindex);
+ return Curl_verify_certificate(data, conn, sockindex);
}
#endif
@@ -1298,7 +1307,7 @@ cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
struct Adder_args
{
- struct connectdata *conn;
+ struct Curl_easy *data;
CURLcode result;
int idx;
int certs_count;
@@ -1313,17 +1322,18 @@ add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
const char *beg = (const char *) ccert_context->pbCertEncoded;
const char *end = beg + ccert_context->cbCertEncoded;
int insert_index = (args->certs_count - 1) - args->idx;
- args->result = Curl_extract_certinfo(args->conn, insert_index, beg, end);
+ args->result = Curl_extract_certinfo(args->data, insert_index,
+ beg, end);
args->idx++;
}
return args->result == CURLE_OK;
}
static CURLcode
-schannel_connect_step3(struct connectdata *conn, int sockindex)
+schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
@@ -1393,7 +1403,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -1401,26 +1411,26 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
/* save the current session data for possible re-use */
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
- struct curl_schannel_cred *old_cred = NULL;
+ struct Curl_schannel_cred *old_cred = NULL;
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL,
sockindex));
if(incache) {
if(old_cred != BACKEND->cred) {
DEBUGF(infof(data,
"schannel: old credential handle is stale, removing\n"));
/* we're not taking old_cred ownership here, no refcount++ is needed */
- Curl_ssl_delsessionid(conn, (void *)old_cred);
+ Curl_ssl_delsessionid(data, (void *)old_cred);
incache = FALSE;
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
- sizeof(struct curl_schannel_cred),
+ result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred,
+ sizeof(struct Curl_schannel_cred),
sockindex);
if(result) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "schannel: failed to store credential handle");
return result;
}
@@ -1431,7 +1441,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
"schannel: stored credential handle in session cache\n"));
}
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
if(data->set.ssl.certinfo) {
@@ -1451,7 +1461,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
result = Curl_ssl_init_certinfo(data, certs_count);
if(!result) {
struct Adder_args args;
- args.conn = conn;
+ args.data = data;
args.idx = 0;
args.certs_count = certs_count;
traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
@@ -1468,11 +1478,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
static CURLcode
-schannel_connect_common(struct connectdata *conn, int sockindex,
- bool nonblocking, bool *done)
+schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool nonblocking, bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -1494,7 +1503,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OPERATION_TIMEDOUT;
}
- result = schannel_connect_step1(conn, sockindex);
+ result = schannel_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -1549,7 +1558,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = schannel_connect_step2(conn, sockindex);
+ result = schannel_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1559,7 +1568,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = schannel_connect_step3(conn, sockindex);
+ result = schannel_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -1590,12 +1599,13 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
}
static ssize_t
-schannel_send(struct connectdata *conn, int sockindex,
+schannel_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
ssize_t written = -1;
size_t data_len = 0;
- unsigned char *data = NULL;
+ unsigned char *ptr = NULL;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SecBuffer outbuf[4];
SecBufferDesc outbuf_desc;
@@ -1622,19 +1632,19 @@ schannel_send(struct connectdata *conn, int sockindex,
/* calculate the complete message length and allocate a buffer for it */
data_len = BACKEND->stream_sizes.cbHeader + len +
BACKEND->stream_sizes.cbTrailer;
- data = (unsigned char *) malloc(data_len);
- if(data == NULL) {
+ ptr = (unsigned char *) malloc(data_len);
+ if(!ptr) {
*err = CURLE_OUT_OF_MEMORY;
return -1;
}
/* setup output buffers (header, data, trailer, empty) */
InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
- data, BACKEND->stream_sizes.cbHeader);
+ ptr, BACKEND->stream_sizes.cbHeader);
InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
- data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
+ ptr + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
- data + BACKEND->stream_sizes.cbHeader + len,
+ ptr + BACKEND->stream_sizes.cbHeader + len,
BACKEND->stream_sizes.cbTrailer);
InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 4);
@@ -1673,10 +1683,10 @@ schannel_send(struct connectdata *conn, int sockindex,
while(len > (size_t)written) {
ssize_t this_write = 0;
int what;
- timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE);
if(timeout_ms < 0) {
/* we already got the timeout */
- failf(conn->data, "schannel: timed out sending data "
+ failf(data, "schannel: timed out sending data "
"(bytes sent: %zd)", written);
*err = CURLE_OPERATION_TIMEDOUT;
written = -1;
@@ -1687,13 +1697,13 @@ schannel_send(struct connectdata *conn, int sockindex,
what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
if(what < 0) {
/* fatal error */
- failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
*err = CURLE_SEND_ERROR;
written = -1;
break;
}
else if(0 == what) {
- failf(conn->data, "schannel: timed out sending data "
+ failf(data, "schannel: timed out sending data "
"(bytes sent: %zd)", written);
*err = CURLE_OPERATION_TIMEDOUT;
written = -1;
@@ -1701,7 +1711,7 @@ schannel_send(struct connectdata *conn, int sockindex,
}
/* socket is writable */
- result = Curl_write_plain(conn, conn->sock[sockindex], data + written,
+ result = Curl_write_plain(data, conn->sock[sockindex], ptr + written,
len - written, &this_write);
if(result == CURLE_AGAIN)
continue;
@@ -1721,7 +1731,7 @@ schannel_send(struct connectdata *conn, int sockindex,
*err = CURLE_SEND_ERROR;
}
- Curl_safefree(data);
+ Curl_safefree(ptr);
if(len == (size_t)written)
/* Encrypted message including header, data and trailer entirely sent.
@@ -1732,12 +1742,12 @@ schannel_send(struct connectdata *conn, int sockindex,
}
static ssize_t
-schannel_recv(struct connectdata *conn, int sockindex,
+schannel_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t len, CURLcode *err)
{
size_t size = 0;
ssize_t nread = -1;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned char *reallocated_buffer;
size_t reallocated_length;
@@ -1776,14 +1786,12 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: server indicated shutdown in a prior call\n");
goto cleanup;
}
- else if(!len) {
- /* It's debatable what to return when !len. Regardless we can't return
- immediately because there may be data to decrypt (in the case we want to
- decrypt all encrypted cached data) so handle !len later in cleanup.
- */
- ; /* do nothing */
- }
- else if(!BACKEND->recv_connection_closed) {
+
+ /* It's debatable what to return when !len. Regardless we can't return
+ immediately because there may be data to decrypt (in the case we want to
+ decrypt all encrypted cached data) so handle !len later in cleanup.
+ */
+ else if(len && !BACKEND->recv_connection_closed) {
/* increase enc buffer in order to fit the requested amount of data */
size = BACKEND->encdata_length - BACKEND->encdata_offset;
if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
@@ -1950,7 +1958,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: renegotiating SSL/TLS connection\n");
connssl->state = ssl_connection_negotiating;
connssl->connecting_state = ssl_connect_2_writing;
- *err = schannel_connect_common(conn, sockindex, FALSE, &done);
+ *err = schannel_connect_common(data, conn, sockindex, FALSE, &done);
if(*err) {
infof(data, "schannel: renegotiation failed\n");
goto cleanup;
@@ -2057,18 +2065,20 @@ schannel_recv(struct connectdata *conn, int sockindex,
return *err ? -1 : 0;
}
-static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode schannel_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return schannel_connect_common(conn, sockindex, TRUE, done);
+ return schannel_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
+static CURLcode schannel_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = schannel_connect_common(conn, sockindex, FALSE, &done);
+ result = schannel_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -2077,8 +2087,8 @@ static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static bool Curl_schannel_data_pending(const struct connectdata *conn,
- int sockindex)
+static bool schannel_data_pending(const struct connectdata *conn,
+ int sockindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -2089,17 +2099,18 @@ static bool Curl_schannel_data_pending(const struct connectdata *conn,
return FALSE;
}
-static void Curl_schannel_close(struct connectdata *conn, int sockindex)
+static void schannel_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
if(conn->ssl[sockindex].use)
/* if the SSL/TLS channel hasn't been shut down yet, do that now. */
- Curl_ssl_shutdown(conn, sockindex);
+ Curl_ssl_shutdown(data, conn, sockindex);
}
-static void Curl_schannel_session_free(void *ptr)
+static void schannel_session_free(void *ptr)
{
/* this is expected to be called under sessionid lock */
- struct curl_schannel_cred *cred = ptr;
+ struct Curl_schannel_cred *cred = ptr;
cred->refcount--;
if(cred->refcount == 0) {
@@ -2108,12 +2119,12 @@ static void Curl_schannel_session_free(void *ptr)
}
}
-static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
+static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
/* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
* Shutting Down an Schannel Connection
*/
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
@@ -2176,7 +2187,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */
ssize_t written;
- result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
outbuf.cbBuffer, &written);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
@@ -2196,14 +2207,9 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
/* free SSPI Schannel API credential handle */
if(BACKEND->cred) {
- /*
- * When this function is called from Curl_schannel_close() the connection
- * might not have an associated transfer so the check for conn->data is
- * necessary.
- */
- Curl_ssl_sessionid_lock(conn);
- Curl_schannel_session_free(BACKEND->cred);
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_lock(data);
+ schannel_session_free(BACKEND->cred);
+ Curl_ssl_sessionid_unlock(data);
BACKEND->cred = NULL;
}
@@ -2225,25 +2231,25 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static int Curl_schannel_init(void)
+static int schannel_init(void)
{
return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
}
-static void Curl_schannel_cleanup(void)
+static void schannel_cleanup(void)
{
Curl_sspi_global_cleanup();
}
-static size_t Curl_schannel_version(char *buffer, size_t size)
+static size_t schannel_version(char *buffer, size_t size)
{
size = msnprintf(buffer, size, "Schannel");
return size;
}
-static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
+static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
HCRYPTPROV hCryptProv = 0;
@@ -2262,10 +2268,10 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
const char *pinnedpubkey)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CERT_CONTEXT *pCertContextServer = NULL;
@@ -2327,12 +2333,12 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
return result;
}
-static void Curl_schannel_checksum(const unsigned char *input,
- size_t inputlen,
- unsigned char *checksum,
- size_t checksumlen,
- DWORD provType,
- const unsigned int algId)
+static void schannel_checksum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *checksum,
+ size_t checksumlen,
+ DWORD provType,
+ const unsigned int algId)
{
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
@@ -2377,28 +2383,18 @@ static void Curl_schannel_checksum(const unsigned char *input,
CryptReleaseContext(hProv, 0);
}
-static CURLcode Curl_schannel_md5sum(unsigned char *input,
- size_t inputlen,
- unsigned char *md5sum,
- size_t md5len)
-{
- Curl_schannel_checksum(input, inputlen, md5sum, md5len,
- PROV_RSA_FULL, CALG_MD5);
- return CURLE_OK;
-}
-
-static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len)
+static CURLcode schannel_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len)
{
- Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
- PROV_RSA_AES, CALG_SHA_256);
+ schannel_checksum(input, inputlen, sha256sum, sha256len,
+ PROV_RSA_AES, CALG_SHA_256);
return CURLE_OK;
}
-static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *schannel_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
(void)info;
return &BACKEND->ctxt->ctxt_handle;
@@ -2412,26 +2408,25 @@ const struct Curl_ssl Curl_ssl_schannel = {
sizeof(struct ssl_backend_data),
- Curl_schannel_init, /* init */
- Curl_schannel_cleanup, /* cleanup */
- Curl_schannel_version, /* version */
+ schannel_init, /* init */
+ schannel_cleanup, /* cleanup */
+ schannel_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_schannel_shutdown, /* shutdown */
- Curl_schannel_data_pending, /* data_pending */
- Curl_schannel_random, /* random */
+ schannel_shutdown, /* shutdown */
+ schannel_data_pending, /* data_pending */
+ schannel_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_schannel_connect, /* connect */
- Curl_schannel_connect_nonblocking, /* connect_nonblocking */
- Curl_schannel_get_internals, /* get_internals */
- Curl_schannel_close, /* close_one */
+ schannel_connect, /* connect */
+ schannel_connect_nonblocking, /* connect_nonblocking */
+ schannel_get_internals, /* get_internals */
+ schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_schannel_session_free, /* session_free */
+ schannel_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 */
- Curl_schannel_md5sum, /* md5sum */
- Curl_schannel_sha256sum /* sha256sum */
+ schannel_sha256sum /* sha256sum */
};
#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index ee8d7d47a..2952caa1a 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -8,11 +8,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -53,7 +53,8 @@
extern const struct Curl_ssl Curl_ssl_schannel;
-CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex);
+CURLcode Curl_verify_certificate(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex);
/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
@@ -70,20 +71,20 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex);
#endif
#endif
-struct curl_schannel_cred {
+struct Curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
int refcount;
};
-struct curl_schannel_ctxt {
+struct Curl_schannel_ctxt {
CtxtHandle ctxt_handle;
TimeStamp time_stamp;
};
struct ssl_backend_data {
- struct curl_schannel_cred *cred;
- struct curl_schannel_ctxt *ctxt;
+ struct Curl_schannel_cred *cred;
+ struct Curl_schannel_ctxt *ctxt;
SecPkgContext_StreamSizes stream_sizes;
size_t encdata_length, decdata_length;
size_t encdata_offset, decdata_offset;
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index ab7be3950..2ef39cc0f 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -7,11 +7,11 @@
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 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.haxx.se/docs/copyright.html.
+ * 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
@@ -79,10 +79,9 @@ static int is_cr_or_lf(char c)
static CURLcode add_certs_to_store(HCERTSTORE trust_store,
const char *ca_file,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
LARGE_INTEGER file_size;
char *ca_file_buffer = NULL;
@@ -477,7 +476,7 @@ static CURLcode verify_host(struct Curl_easy *data,
* (or some equivalent) encoding
*/
cert_hostname = curlx_convert_tchar_to_UTF8(
- &cert_hostname_buff[cert_hostname_buff_index]);
+ &cert_hostname_buff[cert_hostname_buff_index]);
if(!cert_hostname) {
result = CURLE_OUT_OF_MEMORY;
}
@@ -500,8 +499,8 @@ static CURLcode verify_host(struct Curl_easy *data,
"against certificate name (%s)\n",
conn_hostname, cert_hostname);
- cert_hostname_len = _tcslen(
- &cert_hostname_buff[cert_hostname_buff_index]);
+ cert_hostname_len =
+ _tcslen(&cert_hostname_buff[cert_hostname_buff_index]);
/* Move on to next cert name */
cert_hostname_buff_index += cert_hostname_len + 1;
@@ -522,15 +521,15 @@ static CURLcode verify_host(struct Curl_easy *data,
failf(data, "schannel: server certificate name verification failed");
cleanup:
- curlx_unicodefree(cert_hostname_buff);
+ Curl_safefree(cert_hostname_buff);
return result;
}
-CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
+CURLcode Curl_verify_certificate(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
SECURITY_STATUS sspi_status;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CURLcode result = CURLE_OK;
CERT_CONTEXT *pCertContextServer = NULL;
@@ -584,7 +583,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
}
else {
result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
- conn);
+ data);
}
}
@@ -675,7 +674,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
if(result == CURLE_OK) {
if(SSL_CONN_CONFIG(verifyhost)) {
- result = verify_host(conn->data, pCertContextServer, conn_hostname);
+ result = verify_host(data, pCertContextServer, conn_hostname);
}
}
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index 2627aff16..9a8f7de8d 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -1291,9 +1291,9 @@ static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
#endif
static CURLcode
-set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
long ssl_version = SSL_CONN_CONFIG(version);
@@ -1387,21 +1387,26 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
}
-static CURLcode sectransp_connect_step1(struct connectdata *conn,
+static CURLcode sectransp_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->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 bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- char * const ssl_cert = SSL_SET_OPTION(cert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(cert_blob);
+ 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
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1473,7 +1478,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
@@ -1522,7 +1527,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
@@ -1606,8 +1611,11 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
&kCFTypeArrayCallBacks);
#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
- (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifndef CURL_DISABLE_PROXY
+ && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+#endif
+ ) {
CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
}
@@ -1944,12 +1952,12 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
char *ssl_sessionid;
size_t ssl_sessionid_len;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, (void **)&ssl_sessionid,
&ssl_sessionid_len, sockindex)) {
/* we got a session id, use it! */
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -1962,20 +1970,20 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
else {
CURLcode result;
ssl_sessionid =
- aprintf("%s:%d:%d:%s:%hu", ssl_cafile,
+ aprintf("%s:%d:%d:%s:%ld", ssl_cafile,
verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
ssl_sessionid_len = strlen(ssl_sessionid);
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
if(err != noErr) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
- result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
- sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ result = Curl_ssl_addsessionid(data, conn, ssl_sessionid,
+ ssl_sessionid_len, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(result) {
failf(data, "failed to store ssl session");
return result;
@@ -2181,7 +2189,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
if(res < 0) {
free(certbuf);
CFRelease(array);
- failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle",
+ failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
n, offset);
return CURLE_SSL_CACERT_BADFILE;
}
@@ -2371,16 +2379,20 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
#endif /* SECTRANSP_PINNEDPUBKEY */
static CURLcode
-sectransp_connect_step2(struct connectdata *conn, int sockindex)
+sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
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
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -2406,7 +2418,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
return result;
}
/* the documentation says we need to call SSLHandshake() again */
- return sectransp_connect_step2(conn, sockindex);
+ return sectransp_connect_step2(data, conn, sockindex);
/* Problem with encrypt / decrypt */
case errSSLPeerDecodeError:
@@ -2681,7 +2693,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
/* chosenProtocol is a reference to the string within alpnArr
@@ -2699,10 +2711,10 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* This should be called during step3 of the connection at the earliest */
static void
-show_verbose_server_cert(struct connectdata *conn,
+show_verbose_server_cert(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CFArrayRef server_certs = NULL;
@@ -2805,10 +2817,9 @@ show_verbose_server_cert(struct connectdata *conn,
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
static CURLcode
-sectransp_connect_step3(struct connectdata *conn,
+sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* There is no step 3!
@@ -2816,7 +2827,7 @@ sectransp_connect_step3(struct connectdata *conn,
* server certificates. */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(data->set.verbose)
- show_verbose_server_cert(conn, sockindex);
+ show_verbose_server_cert(data, conn, sockindex);
#endif
connssl->connecting_state = ssl_connect_done;
@@ -2827,13 +2838,13 @@ static Curl_recv sectransp_recv;
static Curl_send sectransp_send;
static CURLcode
-sectransp_connect_common(struct connectdata *conn,
+sectransp_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
int what;
@@ -2854,7 +2865,7 @@ sectransp_connect_common(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- result = sectransp_connect_step1(conn, sockindex);
+ result = sectransp_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -2908,7 +2919,7 @@ sectransp_connect_common(struct connectdata *conn,
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- result = sectransp_connect_step2(conn, sockindex);
+ result = sectransp_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -2919,7 +2930,7 @@ sectransp_connect_common(struct connectdata *conn,
if(ssl_connect_3 == connssl->connecting_state) {
- result = sectransp_connect_step3(conn, sockindex);
+ result = sectransp_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -2939,18 +2950,20 @@ sectransp_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode sectransp_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return sectransp_connect_common(conn, sockindex, TRUE, done);
+ return sectransp_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
+static CURLcode sectransp_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = sectransp_connect_common(conn, sockindex, FALSE, &done);
+ result = sectransp_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -2960,11 +2973,14 @@ static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
+static void sectransp_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;
+ (void) data;
+
if(backend->ssl_ctx) {
(void)SSLClose(backend->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
@@ -2982,11 +2998,11 @@ static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
backend->ssl_sockfd = 0;
}
-static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
+static int sectransp_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = conn->data;
ssize_t nread;
int what;
int rc;
@@ -3000,7 +3016,7 @@ static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
return 0;
#endif
- Curl_sectransp_close(conn, sockindex);
+ sectransp_close(data, conn, sockindex);
rc = 0;
@@ -3038,7 +3054,7 @@ static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
return rc;
}
-static void Curl_sectransp_session_free(void *ptr)
+static void sectransp_session_free(void *ptr)
{
/* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
cached session ID inside the Security framework. There is a private
@@ -3049,7 +3065,7 @@ static void Curl_sectransp_session_free(void *ptr)
Curl_safefree(ptr);
}
-static size_t Curl_sectransp_version(char *buffer, size_t size)
+static size_t sectransp_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "SecureTransport");
}
@@ -3062,7 +3078,7 @@ static size_t Curl_sectransp_version(char *buffer, size_t size)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-static int Curl_sectransp_check_cxn(struct connectdata *conn)
+static int sectransp_check_cxn(struct connectdata *conn)
{
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
struct ssl_backend_data *backend = connssl->backend;
@@ -3078,8 +3094,8 @@ static int Curl_sectransp_check_cxn(struct connectdata *conn)
return 0;
}
-static bool Curl_sectransp_data_pending(const struct connectdata *conn,
- int connindex)
+static bool sectransp_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -3096,8 +3112,8 @@ static bool Curl_sectransp_data_pending(const struct connectdata *conn,
return false;
}
-static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
+static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
/* arc4random_buf() isn't available on cats older than Lion, so let's
do this manually for the benefit of the older cats. */
@@ -3116,27 +3132,17 @@ static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
- (void)md5len;
- (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
- return CURLE_OK;
-}
-
-static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
return CURLE_OK;
}
-static bool Curl_sectransp_false_start(void)
+static bool sectransp_false_start(void)
{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
if(SSLSetSessionOption != NULL)
@@ -3145,13 +3151,13 @@ static bool Curl_sectransp_false_start(void)
return FALSE;
}
-static ssize_t sectransp_send(struct connectdata *conn,
+static ssize_t sectransp_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
- /*struct Curl_easy *data = conn->data;*/
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
size_t processed = 0UL;
@@ -3186,7 +3192,7 @@ static ssize_t sectransp_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1L;
default:
- failf(conn->data, "SSLWrite() returned error %d", err);
+ failf(data, "SSLWrite() returned error %d", err);
*curlcode = CURLE_SEND_ERROR;
return -1L;
}
@@ -3203,7 +3209,7 @@ static ssize_t sectransp_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1L;
default:
- failf(conn->data, "SSLWrite() returned error %d", err);
+ failf(data, "SSLWrite() returned error %d", err);
*curlcode = CURLE_SEND_ERROR;
return -1L;
}
@@ -3212,13 +3218,13 @@ static ssize_t sectransp_send(struct connectdata *conn,
return (ssize_t)processed;
}
-static ssize_t sectransp_recv(struct connectdata *conn,
+static ssize_t sectransp_recv(struct Curl_easy *data,
int num,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
- /*struct Curl_easy *data = conn->data;*/
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
size_t processed = 0UL;
@@ -3250,14 +3256,14 @@ static ssize_t sectransp_recv(struct connectdata *conn,
Leopard's headers */
case -9841:
if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data,
+ CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
backend->ssl_ctx);
if(result)
return result;
}
goto again;
default:
- failf(conn->data, "SSLRead() return error %d", err);
+ failf(data, "SSLRead() return error %d", err);
*curlcode = CURLE_RECV_ERROR;
return -1L;
break;
@@ -3266,8 +3272,8 @@ static ssize_t sectransp_recv(struct connectdata *conn,
return (ssize_t)processed;
}
-static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *sectransp_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
@@ -3287,24 +3293,23 @@ const struct Curl_ssl Curl_ssl_sectransp = {
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
- Curl_sectransp_version, /* version */
- Curl_sectransp_check_cxn, /* check_cxn */
- Curl_sectransp_shutdown, /* shutdown */
- Curl_sectransp_data_pending, /* data_pending */
- Curl_sectransp_random, /* random */
+ sectransp_version, /* version */
+ sectransp_check_cxn, /* check_cxn */
+ sectransp_shutdown, /* shutdown */
+ sectransp_data_pending, /* data_pending */
+ sectransp_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_sectransp_connect, /* connect */
- Curl_sectransp_connect_nonblocking, /* connect_nonblocking */
- Curl_sectransp_get_internals, /* get_internals */
- Curl_sectransp_close, /* close_one */
+ sectransp_connect, /* connect */
+ sectransp_connect_nonblocking, /* connect_nonblocking */
+ sectransp_get_internals, /* get_internals */
+ sectransp_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_sectransp_session_free, /* session_free */
+ sectransp_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_sectransp_false_start, /* false_start */
- Curl_sectransp_md5sum, /* md5sum */
- Curl_sectransp_sha256sum /* sha256sum */
+ sectransp_false_start, /* false_start */
+ sectransp_sha256sum /* sha256sum */
};
#ifdef __clang__
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.h b/Utilities/cmcurl/lib/vtls/sectransp.h
index 5cec797b3..0febd6613 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.h
+++ b/Utilities/cmcurl/lib/vtls/sectransp.h
@@ -8,11 +8,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 281043aa6..b8ab7494f 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -75,17 +75,21 @@
(1<<CURL_LOCK_DATA_SSL_SESSION)))
#define CLONE_STRING(var) \
- if(source->var) { \
- dest->var = strdup(source->var); \
- if(!dest->var) \
- return FALSE; \
- } \
- else \
- dest->var = NULL;
-
-#define CLONE_BLOB(var) \
- if(blobdup(&dest->var, source->var)) \
- return FALSE;
+ do { \
+ if(source->var) { \
+ dest->var = strdup(source->var); \
+ if(!dest->var) \
+ return FALSE; \
+ } \
+ else \
+ dest->var = NULL; \
+ } while(0)
+
+#define CLONE_BLOB(var) \
+ do { \
+ if(blobdup(&dest->var, source->var)) \
+ return FALSE; \
+ } while(0)
static CURLcode blobdup(struct curl_blob **dest,
struct curl_blob *src)
@@ -138,6 +142,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
+ Curl_safe_strcasecompare(data->curves, needle->curves) &&
Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
return TRUE;
@@ -164,6 +169,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(cipher_list);
CLONE_STRING(cipher_list13);
CLONE_STRING(pinned_key);
+ CLONE_STRING(curves);
return TRUE;
}
@@ -179,16 +185,17 @@ 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->curves);
}
#ifdef USE_SSL
-static int multissl_init(const struct Curl_ssl *backend);
+static int multissl_setup(const struct Curl_ssl *backend);
#endif
int Curl_ssl_backend(void)
{
#ifdef USE_SSL
- multissl_init(NULL);
+ multissl_setup(NULL);
return Curl_ssl->info.id;
#else
return (int)CURLSSLBACKEND_NONE;
@@ -284,7 +291,8 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
#endif
CURLcode
-Curl_ssl_connect(struct connectdata *conn, int sockindex)
+Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
@@ -296,26 +304,27 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
}
#endif
- if(!ssl_prefs_check(conn->data))
+ if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl-enabled from here on. */
conn->ssl[sockindex].use = TRUE;
conn->ssl[sockindex].state = ssl_connection_negotiating;
- result = Curl_ssl->connect_blocking(conn, sockindex);
+ result = Curl_ssl->connect_blocking(data, conn, sockindex);
if(!result)
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
return result;
}
CURLcode
-Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
- bool *done)
+Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool *done)
{
CURLcode result;
+
#ifndef CURL_DISABLE_PROXY
if(conn->bits.proxy_ssl_connected[sockindex]) {
result = ssl_connect_init_proxy(conn, sockindex);
@@ -323,47 +332,46 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
return result;
}
#endif
- if(!ssl_prefs_check(conn->data))
+ if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
- result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
+ result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
if(!result && *done)
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
return result;
}
/*
* Lock shared SSL session data
*/
-void Curl_ssl_sessionid_lock(struct connectdata *conn)
+void Curl_ssl_sessionid_lock(struct Curl_easy *data)
{
- if(SSLSESSION_SHARED(conn->data))
- Curl_share_lock(conn->data,
- CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+ if(SSLSESSION_SHARED(data))
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
}
/*
* Unlock shared SSL session data
*/
-void Curl_ssl_sessionid_unlock(struct connectdata *conn)
+void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
{
- if(SSLSESSION_SHARED(conn->data))
- Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION);
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
}
/*
* Check if there's a session ID for the given connection in the cache, and if
* there's one suitable, it is provided. Returns TRUE when no entry matched.
*/
-bool Curl_ssl_getsessionid(struct connectdata *conn,
+bool Curl_ssl_getsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex)
{
- struct curl_ssl_session *check;
- struct Curl_easy *data = conn->data;
+ struct Curl_ssl_session *check;
size_t i;
long *general_age;
bool no_match = TRUE;
@@ -429,7 +437,7 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
/*
* Kill a single session ID entry in the cache.
*/
-void Curl_ssl_kill_session(struct curl_ssl_session *session)
+void Curl_ssl_kill_session(struct Curl_ssl_session *session)
{
if(session->sessionid) {
/* defensive check */
@@ -450,13 +458,12 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
/*
* Delete the given session ID from the cache.
*/
-void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
+void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
{
size_t i;
- struct Curl_easy *data = conn->data;
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
- struct curl_ssl_session *check = &data->state.session[i];
+ struct Curl_ssl_session *check = &data->state.session[i];
if(check->sessionid == ssl_sessionid) {
Curl_ssl_kill_session(check);
@@ -471,14 +478,14 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
* layer. Curl_XXXX_session_free() will be called to free/kill the session ID
* later on.
*/
-CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void *ssl_sessionid,
size_t idsize,
int sockindex)
{
size_t i;
- struct Curl_easy *data = conn->data; /* the mother of all structs */
- struct curl_ssl_session *store = &data->state.session[0];
+ struct Curl_ssl_session *store = &data->state.session[0];
long oldest_age = data->state.session[0].age; /* zero if unused */
char *clone_host;
char *clone_conn_to_host;
@@ -617,16 +624,18 @@ int Curl_ssl_getsock(struct connectdata *conn,
/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
#endif
-void Curl_ssl_close(struct connectdata *conn, int sockindex)
+void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- Curl_ssl->close_one(conn, sockindex);
+ Curl_ssl->close_one(data, conn, sockindex);
conn->ssl[sockindex].state = ssl_connection_none;
}
-CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
+CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- if(Curl_ssl->shut_down(conn, sockindex))
+ if(Curl_ssl->shut_down(data, conn, sockindex))
return CURLE_SSL_SHUTDOWN_FAILED;
conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
@@ -664,13 +673,13 @@ struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
*/
CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
{
- struct curl_ssl_session *session;
+ struct Curl_ssl_session *session;
if(data->state.session)
/* this is just a precaution to prevent multiple inits */
return CURLE_OK;
- session = calloc(amount, sizeof(struct curl_ssl_session));
+ session = calloc(amount, sizeof(struct Curl_ssl_session));
if(!session)
return CURLE_OUT_OF_MEMORY;
@@ -681,12 +690,12 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
return CURLE_OK;
}
-static size_t Curl_multissl_version(char *buffer, size_t size);
+static size_t multissl_version(char *buffer, size_t size);
size_t Curl_ssl_version(char *buffer, size_t size)
{
#ifdef CURL_WITH_MULTI_SSL
- return Curl_multissl_version(buffer, size);
+ return multissl_version(buffer, size);
#else
return Curl_ssl->version(buffer, size);
#endif
@@ -1027,16 +1036,6 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
return result;
}
-#ifndef CURL_DISABLE_CRYPTO_AUTH
-CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
- return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
-}
-#endif
-
/*
* Check whether the SSL backend supports the status_request extension.
*/
@@ -1073,9 +1072,11 @@ int Curl_none_init(void)
void Curl_none_cleanup(void)
{ }
-int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
+int Curl_none_shutdown(struct Curl_easy *data UNUSED_PARAM,
+ struct connectdata *conn UNUSED_PARAM,
int sockindex UNUSED_PARAM)
{
+ (void)data;
(void)conn;
(void)sockindex;
return 0;
@@ -1145,70 +1146,44 @@ bool Curl_none_false_start(void)
return FALSE;
}
-#ifndef CURL_DISABLE_CRYPTO_AUTH
-CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
- unsigned char *md5sum, size_t md5len UNUSED_PARAM)
+static int multissl_init(void)
{
- struct MD5_context *MD5pw;
-
- (void)md5len;
-
- MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
- if(!MD5pw)
- return CURLE_OUT_OF_MEMORY;
- Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
- Curl_MD5_final(MD5pw, md5sum);
- return CURLE_OK;
-}
-#else
-CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM,
- size_t inputlen UNUSED_PARAM,
- unsigned char *md5sum UNUSED_PARAM,
- size_t md5len UNUSED_PARAM)
-{
- (void)input;
- (void)inputlen;
- (void)md5sum;
- (void)md5len;
- return CURLE_NOT_BUILT_IN;
-}
-#endif
-
-static int Curl_multissl_init(void)
-{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return 1;
return Curl_ssl->init();
}
-static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
+static CURLcode multissl_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_blocking(conn, sockindex);
+ return Curl_ssl->connect_blocking(data, conn, sockindex);
}
-static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode multissl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_nonblocking(conn, sockindex, done);
+ return Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
}
-static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info)
+static void *multissl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return NULL;
return Curl_ssl->get_internals(connssl, info);
}
-static void Curl_multissl_close(struct connectdata *conn, int sockindex)
+static void multissl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return;
- Curl_ssl->close_one(conn, sockindex);
+ Curl_ssl->close_one(data, conn, sockindex);
}
static const struct Curl_ssl Curl_ssl_multi = {
@@ -1216,25 +1191,24 @@ static const struct Curl_ssl Curl_ssl_multi = {
0, /* supports nothing */
(size_t)-1, /* something insanely large to be on the safe side */
- Curl_multissl_init, /* init */
+ multissl_init, /* init */
Curl_none_cleanup, /* cleanup */
- Curl_multissl_version, /* version */
+ multissl_version, /* version */
Curl_none_check_cxn, /* check_cxn */
Curl_none_shutdown, /* shutdown */
Curl_none_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_multissl_connect, /* connect */
- Curl_multissl_connect_nonblocking, /* connect_nonblocking */
- Curl_multissl_get_internals, /* get_internals */
- Curl_multissl_close, /* close_one */
+ multissl_connect, /* connect */
+ multissl_connect_nonblocking, /* connect_nonblocking */
+ multissl_get_internals, /* get_internals */
+ multissl_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 */
- Curl_none_md5sum, /* md5sum */
NULL /* sha256sum */
};
@@ -1299,7 +1273,7 @@ static const struct Curl_ssl *available_backends[] = {
NULL
};
-static size_t Curl_multissl_version(char *buffer, size_t size)
+static size_t multissl_version(char *buffer, size_t size)
{
static const struct Curl_ssl *selected;
static char backends[200];
@@ -1343,7 +1317,7 @@ static size_t Curl_multissl_version(char *buffer, size_t size)
return backends_len;
}
-static int multissl_init(const struct Curl_ssl *backend)
+static int multissl_setup(const struct Curl_ssl *backend)
{
const char *env;
char *env_tmp;
@@ -1402,7 +1376,7 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
for(i = 0; available_backends[i]; i++) {
if(available_backends[i]->info.id == id ||
(name && strcasecompare(available_backends[i]->info.name, name))) {
- multissl_init(available_backends[i]);
+ multissl_setup(available_backends[i]);
return CURLSSLSET_OK;
}
}
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index bcc844416..9666682ec 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -47,7 +47,8 @@ struct Curl_ssl {
size_t (*version)(char *buffer, size_t size);
int (*check_cxn)(struct connectdata *cxn);
- int (*shut_down)(struct connectdata *conn, int sockindex);
+ int (*shut_down)(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
bool (*data_pending)(const struct connectdata *conn,
int connindex);
@@ -56,11 +57,14 @@ struct Curl_ssl {
size_t length);
bool (*cert_status_request)(void);
- CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex);
- CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex,
+ CURLcode (*connect_blocking)(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex);
+ CURLcode (*connect_nonblocking)(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool *done);
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
- void (*close_one)(struct connectdata *conn, int sockindex);
+ void (*close_one)(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
void (*close_all)(struct Curl_easy *data);
void (*session_free)(void *ptr);
@@ -69,9 +73,6 @@ struct Curl_ssl {
struct curl_slist *(*engines_list)(struct Curl_easy *data);
bool (*false_start)(void);
-
- CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
- unsigned char *md5sum, size_t md5sumlen);
CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
unsigned char *sha256sum, size_t sha256sumlen);
};
@@ -82,7 +83,8 @@ extern const struct Curl_ssl *Curl_ssl;
int Curl_none_init(void);
void Curl_none_cleanup(void);
-int Curl_none_shutdown(struct connectdata *conn, int sockindex);
+int Curl_none_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
int Curl_none_check_cxn(struct connectdata *conn);
CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
size_t length);
@@ -95,8 +97,6 @@ CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
bool Curl_ssl_tls13_ciphersuites(void);
-CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
- unsigned char *md5sum, size_t md5len);
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
@@ -131,12 +131,26 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
#define SSL_SET_OPTION(var) \
(SSL_IS_PROXY() ? data->set.proxy_ssl.var : data->set.ssl.var)
+#define SSL_SET_OPTION_LVALUE(var) \
+ (*(SSL_IS_PROXY() ? &data->set.proxy_ssl.var : &data->set.ssl.var))
#define SSL_CONN_CONFIG(var) \
(SSL_IS_PROXY() ? conn->proxy_ssl_config.var : conn->ssl_config.var)
+#define SSL_HOST_NAME() \
+ (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_PINNED_PUB_KEY() (SSL_IS_PROXY() \
+ ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] \
+ : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG])
#else
#define SSL_IS_PROXY() FALSE
#define SSL_SET_OPTION(var) data->set.ssl.var
+#define SSL_SET_OPTION_LVALUE(var) data->set.ssl.var
#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_PINNED_PUB_KEY() \
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]
#endif
bool Curl_ssl_config_matches(struct ssl_primary_config *data,
@@ -151,15 +165,19 @@ int Curl_ssl_backend(void);
#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
-CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn,
+CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
+CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *done);
/* tell the SSL stuff to close down all open information regarding
connections (and thus session ID caching etc) */
void Curl_ssl_close_all(struct Curl_easy *data);
-void Curl_ssl_close(struct connectdata *conn, int sockindex);
-CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex);
+void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
+CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data);
@@ -191,10 +209,10 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum,
* The purpose of explicitly locking SSL session cache data is to allow
* individual SSL engines to manage session lifetime in their specific way.
*/
-void Curl_ssl_sessionid_lock(struct connectdata *conn);
+void Curl_ssl_sessionid_lock(struct Curl_easy *data);
/* Unlock session cache mutex */
-void Curl_ssl_sessionid_unlock(struct connectdata *conn);
+void Curl_ssl_sessionid_unlock(struct Curl_easy *data);
/* extract a session ID
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
@@ -202,7 +220,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn);
* is properly taken (e.g. its refcount is incremented
* under sessionid mutex).
*/
-bool Curl_ssl_getsessionid(struct connectdata *conn,
+bool Curl_ssl_getsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex);
@@ -211,7 +230,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
* Caller must ensure that it has properly shared ownership of this sessionid
* object with cache (e.g. incrementing refcount on success)
*/
-CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void *ssl_sessionid,
size_t idsize,
int sockindex);
@@ -221,22 +241,18 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
* take sessionid object ownership from sessionid cache
* (e.g. decrement refcount).
*/
-void Curl_ssl_kill_session(struct curl_ssl_session *session);
+void Curl_ssl_kill_session(struct Curl_ssl_session *session);
/* delete a session from the cache
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
* This will call engine-specific curlssl_session_free function, which must
* take sessionid object ownership from sessionid cache
* (e.g. decrement refcount).
*/
-void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
+void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid);
/* get N random bytes into the buffer */
CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
size_t length);
-CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len);
/* Check pinned public key. */
CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
const char *pinnedpubkey,
@@ -253,10 +269,10 @@ bool Curl_ssl_false_start(void);
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1
#define Curl_ssl_cleanup() Curl_nop_stmt
-#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_connect(x,y,z) CURLE_NOT_BUILT_IN
#define Curl_ssl_close_all(x) Curl_nop_stmt
-#define Curl_ssl_close(x,y) Curl_nop_stmt
-#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_close(x,y,z) Curl_nop_stmt
+#define Curl_ssl_shutdown(x,y,z) CURLE_NOT_BUILT_IN
#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN
#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
#define Curl_ssl_engines_list(x) NULL
@@ -266,7 +282,7 @@ bool Curl_ssl_false_start(void);
#define Curl_ssl_data_pending(x,y) 0
#define Curl_ssl_check_cxn(x) 0
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
-#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN
+#define Curl_ssl_connect_nonblocking(x,y,z,w) CURLE_NOT_BUILT_IN
#define Curl_ssl_kill_session(x) Curl_nop_stmt
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
#define Curl_ssl_cert_status_request() FALSE
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index 7b2a124e4..e1fa45926 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -217,11 +217,10 @@ static int do_file_type(const char *type)
* layer and do all necessary magic.
*/
static CURLcode
-wolfssl_connect_step1(struct connectdata *conn,
+wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
char *ciphers;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
SSL_METHOD* req_method = NULL;
@@ -256,7 +255,7 @@ wolfssl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_0:
-#ifdef WOLFSSL_ALLOW_TLSV10
+#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
req_method = TLSv1_client_method();
use_sni(TRUE);
#else
@@ -265,8 +264,13 @@ wolfssl_connect_step1(struct connectdata *conn,
#endif
break;
case CURL_SSLVERSION_TLSv1_1:
+#ifndef NO_OLD_TLS
req_method = TLSv1_1_client_method();
use_sni(TRUE);
+#else
+ failf(data, "wolfSSL does not support TLS 1.1");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_TLSv1_2:
req_method = TLSv1_2_client_method();
@@ -353,8 +357,8 @@ wolfssl_connect_step1(struct connectdata *conn,
SSL_CONN_CONFIG(CApath))) {
if(SSL_CONN_CONFIG(verifypeer)) {
/* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:\n"
- " CAfile: %s\n CApath: %s",
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
SSL_CONN_CONFIG(CAfile)?
SSL_CONN_CONFIG(CAfile): "none",
SSL_CONN_CONFIG(CApath)?
@@ -372,21 +376,19 @@ wolfssl_connect_step1(struct connectdata *conn,
/* Everything is fine. */
infof(data, "successfully set certificate verify locations:\n");
}
- infof(data,
- " CAfile: %s\n"
- " CApath: %s\n",
- SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
- "none",
- SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath):
- "none");
+ infof(data, " CAfile: %s\n",
+ SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile) : "none");
+ infof(data, " CApath: %s\n",
+ SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath) : "none");
}
/* Load the client certificate, and private key */
- if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+ if(SSL_SET_OPTION(primary.clientcert) && SSL_SET_OPTION(key)) {
int file_type = do_file_type(SSL_SET_OPTION(cert_type));
- if(SSL_CTX_use_certificate_file(backend->ctx, SSL_SET_OPTION(cert),
- file_type) != 1) {
+ if(SSL_CTX_use_certificate_file(backend->ctx,
+ SSL_SET_OPTION(primary.clientcert),
+ file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
return CURLE_SSL_CONNECT_ERROR;
@@ -502,16 +504,23 @@ wolfssl_connect_step1(struct connectdata *conn,
}
#endif /* OPENSSL_EXTRA */
+#ifdef HAVE_SECURE_RENEGOTIATION
+ if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
+ failf(data, "SSL: failed setting secure renegotiation");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
/* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, 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)) {
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "SSL: SSL_set_session failed: %s",
ERR_error_string(SSL_get_error(backend->handle, 0),
error_buffer));
@@ -520,7 +529,7 @@ wolfssl_connect_step1(struct connectdata *conn,
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
/* pass the raw socket into the SSL layer */
@@ -535,11 +544,10 @@ wolfssl_connect_step1(struct connectdata *conn,
static CURLcode
-wolfssl_connect_step2(struct connectdata *conn,
+wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
int ret = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
#ifndef CURL_DISABLE_PROXY
@@ -610,7 +618,7 @@ wolfssl_connect_step2(struct connectdata *conn,
* as also mismatching CN fields */
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
- failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
+ failf(data, "\tsubject alt name(s) or common name do not match \"%s\"",
dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
@@ -637,7 +645,7 @@ wolfssl_connect_step2(struct connectdata *conn,
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
else if(ASN_NO_SIGNER_E == detail) {
if(SSL_CONN_CONFIG(verifypeer)) {
- failf(data, "\tCA signer not available for verification\n");
+ failf(data, "\tCA signer not available for verification");
return CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -725,7 +733,7 @@ wolfssl_connect_step2(struct connectdata *conn,
else
infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
protocol);
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else if(rc == SSL_ALPN_NOT_FOUND)
@@ -751,11 +759,10 @@ wolfssl_connect_step2(struct connectdata *conn,
static CURLcode
-wolfssl_connect_step3(struct connectdata *conn,
+wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -768,27 +775,27 @@ wolfssl_connect_step3(struct connectdata *conn,
our_ssl_sessionid = SSL_get_session(backend->handle);
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+ 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(conn, old_ssl_sessionid);
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ result = Curl_ssl_addsessionid(data, conn, our_ssl_sessionid,
0 /* unknown size */, sockindex);
if(result) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "failed to store ssl session");
return result;
}
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
connssl->connecting_state = ssl_connect_done;
@@ -797,12 +804,13 @@ wolfssl_connect_step3(struct connectdata *conn,
}
-static ssize_t wolfssl_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
+static ssize_t wolfssl_send(struct Curl_easy *data,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
@@ -819,7 +827,7 @@ static ssize_t wolfssl_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data, "SSL write: %s, errno %d",
+ failf(data, "SSL write: %s, errno %d",
ERR_error_string(err, error_buffer),
SOCKERRNO);
*curlcode = CURLE_SEND_ERROR;
@@ -829,11 +837,14 @@ static ssize_t wolfssl_send(struct connectdata *conn,
return rc;
}
-static void Curl_wolfssl_close(struct connectdata *conn, int sockindex)
+static void wolfssl_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;
+ (void) data;
+
if(backend->handle) {
(void)SSL_shutdown(backend->handle);
SSL_free(backend->handle);
@@ -845,12 +856,13 @@ static void Curl_wolfssl_close(struct connectdata *conn, int sockindex)
}
}
-static ssize_t wolfssl_recv(struct connectdata *conn,
+static ssize_t wolfssl_recv(struct Curl_easy *data,
int num,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
@@ -869,9 +881,8 @@ static ssize_t wolfssl_recv(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data, "SSL read: %s, errno %d",
- ERR_error_string(err, error_buffer),
- SOCKERRNO);
+ failf(data, "SSL read: %s, errno %d",
+ ERR_error_string(err, error_buffer), SOCKERRNO);
*curlcode = CURLE_RECV_ERROR;
return -1;
}
@@ -880,14 +891,14 @@ static ssize_t wolfssl_recv(struct connectdata *conn,
}
-static void Curl_wolfssl_session_free(void *ptr)
+static void wolfssl_session_free(void *ptr)
{
(void)ptr;
/* wolfSSL reuses sessions on own, no free */
}
-static size_t Curl_wolfssl_version(char *buffer, size_t size)
+static size_t wolfssl_version(char *buffer, size_t size)
{
#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
@@ -897,7 +908,7 @@ static size_t Curl_wolfssl_version(char *buffer, size_t size)
}
-static int Curl_wolfssl_init(void)
+static int wolfssl_init(void)
{
#ifdef OPENSSL_EXTRA
Curl_tls_keylog_open();
@@ -906,7 +917,7 @@ static int Curl_wolfssl_init(void)
}
-static void Curl_wolfssl_cleanup(void)
+static void wolfssl_cleanup(void)
{
wolfSSL_Cleanup();
#ifdef OPENSSL_EXTRA
@@ -915,8 +926,8 @@ static void Curl_wolfssl_cleanup(void)
}
-static bool Curl_wolfssl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool wolfssl_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -931,12 +942,15 @@ static bool Curl_wolfssl_data_pending(const struct connectdata *conn,
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex)
+static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+ (void) data;
+
if(backend->handle) {
SSL_free(backend->handle);
backend->handle = NULL;
@@ -946,13 +960,13 @@ static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex)
static CURLcode
-wolfssl_connect_common(struct connectdata *conn,
+wolfssl_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
int what;
@@ -973,7 +987,7 @@ wolfssl_connect_common(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- result = wolfssl_connect_step1(conn, sockindex);
+ result = wolfssl_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -1028,7 +1042,7 @@ wolfssl_connect_common(struct connectdata *conn,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = wolfssl_connect_step2(conn, sockindex);
+ result = wolfssl_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1037,7 +1051,7 @@ wolfssl_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = wolfssl_connect_step3(conn, sockindex);
+ result = wolfssl_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -1058,19 +1072,21 @@ wolfssl_connect_common(struct connectdata *conn,
}
-static CURLcode Curl_wolfssl_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode wolfssl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return wolfssl_connect_common(conn, sockindex, TRUE, done);
+ return wolfssl_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex)
+static CURLcode wolfssl_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = wolfssl_connect_common(conn, sockindex, FALSE, &done);
+ result = wolfssl_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -1079,8 +1095,8 @@ static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode wolfssl_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
WC_RNG rng;
(void)data;
@@ -1095,10 +1111,10 @@ static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
wc_Sha256 SHA256pw;
(void)unused;
@@ -1108,7 +1124,7 @@ static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl,
+static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
@@ -1126,26 +1142,25 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
sizeof(struct ssl_backend_data),
- Curl_wolfssl_init, /* init */
- Curl_wolfssl_cleanup, /* cleanup */
- Curl_wolfssl_version, /* version */
+ wolfssl_init, /* init */
+ wolfssl_cleanup, /* cleanup */
+ wolfssl_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_wolfssl_shutdown, /* shutdown */
- Curl_wolfssl_data_pending, /* data_pending */
- Curl_wolfssl_random, /* random */
+ wolfssl_shutdown, /* shutdown */
+ wolfssl_data_pending, /* data_pending */
+ wolfssl_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_wolfssl_connect, /* connect */
- Curl_wolfssl_connect_nonblocking, /* connect_nonblocking */
- Curl_wolfssl_get_internals, /* get_internals */
- Curl_wolfssl_close, /* close_one */
+ wolfssl_connect, /* connect */
+ wolfssl_connect_nonblocking, /* connect_nonblocking */
+ wolfssl_get_internals, /* get_internals */
+ wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_wolfssl_session_free, /* session_free */
+ wolfssl_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 */
- Curl_none_md5sum, /* md5sum */
- Curl_wolfssl_sha256sum /* sha256sum */
+ wolfssl_sha256sum /* sha256sum */
};
#endif
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.h b/Utilities/cmcurl/lib/vtls/wolfssl.h
index 2b9673c0f..d411e6913 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.h
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/warnless.c b/Utilities/cmcurl/lib/warnless.c
index cfd5e8e14..c0764c42d 100644
--- a/Utilities/cmcurl/lib/warnless.c
+++ b/Utilities/cmcurl/lib/warnless.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -156,25 +156,6 @@ unsigned char curlx_ultouc(unsigned long ulnum)
}
/*
-** unsigned long to signed int
-*/
-
-int curlx_ultosi(unsigned long ulnum)
-{
-#ifdef __INTEL_COMPILER
-# pragma warning(push)
-# pragma warning(disable:810) /* conversion may lose significant bits */
-#endif
-
- DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT);
- return (int)(ulnum & (unsigned long) CURL_MASK_SINT);
-
-#ifdef __INTEL_COMPILER
-# pragma warning(pop)
-#endif
-}
-
-/*
** unsigned size_t to signed curl_off_t
*/
diff --git a/Utilities/cmcurl/lib/warnless.h b/Utilities/cmcurl/lib/warnless.h
index ab78f9448..2c619bf81 100644
--- a/Utilities/cmcurl/lib/warnless.h
+++ b/Utilities/cmcurl/lib/warnless.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,8 +33,6 @@ unsigned short curlx_ultous(unsigned long ulnum);
unsigned char curlx_ultouc(unsigned long ulnum);
-int curlx_ultosi(unsigned long ulnum);
-
int curlx_uztosi(size_t uznum);
curl_off_t curlx_uztoso(size_t uznum);
diff --git a/Utilities/cmcurl/lib/wildcard.c b/Utilities/cmcurl/lib/wildcard.c
index e94d3c544..105bcce4e 100644
--- a/Utilities/cmcurl/lib/wildcard.c
+++ b/Utilities/cmcurl/lib/wildcard.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/wildcard.h b/Utilities/cmcurl/lib/wildcard.h
index 306c8c99f..081be9ed9 100644
--- a/Utilities/cmcurl/lib/wildcard.h
+++ b/Utilities/cmcurl/lib/wildcard.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2020, 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.haxx.se/docs/copyright.html.
+ * 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
@@ -39,18 +39,18 @@ typedef enum {
CURLWC_ERROR, /* error cases */
CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop
will end */
-} curl_wildcard_states;
+} wildcard_states;
-typedef void (*curl_wildcard_dtor)(void *ptr);
+typedef void (*wildcard_dtor)(void *ptr);
/* struct keeping information about wildcard download process */
struct WildcardData {
- curl_wildcard_states state;
+ wildcard_states state;
char *path; /* path to the directory, where we trying wildcard-match */
char *pattern; /* wildcard pattern */
- struct curl_llist filelist; /* llist with struct Curl_fileinfo */
+ struct Curl_llist filelist; /* llist with struct Curl_fileinfo */
void *protdata; /* pointer to protocol specific temporary data */
- curl_wildcard_dtor dtor;
+ wildcard_dtor dtor;
void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
};
diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index 52747d57d..f29aa05b8 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -945,13 +945,12 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
}
}
-CURLcode Curl_extract_certinfo(struct connectdata *conn,
+CURLcode Curl_extract_certinfo(struct Curl_easy *data,
int certnum,
const char *beg,
const char *end)
{
struct Curl_X509certificate cert;
- struct Curl_easy *data = conn->data;
struct Curl_asn1Element param;
const char *ccp;
char *cp1;
@@ -1132,10 +1131,9 @@ static const char *checkOID(const char *beg, const char *end,
return matched? ccp: NULL;
}
-CURLcode Curl_verifyhost(struct connectdata *conn,
+CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
const char *beg, const char *end)
{
- struct Curl_easy *data = conn->data;
struct Curl_X509certificate cert;
struct Curl_asn1Element dn;
struct Curl_asn1Element elem;
diff --git a/Utilities/cmcurl/lib/x509asn1.h b/Utilities/cmcurl/lib/x509asn1.h
index 0b7fb8817..326e32d58 100644
--- a/Utilities/cmcurl/lib/x509asn1.h
+++ b/Utilities/cmcurl/lib/x509asn1.h
@@ -8,11 +8,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -125,9 +125,9 @@ const char *Curl_ASN1tostr(struct Curl_asn1Element *elem, int type);
const char *Curl_DNtostr(struct Curl_asn1Element *dn);
int Curl_parseX509(struct Curl_X509certificate *cert,
const char *beg, const char *end);
-CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum,
+CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
const char *beg, const char *end);
-CURLcode Curl_verifyhost(struct connectdata *conn,
+CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
const char *beg, const char *end);
#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */
#endif /* HEADER_CURL_X509ASN1_H */
diff --git a/Utilities/cmexpat/CMakeLists.txt b/Utilities/cmexpat/CMakeLists.txt
index cf315563d..b8dc4e8cc 100644
--- a/Utilities/cmexpat/CMakeLists.txt
+++ b/Utilities/cmexpat/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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt
index 764be8d55..74e998823 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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 6eeba0e65..8362fc4cb 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
@@ -2,74 +2,88 @@
// 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 <utility>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
#include <istream>
-#include <sstream>
+#include <limits>
#include <memory>
#include <set>
-#include <limits>
+#include <sstream>
+#include <utility>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
#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;
@@ -81,7 +95,8 @@ 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;
@@ -92,24 +107,44 @@ 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) {
- 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(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(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
@@ -119,257 +154,263 @@ bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
// create an extra copy.
JSONCPP_STRING doc;
std::getline(sin, doc, (char)EOF);
- return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
+ return this->parse(doc.data(), doc.data() + doc.size(), root,
+ collectComments);
}
-bool Reader::parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
- bool collectComments) {
- if (!features_.allowComments_) {
+bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments)
+{
+ if (!this->features_.allowComments_) {
collectComments = false;
}
- 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();
+ 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();
Token token;
- skipCommentTokens(token);
- if (collectComments_ && !commentsBefore_.empty())
- root.setComment(commentsBefore_, commentAfter);
- if (features_.strictRoot_) {
+ this->skipCommentTokens(token);
+ if (this->collectComments_ && !this->commentsBefore_.empty())
+ root.setComment(this->commentsBefore_, commentAfter);
+ if (this->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;
- addError(
- "A valid JSON document must be either an array or an object value.",
- token);
+ this->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 (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 (this->nodes_.size() > stackLimit_g)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
- skipCommentTokens(token);
+ this->skipCommentTokens(token);
bool successful = true;
- if (collectComments_ && !commentsBefore_.empty()) {
- currentValue().setComment(commentsBefore_, commentBefore);
- commentsBefore_.clear();
+ if (this->collectComments_ && !this->commentsBefore_.empty()) {
+ this->currentValue().setComment(this->commentsBefore_, commentBefore);
+ this->commentsBefore_.clear();
}
switch (token.type_) {
- 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;
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(current_ - begin_ - 1);
- currentValue().setOffsetLimit(current_ - begin_);
+ 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;
- } // Else, fall through...
- default:
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- return addError("Syntax error: value, object or array expected.", token);
+ 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: {
+ 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);
}
- if (collectComments_) {
- lastValueEnd_ = current_;
- lastValue_ = &currentValue();
+ if (this->collectComments_) {
+ this->lastValueEnd_ = this->current_;
+ this->lastValue_ = &this->currentValue();
}
return successful;
}
-void Reader::skipCommentTokens(Token& token) {
- if (features_.allowComments_) {
+void Reader::skipCommentTokens(Token& token)
+{
+ if (this->features_.allowComments_) {
do {
- readToken(token);
+ this->readToken(token);
} while (token.type_ == tokenComment);
} else {
- readToken(token);
+ this->readToken(token);
}
}
-bool Reader::readToken(Token& token) {
- skipSpaces();
- token.start_ = current_;
- Char c = getNextChar();
+bool Reader::readToken(Token& token)
+{
+ this->skipSpaces();
+ token.start_ = this->current_;
+ Char c = this->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 = 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;
+ 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;
}
if (!ok)
token.type_ = tokenError;
- token.end_ = current_;
+ token.end_ = this->current_;
return true;
}
-void Reader::skipSpaces() {
- while (current_ != end_) {
- Char c = *current_;
+void Reader::skipSpaces()
+{
+ while (this->current_ != this->end_) {
+ Char c = *this->current_;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- ++current_;
+ ++this->current_;
else
break;
}
}
-bool Reader::match(Location pattern, int patternLength) {
- if (end_ - current_ < patternLength)
+bool Reader::match(Location pattern, int patternLength)
+{
+ if (this->end_ - this->current_ < patternLength)
return false;
int index = patternLength;
while (index--)
- if (current_[index] != pattern[index])
+ if (this->current_[index] != pattern[index])
return false;
- current_ += patternLength;
+ this->current_ += patternLength;
return true;
}
-bool Reader::readComment() {
- Location commentBegin = current_ - 1;
- Char c = getNextChar();
+bool Reader::readComment()
+{
+ Location commentBegin = this->current_ - 1;
+ Char c = this->getNextChar();
bool successful = false;
if (c == '*')
- successful = readCStyleComment();
+ successful = this->readCStyleComment();
else if (c == '/')
- successful = readCppStyleComment();
+ successful = this->readCppStyleComment();
if (!successful)
return false;
- if (collectComments_) {
+ if (this->collectComments_) {
CommentPlacement placement = commentBefore;
- if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, current_))
+ if (this->lastValueEnd_ &&
+ !containsNewLine(this->lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, this->current_))
placement = commentAfterOnSameLine;
}
- addComment(commentBegin, current_, placement);
+ this->addComment(commentBegin, this->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;
@@ -377,8 +418,8 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end
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 {
@@ -388,36 +429,39 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end
return normalized;
}
-void
-Reader::addComment(Location begin, Location end, CommentPlacement placement) {
- assert(collectComments_);
+void Reader::addComment(Location begin, Location end,
+ CommentPlacement placement)
+{
+ assert(this->collectComments_);
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(lastValue_ != 0);
- lastValue_->setComment(normalized, placement);
+ assert(this->lastValue_ != 0);
+ this->lastValue_->setComment(normalized, placement);
} else {
- commentsBefore_ += normalized;
+ this->commentsBefore_ += normalized;
}
}
-bool Reader::readCStyleComment() {
- while ((current_ + 1) < end_) {
- Char c = getNextChar();
- if (c == '*' && *current_ == '/')
+bool Reader::readCStyleComment()
+{
+ while ((this->current_ + 1) < this->end_) {
+ Char c = this->getNextChar();
+ if (c == '*' && *this->current_ == '/')
break;
}
- return getNextChar() == '/';
+ return this->getNextChar() == '/';
}
-bool Reader::readCppStyleComment() {
- while (current_ != end_) {
- Char c = getNextChar();
+bool Reader::readCppStyleComment()
+{
+ while (this->current_ != this->end_) {
+ Char c = this->getNextChar();
if (c == '\n')
break;
if (c == '\r') {
// Consume DOS EOL. It will be normalized in addComment.
- if (current_ != end_ && *current_ == '\n')
- getNextChar();
+ if (this->current_ != this->end_ && *this->current_ == '\n')
+ this->getNextChar();
// Break on Moc OS 9 EOL.
break;
}
@@ -425,127 +469,132 @@ bool Reader::readCppStyleComment() {
return true;
}
-void Reader::readNumber() {
- const char *p = current_;
+void Reader::readNumber()
+{
+ const char* p = this->current_;
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
}
-bool Reader::readString() {
+bool Reader::readString()
+{
Char c = '\0';
- while (current_ != end_) {
- c = getNextChar();
+ while (this->current_ != this->end_) {
+ c = this->getNextChar();
if (c == '\\')
- getNextChar();
+ this->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);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- while (readToken(tokenName)) {
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ while (this->readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
- initialTokenOk = readToken(tokenName);
+ initialTokenOk = this->readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
return true;
name.clear();
if (tokenName.type_ == tokenString) {
- if (!decodeString(tokenName, name))
- return recoverFromError(tokenObjectEnd);
- } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ if (!this->decodeString(tokenName, name))
+ return this->recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber &&
+ this->features_.allowNumericKeys_) {
Value numberName;
- if (!decodeNumber(tokenName, numberName))
- return recoverFromError(tokenObjectEnd);
+ if (!this->decodeNumber(tokenName, numberName))
+ return this->recoverFromError(tokenObjectEnd);
name = JSONCPP_STRING(numberName.asCString());
} else {
break;
}
Token colon;
- if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return addErrorAndRecover(
- "Missing ':' after object member name", colon, tokenObjectEnd);
+ if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return this->addErrorAndRecover("Missing ':' after object member name",
+ colon, tokenObjectEnd);
}
- Value& value = currentValue()[name];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[name];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenObjectEnd);
+ return this->recoverFromError(tokenObjectEnd);
Token comma;
- if (!readToken(comma) ||
+ if (!this->readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
- finalizeTokenOk = readToken(comma);
+ finalizeTokenOk = this->readToken(comma);
if (comma.type_ == tokenObjectEnd)
return true;
}
- return addErrorAndRecover(
- "Missing '}' or object member name", tokenName, tokenObjectEnd);
+ return this->addErrorAndRecover("Missing '}' or object member name",
+ tokenName, tokenObjectEnd);
}
-bool Reader::readArray(Token& tokenStart) {
+bool Reader::readArray(Token& tokenStart)
+{
Value init(arrayValue);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- skipSpaces();
- if (current_ != end_ && *current_ == ']') // empty array
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ this->skipSpaces();
+ if (this->current_ != this->end_ && *this->current_ == ']') // empty array
{
Token endArray;
- readToken(endArray);
+ this->readToken(endArray);
return true;
}
int index = 0;
for (;;) {
- Value& value = currentValue()[index++];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[index++];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenArrayEnd);
+ return this->recoverFromError(tokenArrayEnd);
Token token;
// Accept Comment after last item in the array.
- ok = readToken(token);
+ ok = this->readToken(token);
while (token.type_ == tokenComment && ok) {
- ok = readToken(token);
+ ok = this->readToken(token);
}
bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
}
if (token.type_ == tokenArrayEnd)
break;
@@ -553,17 +602,19 @@ bool Reader::readArray(Token& tokenStart) {
return true;
}
-bool Reader::decodeNumber(Token& token) {
+bool Reader::decodeNumber(Token& token)
+{
Value decoded;
- if (!decodeNumber(token, decoded))
+ if (!this->decodeNumber(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->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.
@@ -571,16 +622,17 @@ 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 decodeDouble(token, decoded);
+ return this->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
@@ -589,7 +641,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 decodeDouble(token, decoded);
+ return this->decodeDouble(token, decoded);
}
}
value = value * 10 + digit;
@@ -605,40 +657,44 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
return true;
}
-bool Reader::decodeDouble(Token& token) {
+bool Reader::decodeDouble(Token& token)
+{
Value decoded;
- if (!decodeDouble(token, decoded))
+ if (!this->decodeDouble(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->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 addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
+ return this->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 (!decodeString(token, decoded_string))
+ if (!this->decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->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 '"'
@@ -648,41 +704,43 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
break;
else if (c == '\\') {
if (current == end)
- return addError("Empty escape sequence in string", token, current);
+ return this->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 (!decodeUnicodeCodePoint(token, current, end, unicode))
- return false;
- decoded += codePointToUTF8(unicode);
- } break;
- default:
- return 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 (!this->decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return this->addError("Bad escape sequence in string", token,
+ current);
}
} else {
decoded += c;
@@ -691,44 +749,43 @@ 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 (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode))
return false;
if (unicode >= 0xD800 && unicode <= 0xDBFF) {
// surrogate pairs
if (end - current < 6)
- return addError(
- "additional six characters expected to parse unicode surrogate pair.",
- token,
- current);
+ return this->addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token, current);
unsigned int surrogatePair;
if (*(current++) == '\\' && *(current++) == 'u') {
- if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
- unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ if (this->decodeUnicodeEscapeSequence(token, current, end,
+ surrogatePair)) {
+ unicode =
+ 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
- return addError("expecting another \\u token to begin the second half of "
- "a unicode surrogate pair",
- token,
- current);
+ return this->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 addError(
- "Bad unicode escape sequence in string: four digits expected.",
- token,
- current);
+ return this->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++;
@@ -740,60 +797,65 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token,
else if (c >= 'A' && c <= 'F')
unicode += c - 'A' + 10;
else
- return addError(
- "Bad unicode escape sequence in string: hexadecimal digit expected.",
- token,
- current);
+ return this->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;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return false;
}
-bool Reader::recoverFromError(TokenType skipUntilToken) {
- size_t const errorCount = errors_.size();
+bool Reader::recoverFromError(TokenType skipUntilToken)
+{
+ size_t const errorCount = this->errors_.size();
Token skip;
for (;;) {
- if (!readToken(skip))
- errors_.resize(errorCount); // discard errors caused by recovery
+ if (!this->readToken(skip))
+ this->errors_.resize(errorCount); // discard errors caused by recovery
if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
break;
}
- errors_.resize(errorCount);
+ this->errors_.resize(errorCount);
return false;
}
-bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
- TokenType skipUntilToken) {
- addError(message, token);
- return recoverFromError(skipUntilToken);
+bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
+ TokenType skipUntilToken)
+{
+ this->addError(message, token);
+ return this->recoverFromError(skipUntilToken);
}
-Value& Reader::currentValue() { return *(nodes_.top()); }
+Value& Reader::currentValue()
+{
+ return *(this->nodes_.top());
+}
-Reader::Char Reader::getNextChar() {
- if (current_ == end_)
+Reader::Char Reader::getNextChar()
+{
+ if (this->current_ == this->end_)
return 0;
- return *current_++;
+ return *this->current_++;
}
-void Reader::getLocationLineAndColumn(Location location,
- int& line,
- int& column) const {
- Location current = begin_;
+void Reader::getLocationLineAndColumn(Location location, int& line,
+ int& column) const
+{
+ Location current = this->begin_;
Location lastLineStart = current;
line = 0;
- while (current < location && current != end_) {
+ while (current < location && current != this->end_) {
Char c = *current++;
if (c == '\r') {
if (*current == '\n')
@@ -810,91 +872,96 @@ void Reader::getLocationLineAndColumn(Location location,
++line;
}
-JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
+JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const
+{
int line, column;
- getLocationLineAndColumn(location, line, column);
+ this->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 getFormattedErrorMessages();
+JSONCPP_STRING Reader::getFormatedErrorMessages() const
+{
+ return this->getFormattedErrorMessages();
}
-JSONCPP_STRING Reader::getFormattedErrorMessages() const {
+JSONCPP_STRING Reader::getFormattedErrorMessages() const
+{
JSONCPP_STRING formattedMessage;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
- "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
if (error.extra_)
- formattedMessage +=
- "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ formattedMessage += "See " +
+ this->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 = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
Reader::StructuredError structured;
- structured.offset_start = error.token_.start_ - begin_;
- structured.offset_limit = error.token_.end_ - begin_;
+ structured.offset_start = error.token_.start_ - this->begin_;
+ structured.offset_limit = error.token_.end_ - this->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 = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length)
+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)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = end_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return true;
}
-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)
+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)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = begin_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
- info.extra_ = begin_ + extra.getOffsetStart();
- errors_.push_back(info);
+ info.extra_ = this->begin_ + extra.getOffsetStart();
+ this->errors_.push_back(info);
return true;
}
-bool Reader::good() const {
- return !errors_.size();
+bool Reader::good() const
+{
+ return !this->errors_.size();
}
// exact copy of Features
-class OurFeatures {
+class OurFeatures
+{
public:
static OurFeatures all();
bool allowComments_;
@@ -906,43 +973,48 @@ 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,
@@ -962,14 +1034,16 @@ private:
tokenError
};
- class Token {
+ class Token
+ {
public:
TokenType type_;
Location start_;
Location end_;
};
- class ErrorInfo {
+ class ErrorInfo
+ {
public:
Token token_;
JSONCPP_STRING message_;
@@ -996,24 +1070,20 @@ 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);
@@ -1034,11 +1104,13 @@ 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;
@@ -1046,315 +1118,322 @@ bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location e
}
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 (!features_.allowComments_) {
+bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments)
+{
+ if (!this->features_.allowComments_) {
collectComments = false;
}
- 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();
+ 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();
Token token;
- skipCommentTokens(token);
- if (features_.failIfExtra_) {
- if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
- addError("Extra non-whitespace after JSON value.", 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);
return false;
}
}
- if (collectComments_ && !commentsBefore_.empty())
- root.setComment(commentsBefore_, commentAfter);
- if (features_.strictRoot_) {
+ if (this->collectComments_ && !this->commentsBefore_.empty())
+ root.setComment(this->commentsBefore_, commentAfter);
+ if (this->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;
- addError(
- "A valid JSON document must be either an array or an object value.",
- token);
+ this->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>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
+ if (static_cast<int>(this->nodes_.size()) > this->features_.stackLimit_)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
- skipCommentTokens(token);
+ this->skipCommentTokens(token);
bool successful = true;
- if (collectComments_ && !commentsBefore_.empty()) {
- currentValue().setComment(commentsBefore_, commentBefore);
- commentsBefore_.clear();
+ if (this->collectComments_ && !this->commentsBefore_.empty()) {
+ this->currentValue().setComment(this->commentsBefore_, commentBefore);
+ this->commentsBefore_.clear();
}
switch (token.type_) {
- 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;
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(current_ - begin_ - 1);
- currentValue().setOffsetLimit(current_ - begin_);
+ 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;
- } // else, fall through ...
- default:
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- return addError("Syntax error: value, object or array expected.", token);
+ 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: {
+ 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);
}
- if (collectComments_) {
- lastValueEnd_ = current_;
- lastValue_ = &currentValue();
+ if (this->collectComments_) {
+ this->lastValueEnd_ = this->current_;
+ this->lastValue_ = &this->currentValue();
}
return successful;
}
-void OurReader::skipCommentTokens(Token& token) {
- if (features_.allowComments_) {
+void OurReader::skipCommentTokens(Token& token)
+{
+ if (this->features_.allowComments_) {
do {
- readToken(token);
+ this->readToken(token);
} while (token.type_ == tokenComment);
} else {
- readToken(token);
+ this->readToken(token);
}
}
-bool OurReader::readToken(Token& token) {
- skipSpaces();
- token.start_ = current_;
- Char c = getNextChar();
+bool OurReader::readToken(Token& token)
+{
+ this->skipSpaces();
+ token.start_ = this->current_;
+ Char c = this->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 = 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)) {
+ 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':
token.type_ = tokenNumber;
- } 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;
- case 'I':
- if (features_.allowSpecialFloats_) {
- token.type_ = tokenPosInf;
- ok = match("nfinity", 7);
- } else {
+ 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:
ok = false;
- }
- break;
- case ',':
- token.type_ = tokenArraySeparator;
- break;
- case ':':
- token.type_ = tokenMemberSeparator;
- break;
- case 0:
- token.type_ = tokenEndOfStream;
- break;
- default:
- ok = false;
- break;
+ break;
}
if (!ok)
token.type_ = tokenError;
- token.end_ = current_;
+ token.end_ = this->current_;
return true;
}
-void OurReader::skipSpaces() {
- while (current_ != end_) {
- Char c = *current_;
+void OurReader::skipSpaces()
+{
+ while (this->current_ != this->end_) {
+ Char c = *this->current_;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- ++current_;
+ ++this->current_;
else
break;
}
}
-bool OurReader::match(Location pattern, int patternLength) {
- if (end_ - current_ < patternLength)
+bool OurReader::match(Location pattern, int patternLength)
+{
+ if (this->end_ - this->current_ < patternLength)
return false;
int index = patternLength;
while (index--)
- if (current_[index] != pattern[index])
+ if (this->current_[index] != pattern[index])
return false;
- current_ += patternLength;
+ this->current_ += patternLength;
return true;
}
-bool OurReader::readComment() {
- Location commentBegin = current_ - 1;
- Char c = getNextChar();
+bool OurReader::readComment()
+{
+ Location commentBegin = this->current_ - 1;
+ Char c = this->getNextChar();
bool successful = false;
if (c == '*')
- successful = readCStyleComment();
+ successful = this->readCStyleComment();
else if (c == '/')
- successful = readCppStyleComment();
+ successful = this->readCppStyleComment();
if (!successful)
return false;
- if (collectComments_) {
+ if (this->collectComments_) {
CommentPlacement placement = commentBefore;
- if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, current_))
+ if (this->lastValueEnd_ &&
+ !containsNewLine(this->lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, this->current_))
placement = commentAfterOnSameLine;
}
- addComment(commentBegin, current_, placement);
+ this->addComment(commentBegin, this->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;
@@ -1362,8 +1441,8 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Loc
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 {
@@ -1373,36 +1452,39 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Loc
return normalized;
}
-void
-OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
- assert(collectComments_);
+void OurReader::addComment(Location begin, Location end,
+ CommentPlacement placement)
+{
+ assert(this->collectComments_);
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(lastValue_ != 0);
- lastValue_->setComment(normalized, placement);
+ assert(this->lastValue_ != 0);
+ this->lastValue_->setComment(normalized, placement);
} else {
- commentsBefore_ += normalized;
+ this->commentsBefore_ += normalized;
}
}
-bool OurReader::readCStyleComment() {
- while ((current_ + 1) < end_) {
- Char c = getNextChar();
- if (c == '*' && *current_ == '/')
+bool OurReader::readCStyleComment()
+{
+ while ((this->current_ + 1) < this->end_) {
+ Char c = this->getNextChar();
+ if (c == '*' && *this->current_ == '/')
break;
}
- return getNextChar() == '/';
+ return this->getNextChar() == '/';
}
-bool OurReader::readCppStyleComment() {
- while (current_ != end_) {
- Char c = getNextChar();
+bool OurReader::readCppStyleComment()
+{
+ while (this->current_ != this->end_) {
+ Char c = this->getNextChar();
if (c == '\n')
break;
if (c == '\r') {
// Consume DOS EOL. It will be normalized in addComment.
- if (current_ != end_ && *current_ == '\n')
- getNextChar();
+ if (this->current_ != this->end_ && *this->current_ == '\n')
+ this->getNextChar();
// Break on Moc OS 9 EOL.
break;
}
@@ -1410,150 +1492,156 @@ bool OurReader::readCppStyleComment() {
return true;
}
-bool OurReader::readNumber(bool checkInf) {
- const char *p = current_;
- if (checkInf && p != end_ && *p == 'I') {
- current_ = ++p;
+bool OurReader::readNumber(bool checkInf)
+{
+ const char* p = this->current_;
+ if (checkInf && p != this->end_ && *p == 'I') {
+ this->current_ = ++p;
return false;
}
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
return true;
}
-bool OurReader::readString() {
+bool OurReader::readString()
+{
Char c = 0;
- while (current_ != end_) {
- c = getNextChar();
+ while (this->current_ != this->end_) {
+ c = this->getNextChar();
if (c == '\\')
- getNextChar();
+ this->getNextChar();
else if (c == '"')
break;
}
return c == '"';
}
-
-bool OurReader::readStringSingleQuote() {
+bool OurReader::readStringSingleQuote()
+{
Char c = 0;
- while (current_ != end_) {
- c = getNextChar();
+ while (this->current_ != this->end_) {
+ c = this->getNextChar();
if (c == '\\')
- getNextChar();
+ this->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);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- while (readToken(tokenName)) {
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ while (this->readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
- initialTokenOk = readToken(tokenName);
+ initialTokenOk = this->readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
return true;
name.clear();
if (tokenName.type_ == tokenString) {
- if (!decodeString(tokenName, name))
- return recoverFromError(tokenObjectEnd);
- } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ if (!this->decodeString(tokenName, name))
+ return this->recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber &&
+ this->features_.allowNumericKeys_) {
Value numberName;
- if (!decodeNumber(tokenName, numberName))
- return recoverFromError(tokenObjectEnd);
+ if (!this->decodeNumber(tokenName, numberName))
+ return this->recoverFromError(tokenObjectEnd);
name = numberName.asString();
} else {
break;
}
Token colon;
- if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return addErrorAndRecover(
- "Missing ':' after object member name", colon, tokenObjectEnd);
+ if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return this->addErrorAndRecover("Missing ':' after object member name",
+ colon, tokenObjectEnd);
}
- if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
- if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+ if (name.length() >= (1U << 30))
+ throwRuntimeError("keylength >= 2^30");
+ if (this->features_.rejectDupKeys_ &&
+ this->currentValue().isMember(name)) {
JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
- return addErrorAndRecover(
- msg, tokenName, tokenObjectEnd);
+ return this->addErrorAndRecover(msg, tokenName, tokenObjectEnd);
}
- Value& value = currentValue()[name];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[name];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenObjectEnd);
+ return this->recoverFromError(tokenObjectEnd);
Token comma;
- if (!readToken(comma) ||
+ if (!this->readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
- finalizeTokenOk = readToken(comma);
+ finalizeTokenOk = this->readToken(comma);
if (comma.type_ == tokenObjectEnd)
return true;
}
- return addErrorAndRecover(
- "Missing '}' or object member name", tokenName, tokenObjectEnd);
+ return this->addErrorAndRecover("Missing '}' or object member name",
+ tokenName, tokenObjectEnd);
}
-bool OurReader::readArray(Token& tokenStart) {
+bool OurReader::readArray(Token& tokenStart)
+{
Value init(arrayValue);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- skipSpaces();
- if (current_ != end_ && *current_ == ']') // empty array
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ this->skipSpaces();
+ if (this->current_ != this->end_ && *this->current_ == ']') // empty array
{
Token endArray;
- readToken(endArray);
+ this->readToken(endArray);
return true;
}
int index = 0;
for (;;) {
- Value& value = currentValue()[index++];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[index++];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenArrayEnd);
+ return this->recoverFromError(tokenArrayEnd);
Token token;
// Accept Comment after last item in the array.
- ok = readToken(token);
+ ok = this->readToken(token);
while (token.type_ == tokenComment && ok) {
- ok = readToken(token);
+ ok = this->readToken(token);
}
bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
}
if (token.type_ == tokenArrayEnd)
break;
@@ -1561,17 +1649,19 @@ bool OurReader::readArray(Token& tokenStart) {
return true;
}
-bool OurReader::decodeNumber(Token& token) {
+bool OurReader::decodeNumber(Token& token)
+{
Value decoded;
- if (!decodeNumber(token, decoded))
+ if (!this->decodeNumber(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->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.
@@ -1579,16 +1669,17 @@ 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 decodeDouble(token, decoded);
+ return this->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
@@ -1597,7 +1688,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 decodeDouble(token, decoded);
+ return this->decodeDouble(token, decoded);
}
}
value = value * 10 + digit;
@@ -1611,17 +1702,19 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
return true;
}
-bool OurReader::decodeDouble(Token& token) {
+bool OurReader::decodeDouble(Token& token)
+{
Value decoded;
- if (!decodeDouble(token, decoded))
+ if (!this->decodeDouble(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->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;
@@ -1629,7 +1722,7 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
// Sanity check to avoid buffer overflow exploits.
if (length < 0) {
- return addError("Unable to parse token length", token);
+ return this->addError("Unable to parse token length", token);
}
size_t const ulength = static_cast<size_t>(length);
@@ -1652,25 +1745,27 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
}
if (count != 1)
- return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
+ return this->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 (!decodeString(token, decoded_string))
+ if (!this->decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->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 '"'
@@ -1680,41 +1775,43 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
break;
else if (c == '\\') {
if (current == end)
- return addError("Empty escape sequence in string", token, current);
+ return this->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 (!decodeUnicodeCodePoint(token, current, end, unicode))
- return false;
- decoded += codePointToUTF8(unicode);
- } break;
- default:
- return 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 (!this->decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return this->addError("Bad escape sequence in string", token,
+ current);
}
} else {
decoded += c;
@@ -1723,45 +1820,44 @@ 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 (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode))
return false;
if (unicode >= 0xD800 && unicode <= 0xDBFF) {
// surrogate pairs
if (end - current < 6)
- return addError(
- "additional six characters expected to parse unicode surrogate pair.",
- token,
- current);
+ return this->addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token, current);
unsigned int surrogatePair;
if (*(current++) == '\\' && *(current++) == 'u') {
- if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
- unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ if (this->decodeUnicodeEscapeSequence(token, current, end,
+ surrogatePair)) {
+ unicode =
+ 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
- return addError("expecting another \\u token to begin the second half of "
- "a unicode surrogate pair",
- token,
- current);
+ return this->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 addError(
- "Bad unicode escape sequence in string: four digits expected.",
- token,
- current);
+ return this->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++;
@@ -1773,60 +1869,65 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token,
else if (c >= 'A' && c <= 'F')
unicode += c - 'A' + 10;
else
- return addError(
- "Bad unicode escape sequence in string: hexadecimal digit expected.",
- token,
- current);
+ return this->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;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return false;
}
-bool OurReader::recoverFromError(TokenType skipUntilToken) {
- size_t errorCount = errors_.size();
+bool OurReader::recoverFromError(TokenType skipUntilToken)
+{
+ size_t errorCount = this->errors_.size();
Token skip;
for (;;) {
- if (!readToken(skip))
- errors_.resize(errorCount); // discard errors caused by recovery
+ if (!this->readToken(skip))
+ this->errors_.resize(errorCount); // discard errors caused by recovery
if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
break;
}
- errors_.resize(errorCount);
+ this->errors_.resize(errorCount);
return false;
}
-bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
- TokenType skipUntilToken) {
- addError(message, token);
- return recoverFromError(skipUntilToken);
+bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
+ TokenType skipUntilToken)
+{
+ this->addError(message, token);
+ return this->recoverFromError(skipUntilToken);
}
-Value& OurReader::currentValue() { return *(nodes_.top()); }
+Value& OurReader::currentValue()
+{
+ return *(this->nodes_.top());
+}
-OurReader::Char OurReader::getNextChar() {
- if (current_ == end_)
+OurReader::Char OurReader::getNextChar()
+{
+ if (this->current_ == this->end_)
return 0;
- return *current_++;
+ return *this->current_++;
}
-void OurReader::getLocationLineAndColumn(Location location,
- int& line,
- int& column) const {
- Location current = begin_;
+void OurReader::getLocationLineAndColumn(Location location, int& line,
+ int& column) const
+{
+ Location current = this->begin_;
Location lastLineStart = current;
line = 0;
- while (current < location && current != end_) {
+ while (current < location && current != this->end_) {
Char c = *current++;
if (c == '\r') {
if (*current == '\n')
@@ -1843,101 +1944,105 @@ void OurReader::getLocationLineAndColumn(Location location,
++line;
}
-JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
+JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const
+{
int line, column;
- getLocationLineAndColumn(location, line, column);
+ this->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 = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
- "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
if (error.extra_)
- formattedMessage +=
- "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ formattedMessage += "See " +
+ this->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 = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
OurReader::StructuredError structured;
- structured.offset_start = error.token_.start_ - begin_;
- structured.offset_limit = error.token_.end_ - begin_;
+ structured.offset_start = error.token_.start_ - this->begin_;
+ structured.offset_limit = error.token_.end_ - this->begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
-bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
- ptrdiff_t length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length)
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message)
+{
+ ptrdiff_t length = this->end_ - this->begin_;
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = end_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return true;
}
-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)
+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)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = begin_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
- info.extra_ = begin_ + extra.getOffsetStart();
- errors_.push_back(info);
+ info.extra_ = this->begin_ + extra.getOffsetStart();
+ this->errors_.push_back(info);
return true;
}
-bool OurReader::good() const {
- return !errors_.size();
+bool OurReader::good() const
+{
+ return !this->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 = reader_.parse(beginDoc, endDoc, *root, 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 =
+ this->reader_.parse(beginDoc, endDoc, *root, this->collectComments_);
if (errs) {
- *errs = reader_.getFormattedErrorMessages();
+ *errs = this->reader_.getFormattedErrorMessages();
}
return ok;
}
@@ -1945,23 +2050,26 @@ public:
CharReaderBuilder::CharReaderBuilder()
{
- setDefaults(&settings_);
+ setDefaults(&this->settings_);
}
CharReaderBuilder::~CharReaderBuilder()
-{}
+{
+}
CharReader* CharReaderBuilder::newCharReader() const
{
- bool collectComments = settings_["collectComments"].asBool();
+ bool collectComments = this->settings_["collectComments"].asBool();
OurFeatures features = OurFeatures::all();
- 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();
+ 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();
return new OurCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
@@ -1981,28 +2089,29 @@ 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 = settings_.getMemberNames();
+ Value::Members keys = this->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] = settings_[key];
+ inv[key] = this->settings_[key];
}
}
return 0u == inv.size();
}
Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
{
- return settings_[key];
+ return this->settings_[key];
}
// static
void CharReaderBuilder::strictMode(Json::Value* settings)
{
-//! [CharReaderBuilderStrictMode]
+ //! [CharReaderBuilderStrictMode]
(*settings)["allowComments"] = false;
(*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false;
@@ -2012,12 +2121,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;
@@ -2028,15 +2137,14 @@ 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();
@@ -2048,14 +2156,13 @@ bool parseFromStream(
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 f271e5731..eadb1c375 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
@@ -1,23 +1,25 @@
// 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 <string.h>
+
#include <assert.h>
+#include <math.h>
+#include <string.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)
@@ -27,24 +29,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();
@@ -66,23 +68,29 @@ 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)
@@ -94,8 +102,7 @@ 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.
@@ -104,9 +111,8 @@ static inline char* duplicateStringValue(const char* value,
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;
@@ -115,30 +121,30 @@ static inline char* duplicateStringValue(const char* value,
/* 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));
@@ -148,10 +154,12 @@ inline static void decodePrefixedString(
*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);
@@ -159,17 +167,20 @@ 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
@@ -185,26 +196,30 @@ 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 msg_.c_str();
+ return this->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);
@@ -222,25 +237,29 @@ JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
-Value::CommentInfo::CommentInfo() : comment_(0)
-{}
+Value::CommentInfo::CommentInfo()
+ : comment_(0)
+{
+}
-Value::CommentInfo::~CommentInfo() {
- if (comment_)
- releaseStringValue(comment_, 0u);
+Value::CommentInfo::~CommentInfo()
+{
+ if (this->comment_)
+ releaseStringValue(this->comment_, 0u);
}
-void Value::CommentInfo::setComment(const char* text, size_t len) {
- if (comment_) {
- releaseStringValue(comment_, 0u);
- comment_ = 0;
+void Value::CommentInfo::setComment(const char* text, size_t len)
+{
+ if (this->comment_) {
+ releaseStringValue(this->comment_, 0u);
+ this->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.
- comment_ = duplicateStringValue(text, len);
+ this->comment_ = duplicateStringValue(text, len);
}
// //////////////////////////////////////////////////////////////////
@@ -254,91 +273,130 @@ 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
- storage_.policy_ = allocate & 0x3;
- storage_.length_ = ulength & 0x3FFFFFFF;
+ this->storage_.policy_ = allocate & 0x3;
+ this->storage_.length_ = ulength & 0x3FFFFFFF;
}
-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_;
+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_;
}
#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 (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
+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
}
}
-void Value::CZString::swap(CZString& other) {
- std::swap(cstr_, other.cstr_);
- std::swap(index_, other.index_);
+void Value::CZString::swap(CZString& other)
+{
+ std::swap(this->cstr_, other.cstr_);
+ std::swap(this->index_, other.index_);
}
-Value::CZString& Value::CZString::operator=(const CZString& other) {
- cstr_ = other.cstr_;
- index_ = other.index_;
+Value::CZString& Value::CZString::operator=(const CZString& other)
+{
+ this->cstr_ = other.cstr_;
+ this->index_ = other.index_;
return *this;
}
#if JSON_HAS_RVALUE_REFERENCES
-Value::CZString& Value::CZString::operator=(CZString&& other) {
- cstr_ = other.cstr_;
- index_ = other.index_;
+Value::CZString& Value::CZString::operator=(CZString&& other)
+{
+ this->cstr_ = other.cstr_;
+ this->index_ = other.index_;
other.cstr_ = nullptr;
return *this;
}
#endif
-bool Value::CZString::operator<(const CZString& other) const {
- if (!cstr_) return index_ < other.index_;
- //return strcmp(cstr_, other.cstr_) < 0;
+bool Value::CZString::operator<(const CZString& other) const
+{
+ if (!this->cstr_)
+ return this->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 (!cstr_) return index_ == other.index_;
- //return strcmp(cstr_, other.cstr_) == 0;
+bool Value::CZString::operator==(const CZString& other) const
+{
+ if (!this->cstr_)
+ return this->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 index_; }
+ArrayIndex Value::CZString::index() const
+{
+ return this->index_;
+}
-//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; }
+// 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;
+}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -352,210 +410,238 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* 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[] = "";
- initBasic(vtype);
+ this->initBasic(vtype);
switch (vtype) {
- 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;
+ 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;
}
}
-Value::Value(Int value) {
- initBasic(intValue);
- value_.int_ = value;
+Value::Value(Int value)
+{
+ this->initBasic(intValue);
+ this->value_.int_ = value;
}
-Value::Value(UInt value) {
- initBasic(uintValue);
- value_.uint_ = value;
+Value::Value(UInt value)
+{
+ this->initBasic(uintValue);
+ this->value_.uint_ = value;
}
#if defined(JSON_HAS_INT64)
-Value::Value(Int64 value) {
- initBasic(intValue);
- value_.int_ = value;
+Value::Value(Int64 value)
+{
+ this->initBasic(intValue);
+ this->value_.int_ = value;
}
-Value::Value(UInt64 value) {
- initBasic(uintValue);
- value_.uint_ = value;
+Value::Value(UInt64 value)
+{
+ this->initBasic(uintValue);
+ this->value_.uint_ = value;
}
#endif // defined(JSON_HAS_INT64)
-Value::Value(double value) {
- initBasic(realValue);
- value_.real_ = value;
+Value::Value(double value)
+{
+ this->initBasic(realValue);
+ this->value_.real_ = value;
}
-Value::Value(const char* value) {
- initBasic(stringValue, true);
+Value::Value(const char* value)
+{
+ this->initBasic(stringValue, true);
JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
- value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
+ this->value_.string_ =
+ duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
}
-Value::Value(const char* beginValue, const char* endValue) {
- initBasic(stringValue, true);
- value_.string_ =
- duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
+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 JSONCPP_STRING& value) {
- initBasic(stringValue, true);
- value_.string_ =
- duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
+Value::Value(const JSONCPP_STRING& value)
+{
+ this->initBasic(stringValue, true);
+ this->value_.string_ = duplicateAndPrefixStringValue(
+ value.data(), static_cast<unsigned>(value.length()));
}
-Value::Value(const StaticString& value) {
- initBasic(stringValue);
- value_.string_ = const_cast<char*>(value.c_str());
+Value::Value(const StaticString& value)
+{
+ this->initBasic(stringValue);
+ this->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) {
- initBasic(booleanValue);
- value_.bool_ = value;
+Value::Value(bool value)
+{
+ this->initBasic(booleanValue);
+ this->value_.bool_ = value;
}
Value::Value(Value const& other)
- : 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;
+ : 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;
}
if (other.comments_) {
- comments_ = new CommentInfo[numberOfCommentPlacement];
+ this->comments_ = new CommentInfo[numberOfCommentPlacement];
for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
const CommentInfo& otherComment = other.comments_[comment];
if (otherComment.comment_)
- comments_[comment].setComment(
- otherComment.comment_, strlen(otherComment.comment_));
+ this->comments_[comment].setComment(otherComment.comment_,
+ strlen(otherComment.comment_));
}
}
}
#if JSON_HAS_RVALUE_REFERENCES
// Move constructor
-Value::Value(Value&& other) {
- initBasic(nullValue);
- swap(other);
+Value::Value(Value&& other)
+{
+ this->initBasic(nullValue);
+ this->swap(other);
}
#endif
-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;
+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;
}
- delete[] comments_;
+ delete[] this->comments_;
- value_.uint_ = 0;
+ this->value_.uint_ = 0;
}
-Value& Value::operator=(Value other) {
- swap(other);
+Value& Value::operator=(Value other)
+{
+ this->swap(other);
return *this;
}
-void Value::swapPayload(Value& other) {
- ValueType temp = type_;
- type_ = other.type_;
+void Value::swapPayload(Value& other)
+{
+ ValueType temp = this->type_;
+ this->type_ = other.type_;
other.type_ = temp;
- std::swap(value_, other.value_);
- int temp2 = allocated_;
- allocated_ = other.allocated_;
+ std::swap(this->value_, other.value_);
+ int temp2 = this->allocated_;
+ this->allocated_ = other.allocated_;
other.allocated_ = temp2 & 0x1;
}
-void Value::copyPayload(const Value& other) {
- type_ = other.type_;
- value_ = other.value_;
- allocated_ = other.allocated_;
+void Value::copyPayload(const Value& other)
+{
+ this->type_ = other.type_;
+ this->value_ = other.value_;
+ this->allocated_ = other.allocated_;
}
-void Value::swap(Value& other) {
- swapPayload(other);
- std::swap(comments_, other.comments_);
- std::swap(start_, other.start_);
- std::swap(limit_, other.limit_);
+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::copy(const Value& other) {
- copyPayload(other);
- comments_ = other.comments_;
- start_ = other.start_;
- limit_ = other.limit_;
+void Value::copy(const Value& other)
+{
+ this->copyPayload(other);
+ this->comments_ = other.comments_;
+ this->start_ = other.start_;
+ this->limit_ = other.limit_;
}
-ValueType Value::type() const { return type_; }
+ValueType Value::type() const
+{
+ return this->type_;
+}
-int Value::compare(const Value& other) const {
+int Value::compare(const Value& other) const
+{
if (*this < other)
return -1;
if (*this > other)
@@ -563,509 +649,568 @@ int Value::compare(const Value& other) const {
return 0;
}
-bool Value::operator<(const Value& other) const {
- int typeDelta = type_ - other.type_;
+bool Value::operator<(const Value& other) const
+{
+ int typeDelta = this->type_ - other.type_;
if (typeDelta)
return typeDelta < 0 ? true : false;
- 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;
+ 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);
}
- 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;
+ 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_);
+ }
+ 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 (type_ != temp)
+ if (this->type_ != temp)
return false;
- 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_);
+ 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;
}
- 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;
+ case arrayValue:
+ case objectValue:
+ return this->value_.map_->size() == other.value_.map_->size() &&
+ (*this->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 (value_.string_ == 0) return 0;
+ if (this->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 (type_ != stringValue) return false;
- if (value_.string_ == 0) return false;
+bool Value::getString(char const** str, char const** cend) const
+{
+ if (this->type_ != stringValue)
+ return false;
+ if (this->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 (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");
+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");
}
}
#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 (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;
+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;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int.");
}
-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;
+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;
}
JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
}
#if defined(JSON_HAS_INT64)
-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;
+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;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
}
-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;
+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;
}
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 asInt64();
+ return this->asInt64();
#endif
}
-LargestUInt Value::asLargestUInt() const {
+LargestUInt Value::asLargestUInt() const
+{
#if defined(JSON_NO_INT64)
return asUInt();
#else
- return asUInt64();
+ return this->asUInt64();
#endif
}
-double Value::asDouble() const {
- switch (type_) {
- case intValue:
- return static_cast<double>(value_.int_);
- case uintValue:
+double Value::asDouble() const
+{
+ switch (this->type_) {
+ case intValue:
+ return static_cast<double>(this->value_.int_);
+ case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<double>(value_.uint_);
+ return static_cast<double>(this->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 value_.real_;
- case nullValue:
- return 0.0;
- case booleanValue:
- return value_.bool_ ? 1.0 : 0.0;
- default:
- break;
+ case realValue:
+ return this->value_.real_;
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return this->value_.bool_ ? 1.0 : 0.0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to double.");
}
-float Value::asFloat() const {
- switch (type_) {
- case intValue:
- return static_cast<float>(value_.int_);
- case uintValue:
+float Value::asFloat() const
+{
+ switch (this->type_) {
+ case intValue:
+ return static_cast<float>(this->value_.int_);
+ case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<float>(value_.uint_);
+ return static_cast<float>(this->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>(value_.real_);
- case nullValue:
- return 0.0;
- case booleanValue:
- return value_.bool_ ? 1.0f : 0.0f;
- default:
- break;
+ 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;
}
JSON_FAIL_MESSAGE("Value is not convertible to float.");
}
-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;
+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;
}
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 (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;
+ 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;
}
JSON_ASSERT_UNREACHABLE;
return false;
}
/// Number of values in array or object
-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());
+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());
}
JSON_ASSERT_UNREACHABLE;
return 0; // unreachable;
}
-bool Value::empty() const {
- if (isNull() || isArray() || isObject())
- return size() == 0u;
+bool Value::empty() const
+{
+ if (this->isNull() || this->isArray() || this->isObject())
+ return this->size() == 0u;
else
return false;
}
-bool Value::operator!() const { return isNull(); }
+bool Value::operator!() const
+{
+ return this->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");
- start_ = 0;
- limit_ = 0;
- switch (type_) {
- case arrayValue:
- case objectValue:
- value_.map_->clear();
- break;
- default:
- break;
+ this->start_ = 0;
+ this->limit_ = 0;
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ this->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 (type_ == nullValue)
+ if (this->type_ == nullValue)
*this = Value(arrayValue);
- ArrayIndex oldSize = size();
+ ArrayIndex oldSize = this->size();
if (newSize == 0)
- clear();
+ this->clear();
else if (newSize > oldSize)
(*this)[newSize - 1];
else {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
- value_.map_->erase(index);
+ this->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 (type_ == nullValue)
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex): requires arrayValue");
+ if (this->type_ == nullValue)
*this = Value(arrayValue);
CZString key(index);
- ObjectValues::iterator it = value_.map_->lower_bound(key);
- if (it != value_.map_->end() && (*it).first == key)
+ ObjectValues::iterator it = this->value_.map_->lower_bound(key);
+ if (it != this->value_.map_->end() && (*it).first == key)
return (*it).second;
ObjectValues::value_type defaultValue(key, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
+ it = this->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 (type_ == nullValue)
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
+ if (this->type_ == nullValue)
return nullSingleton();
CZString key(index);
- ObjectValues::const_iterator it = value_.map_->find(key);
- if (it == value_.map_->end())
+ ObjectValues::const_iterator it = this->value_.map_->find(key);
+ if (it == this->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) {
- type_ = vtype;
- allocated_ = allocated;
- comments_ = 0;
- start_ = 0;
- limit_ = 0;
+void Value::initBasic(ValueType vtype, bool allocated)
+{
+ this->type_ = vtype;
+ this->allocated_ = allocated;
+ this->comments_ = 0;
+ this->start_ = 0;
+ this->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 (type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(): requires objectValue");
+ if (this->type_ == nullValue)
*this = Value(objectValue);
- 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)
+ 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)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
+ it = this->value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}
@@ -1074,198 +1219,223 @@ 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 (type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(key, end): requires objectValue");
+ if (this->type_ == nullValue)
*this = Value(objectValue);
- 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)
+ 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)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
+ it = this->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 < size(); }
+bool Value::isValidIndex(ArrayIndex index) const
+{
+ return index < this->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 (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;
+ 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;
return &(*it).second;
}
const Value& Value::operator[](const char* key) const
{
- Value const* found = find(key, key + strlen(key));
- if (!found) return nullSingleton();
+ Value const* found = this->find(key, key + strlen(key));
+ if (!found)
+ return nullSingleton();
return *found;
}
Value const& Value::operator[](JSONCPP_STRING const& key) const
{
- Value const* found = find(key.data(), key.data() + key.length());
- if (!found) return nullSingleton();
+ Value const* found = this->find(key.data(), key.data() + key.length());
+ if (!found)
+ return nullSingleton();
return *found;
}
-Value& Value::operator[](const char* key) {
- return resolveReference(key, key + strlen(key));
+Value& Value::operator[](const char* key)
+{
+ return this->resolveReference(key, key + strlen(key));
}
-Value& Value::operator[](const JSONCPP_STRING& key) {
- return resolveReference(key.data(), key.data() + key.length());
+Value& Value::operator[](const JSONCPP_STRING& key)
+{
+ return this->resolveReference(key.data(), key.data() + key.length());
}
-Value& Value::operator[](const StaticString& key) {
- return resolveReference(key.c_str());
+Value& Value::operator[](const StaticString& key)
+{
+ return this->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)[size()] = value; }
+Value& Value::append(const Value& value)
+{
+ return (*this)[this->size()] = value;
+}
#if JSON_HAS_RVALUE_REFERENCES
- Value& Value::append(Value&& value) { return (*this)[size()] = value; }
+Value& Value::append(Value&& value)
+{
+ return (*this)[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 = find(key, cend);
+ Value const* found = this->find(key, cend);
return !found ? defaultValue : *found;
}
Value Value::get(char const* key, Value const& defaultValue) const
{
- return get(key, key + strlen(key), defaultValue);
+ return this->get(key, key + strlen(key), defaultValue);
}
Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
{
- return get(key.data(), key.data() + key.length(), defaultValue);
+ return this->get(key.data(), key.data() + key.length(), defaultValue);
}
-
bool Value::removeMember(const char* key, const char* cend, Value* removed)
{
- if (type_ != objectValue) {
+ if (this->type_ != objectValue) {
return false;
}
- CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
- ObjectValues::iterator it = value_.map_->find(actualKey);
- if (it == value_.map_->end())
+ CZString actualKey(key, static_cast<unsigned>(cend - key),
+ CZString::noDuplication);
+ ObjectValues::iterator it = this->value_.map_->find(actualKey);
+ if (it == this->value_.map_->end())
return false;
*removed = it->second;
- value_.map_->erase(it);
+ this->value_.map_->erase(it);
return true;
}
bool Value::removeMember(const char* key, Value* removed)
{
- return removeMember(key, key + strlen(key), removed);
+ return this->removeMember(key, key + strlen(key), removed);
}
bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
{
- return removeMember(key.data(), key.data() + key.length(), removed);
+ return this->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 (type_ == nullValue)
+ if (this->type_ == nullValue)
return nullSingleton();
- Value removed; // null
- removeMember(key, key + strlen(key), &removed);
+ Value removed; // null
+ this->removeMember(key, key + strlen(key), &removed);
return removed; // still null if removeMember() did nothing
}
Value Value::removeMember(const JSONCPP_STRING& key)
{
- return removeMember(key.c_str());
+ return this->removeMember(key.c_str());
}
-bool Value::removeIndex(ArrayIndex index, Value* removed) {
- if (type_ != arrayValue) {
+bool Value::removeIndex(ArrayIndex index, Value* removed)
+{
+ if (this->type_ != arrayValue) {
return false;
}
CZString key(index);
- ObjectValues::iterator it = value_.map_->find(key);
- if (it == value_.map_->end()) {
+ ObjectValues::iterator it = this->value_.map_->find(key);
+ if (it == this->value_.map_->end()) {
return false;
}
*removed = it->second;
- ArrayIndex oldSize = size();
+ ArrayIndex oldSize = this->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);
- (*value_.map_)[keey] = (*this)[i + 1];
+ (*this->value_.map_)[keey] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
- ObjectValues::iterator itLast = value_.map_->find(keyLast);
- value_.map_->erase(itLast);
+ ObjectValues::iterator itLast = this->value_.map_->find(keyLast);
+ this->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 = find(key, cend);
+ Value const* value = this->find(key, cend);
return NULL != value;
}
bool Value::isMember(char const* key) const
{
- return isMember(key, key + strlen(key));
+ return this->isMember(key, key + strlen(key));
}
bool Value::isMember(JSONCPP_STRING const& key) const
{
- return isMember(key.data(), key.data() + key.length());
+ return this->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 (type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::getMemberNames(), value must be objectValue");
+ if (this->type_ == nullValue)
return Value::Members();
Members members;
- members.reserve(value_.map_->size());
- ObjectValues::const_iterator it = value_.map_->begin();
- ObjectValues::const_iterator itEnd = value_.map_->end();
+ members.reserve(this->value_.map_->size());
+ ObjectValues::const_iterator it = this->value_.map_->begin();
+ ObjectValues::const_iterator itEnd = this->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;
}
@@ -1277,8 +1447,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();
//}
@@ -1295,99 +1465,114 @@ 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 type_ == nullValue; }
+bool Value::isNull() const
+{
+ return this->type_ == nullValue;
+}
-bool Value::isBool() const { return type_ == booleanValue; }
+bool Value::isBool() const
+{
+ return this->type_ == booleanValue;
+}
-bool Value::isInt() const {
- switch (type_) {
- case intValue:
+bool Value::isInt() const
+{
+ switch (this->type_) {
+ case intValue:
#if defined(JSON_HAS_INT64)
- return value_.int_ >= minInt && value_.int_ <= maxInt;
+ return this->value_.int_ >= minInt && this->value_.int_ <= maxInt;
#else
- return true;
+ return true;
#endif
- case uintValue:
- return value_.uint_ <= UInt(maxInt);
- case realValue:
- return value_.real_ >= minInt && value_.real_ <= maxInt &&
- IsIntegral(value_.real_);
- default:
- break;
+ 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;
}
return false;
}
-bool Value::isUInt() const {
- switch (type_) {
- case intValue:
+bool Value::isUInt() const
+{
+ switch (this->type_) {
+ case intValue:
#if defined(JSON_HAS_INT64)
- return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+ return this->value_.int_ >= 0 &&
+ LargestUInt(this->value_.int_) <= LargestUInt(maxUInt);
#else
- return value_.int_ >= 0;
+ return value_.int_ >= 0;
#endif
- case uintValue:
+ case uintValue:
#if defined(JSON_HAS_INT64)
- return value_.uint_ <= maxUInt;
+ return this->value_.uint_ <= maxUInt;
#else
- return true;
+ return true;
#endif
- case realValue:
- return value_.real_ >= 0 && value_.real_ <= maxUInt &&
- IsIntegral(value_.real_);
- default:
- break;
+ case realValue:
+ return this->value_.real_ >= 0 && this->value_.real_ <= maxUInt &&
+ IsIntegral(this->value_.real_);
+ default:
+ break;
}
return false;
}
-bool Value::isInt64() const {
+bool Value::isInt64() const
+{
#if defined(JSON_HAS_INT64)
- 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;
+ 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;
}
#endif // JSON_HAS_INT64
return false;
}
-bool Value::isUInt64() const {
+bool Value::isUInt64() const
+{
#if defined(JSON_HAS_INT64)
- 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;
+ 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;
}
#endif // JSON_HAS_INT64
return false;
}
-bool Value::isIntegral() const {
- switch (type_) {
+bool Value::isIntegral() const
+{
+ switch (this->type_) {
case intValue:
case uintValue:
return true;
@@ -1396,9 +1581,12 @@ 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 value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
+ return this->value_.real_ >= double(minInt64) &&
+ this->value_.real_ < maxUInt64AsDouble &&
+ IsIntegral(this->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;
@@ -1406,53 +1594,89 @@ bool Value::isIntegral() const {
return false;
}
-bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
+bool Value::isDouble() const
+{
+ return this->type_ == intValue || this->type_ == uintValue ||
+ this->type_ == realValue;
+}
-bool Value::isNumeric() const { return isDouble(); }
+bool Value::isNumeric() const
+{
+ return this->isDouble();
+}
-bool Value::isString() const { return type_ == stringValue; }
+bool Value::isString() const
+{
+ return this->type_ == stringValue;
+}
-bool Value::isArray() const { return type_ == arrayValue; }
+bool Value::isArray() const
+{
+ return this->type_ == arrayValue;
+}
-bool Value::isObject() const { return type_ == objectValue; }
+bool Value::isObject() const
+{
+ return this->type_ == objectValue;
+}
-void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
- if (!comments_)
- comments_ = new CommentInfo[numberOfCommentPlacement];
- if ((len > 0) && (comment[len-1] == '\n')) {
+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')) {
// Always discard trailing newline, to aid indentation.
len -= 1;
}
- comments_[placement].setComment(comment, len);
+ this->comments_[placement].setComment(comment, len);
}
-void Value::setComment(const char* comment, CommentPlacement placement) {
- setComment(comment, strlen(comment), placement);
+void Value::setComment(const char* comment, CommentPlacement placement)
+{
+ this->setComment(comment, strlen(comment), placement);
}
-void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
- setComment(comment.c_str(), comment.length(), placement);
+void Value::setComment(const JSONCPP_STRING& comment,
+ CommentPlacement placement)
+{
+ this->setComment(comment.c_str(), comment.length(), placement);
}
-bool Value::hasComment(CommentPlacement placement) const {
- return comments_ != 0 && comments_[placement].comment_ != 0;
+bool Value::hasComment(CommentPlacement placement) const
+{
+ return this->comments_ != 0 && this->comments_[placement].comment_ != 0;
}
-JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
- if (hasComment(placement))
- return comments_[placement].comment_;
+JSONCPP_STRING Value::getComment(CommentPlacement placement) const
+{
+ if (this->hasComment(placement))
+ return this->comments_[placement].comment_;
return "";
}
-void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
+void Value::setOffsetStart(ptrdiff_t start)
+{
+ this->start_ = start;
+}
-void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
+void Value::setOffsetLimit(ptrdiff_t limit)
+{
+ this->limit_ = limit;
+}
-ptrdiff_t Value::getOffsetStart() const { return start_; }
+ptrdiff_t Value::getOffsetStart() const
+{
+ return this->start_;
+}
-ptrdiff_t Value::getOffsetLimit() const { return limit_; }
+ptrdiff_t Value::getOffsetLimit() const
+{
+ return this->limit_;
+}
-JSONCPP_STRING Value::toStyledString() const {
+JSONCPP_STRING Value::toStyledString() const
+{
StreamWriterBuilder builder;
JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
@@ -1462,54 +1686,58 @@ JSONCPP_STRING Value::toStyledString() const {
return out;
}
-Value::const_iterator Value::begin() const {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->begin());
- break;
- default:
- break;
+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;
}
return const_iterator();
}
-Value::const_iterator Value::end() const {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->end());
- break;
- default:
- break;
+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;
}
return const_iterator();
}
-Value::iterator Value::begin() {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->begin());
- break;
- default:
- break;
+Value::iterator Value::begin()
+{
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ if (this->value_.map_)
+ return iterator(this->value_.map_->begin());
+ break;
+ default:
+ break;
}
return iterator();
}
-Value::iterator Value::end() {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->end());
- break;
- default:
- break;
+Value::iterator Value::end()
+{
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ if (this->value_.map_)
+ return iterator(this->value_.map_->end());
+ break;
+ default:
+ break;
}
return iterator();
}
@@ -1517,26 +1745,41 @@ 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);
@@ -1544,10 +1787,11 @@ Path::Path(const JSONCPP_STRING& path,
in.push_back(&a3);
in.push_back(&a4);
in.push_back(&a5);
- makePath(path, in);
+ this->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();
@@ -1555,17 +1799,17 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
if (*current == '[') {
++current;
if (*current == '%')
- addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+ this->addPathInArg(path, in, itInArg, PathArgument::kindIndex);
else {
ArrayIndex index = 0;
for (; current != end && *current >= '0' && *current <= '9'; ++current)
index = index * 10 + ArrayIndex(*current - '0');
- args_.push_back(index);
+ this->args_.push_back(index);
}
if (current == end || *++current != ']')
- invalidPath(path, int(current - path.c_str()));
+ this->invalidPath(path, int(current - path.c_str()));
} else if (*current == '%') {
- addPathInArg(path, in, itInArg, PathArgument::kindKey);
+ this->addPathInArg(path, in, itInArg, PathArgument::kindKey);
++current;
} else if (*current == '.' || *current == ']') {
++current;
@@ -1573,31 +1817,34 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
const char* beginName = current;
while (current != end && !strchr("[.", *current))
++current;
- args_.push_back(JSONCPP_STRING(beginName, current));
+ this->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 {
- args_.push_back(**itInArg++);
+ this->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 = args_.begin(); it != args_.end(); ++it) {
+ for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
+ ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
@@ -1621,9 +1868,11 @@ 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 = args_.begin(); it != args_.end(); ++it) {
+ for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
+ ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_))
@@ -1640,9 +1889,11 @@ 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 = args_.begin(); it != args_.end(); ++it) {
+ for (Args::const_iterator it = this->args_.begin(); it != this->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 fc8650598..803cfab01 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
@@ -1,111 +1,115 @@
// 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 <math.h>
+# define isfinite finite
+# endif
+# endif
#else
-#include <cmath>
-#if !(defined(__QNXNTO__)) // QNX already defines isfinite
-#define isfinite std::isfinite
-#endif
+# 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
+# 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
#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 {
@@ -113,10 +117,11 @@ 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;
@@ -124,17 +129,19 @@ 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) {
@@ -150,7 +157,8 @@ 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);
@@ -160,18 +168,22 @@ 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];
@@ -187,7 +199,8 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
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");
}
@@ -195,11 +208,14 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
} 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);
@@ -207,11 +223,18 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
}
}
-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...
@@ -222,51 +245,50 @@ 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 += "\"";
@@ -274,7 +296,8 @@ 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;
@@ -288,7 +311,8 @@ 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...
@@ -298,53 +322,51 @@ 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 += "\"";
@@ -353,80 +375,98 @@ 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() { yamlCompatiblityEnabled_ = true; }
+void FastWriter::enableYAMLCompatibility()
+{
+ this->yamlCompatiblityEnabled_ = true;
+}
-void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
+void FastWriter::dropNullPlaceholders()
+{
+ this->dropNullPlaceholders_ = true;
+}
-void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
+void FastWriter::omitEndingLineFeed()
+{
+ this->omitEndingLineFeed_ = true;
+}
-JSONCPP_STRING FastWriter::write(const Value& root) {
- document_.clear();
- writeValue(root);
- if (!omitEndingLineFeed_)
- document_ += "\n";
- return document_;
+JSONCPP_STRING FastWriter::write(const Value& root)
+{
+ this->document_.clear();
+ this->writeValue(root);
+ if (!this->omitEndingLineFeed_)
+ this->document_ += "\n";
+ return this->document_;
}
-void FastWriter::writeValue(const Value& value) {
+void FastWriter::writeValue(const Value& value)
+{
switch (value.type()) {
- 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]);
- }
- 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]);
+ 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;
}
- document_ += '}';
- } break;
+ 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;
}
}
@@ -434,454 +474,498 @@ 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) {
- document_.clear();
- addChildValues_ = false;
- indentString_.clear();
- writeCommentBeforeValue(root);
- writeValue(root);
- writeCommentAfterValueOnSameLine(root);
- document_ += "\n";
- return document_;
+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_;
}
-void StyledWriter::writeValue(const Value& value) {
+void StyledWriter::writeValue(const Value& value)
+{
switch (value.type()) {
- 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;
+ 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);
}
- document_ += ',';
- writeCommentAfterValueOnSameLine(childValue);
+ this->unindent();
+ this->writeWithIndent("}");
}
- unindent();
- writeWithIndent("}");
- }
- } break;
+ } break;
}
}
-void StyledWriter::writeArrayValue(const Value& value) {
+void StyledWriter::writeArrayValue(const Value& value)
+{
unsigned size = value.size();
if (size == 0)
- pushValue("[]");
+ this->pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = this->isMultineArray(value);
if (isArrayMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
+ this->writeWithIndent("[");
+ this->indent();
+ bool hasChildValue = !this->childValues_.empty();
unsigned index = 0;
for (;;) {
const Value& childValue = value[index];
- writeCommentBeforeValue(childValue);
+ this->writeCommentBeforeValue(childValue);
if (hasChildValue)
- writeWithIndent(childValues_[index]);
+ this->writeWithIndent(this->childValues_[index]);
else {
- writeIndent();
- writeValue(childValue);
+ this->writeIndent();
+ this->writeValue(childValue);
}
if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
+ this->writeCommentAfterValueOnSameLine(childValue);
break;
}
- document_ += ',';
- writeCommentAfterValueOnSameLine(childValue);
+ this->document_ += ',';
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- unindent();
- writeWithIndent("]");
+ this->unindent();
+ this->writeWithIndent("]");
} else // output on a single line
{
- assert(childValues_.size() == size);
- document_ += "[ ";
+ assert(this->childValues_.size() == size);
+ this->document_ += "[ ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- document_ += ", ";
- document_ += childValues_[index];
+ this->document_ += ", ";
+ this->document_ += this->childValues_[index];
}
- document_ += " ]";
+ this->document_ += " ]";
}
}
}
-bool StyledWriter::isMultineArray(const Value& value) {
+bool StyledWriter::isMultineArray(const Value& value)
+{
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
+ bool isMultiLine = size * 3 >= this->rightMargin_;
+ this->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
{
- childValues_.reserve(size);
- addChildValues_ = true;
+ this->childValues_.reserve(size);
+ this->addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
- if (hasCommentForValue(value[index])) {
+ if (this->hasCommentForValue(value[index])) {
isMultiLine = true;
}
- writeValue(value[index]);
- lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ this->writeValue(value[index]);
+ lineLength +=
+ static_cast<ArrayIndex>(this->childValues_[index].length());
}
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ this->addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
}
return isMultiLine;
}
-void StyledWriter::pushValue(const JSONCPP_STRING& value) {
- if (addChildValues_)
- childValues_.push_back(value);
+void StyledWriter::pushValue(const JSONCPP_STRING& value)
+{
+ if (this->addChildValues_)
+ this->childValues_.push_back(value);
else
- document_ += value;
+ this->document_ += value;
}
-void StyledWriter::writeIndent() {
- if (!document_.empty()) {
- char last = document_[document_.length() - 1];
+void StyledWriter::writeIndent()
+{
+ if (!this->document_.empty()) {
+ char last = this->document_[this->document_.length() - 1];
if (last == ' ') // already indented
return;
if (last != '\n') // Comments may add new-line
- document_ += '\n';
+ this->document_ += '\n';
}
- document_ += indentString_;
+ this->document_ += this->indentString_;
}
-void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
- writeIndent();
- document_ += value;
+void StyledWriter::writeWithIndent(const JSONCPP_STRING& value)
+{
+ this->writeIndent();
+ this->document_ += value;
}
-void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
+void StyledWriter::indent()
+{
+ this->indentString_ += JSONCPP_STRING(this->indentSize_, ' ');
+}
-void StyledWriter::unindent() {
- assert(indentString_.size() >= indentSize_);
- indentString_.resize(indentString_.size() - indentSize_);
+void StyledWriter::unindent()
+{
+ assert(this->indentString_.size() >= this->indentSize_);
+ this->indentString_.resize(this->indentString_.size() - this->indentSize_);
}
-void StyledWriter::writeCommentBeforeValue(const Value& root) {
+void StyledWriter::writeCommentBeforeValue(const Value& root)
+{
if (!root.hasComment(commentBefore))
return;
- document_ += "\n";
- writeIndent();
+ this->document_ += "\n";
+ this->writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- document_ += *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
- writeIndent();
+ this->document_ += *iter;
+ if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
+ this->writeIndent();
++iter;
}
// Comments are stripped of trailing newlines, so add one here
- document_ += "\n";
+ this->document_ += "\n";
}
-void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root)
+{
if (root.hasComment(commentAfterOnSameLine))
- document_ += " " + root.getComment(commentAfterOnSameLine);
+ this->document_ += " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- document_ += "\n";
- document_ += root.getComment(commentAfter);
- document_ += "\n";
+ this->document_ += "\n";
+ this->document_ += root.getComment(commentAfter);
+ this->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) {
- 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) {
+ : 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)
+{
switch (value.type()) {
- 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;
+ 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);
}
- *document_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ this->unindent();
+ this->writeWithIndent("}");
}
- unindent();
- writeWithIndent("}");
- }
- } break;
+ } break;
}
}
-void StyledStreamWriter::writeArrayValue(const Value& value) {
+void StyledStreamWriter::writeArrayValue(const Value& value)
+{
unsigned size = value.size();
if (size == 0)
- pushValue("[]");
+ this->pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = this->isMultineArray(value);
if (isArrayMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
+ this->writeWithIndent("[");
+ this->indent();
+ bool hasChildValue = !this->childValues_.empty();
unsigned index = 0;
for (;;) {
const Value& childValue = value[index];
- writeCommentBeforeValue(childValue);
+ this->writeCommentBeforeValue(childValue);
if (hasChildValue)
- writeWithIndent(childValues_[index]);
+ this->writeWithIndent(this->childValues_[index]);
else {
- if (!indented_) writeIndent();
- indented_ = true;
- writeValue(childValue);
- indented_ = false;
+ if (!this->indented_)
+ this->writeIndent();
+ this->indented_ = true;
+ this->writeValue(childValue);
+ this->indented_ = false;
}
if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
+ this->writeCommentAfterValueOnSameLine(childValue);
break;
}
- *document_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ *this->document_ << ",";
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- unindent();
- writeWithIndent("]");
+ this->unindent();
+ this->writeWithIndent("]");
} else // output on a single line
{
- assert(childValues_.size() == size);
- *document_ << "[ ";
+ assert(this->childValues_.size() == size);
+ *this->document_ << "[ ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- *document_ << ", ";
- *document_ << childValues_[index];
+ *this->document_ << ", ";
+ *this->document_ << this->childValues_[index];
}
- *document_ << " ]";
+ *this->document_ << " ]";
}
}
}
-bool StyledStreamWriter::isMultineArray(const Value& value) {
+bool StyledStreamWriter::isMultineArray(const Value& value)
+{
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
+ bool isMultiLine = size * 3 >= this->rightMargin_;
+ this->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
{
- childValues_.reserve(size);
- addChildValues_ = true;
+ this->childValues_.reserve(size);
+ this->addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
- if (hasCommentForValue(value[index])) {
+ if (this->hasCommentForValue(value[index])) {
isMultiLine = true;
}
- writeValue(value[index]);
- lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ this->writeValue(value[index]);
+ lineLength +=
+ static_cast<ArrayIndex>(this->childValues_[index].length());
}
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ this->addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
}
return isMultiLine;
}
-void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
- if (addChildValues_)
- childValues_.push_back(value);
+void StyledStreamWriter::pushValue(const JSONCPP_STRING& value)
+{
+ if (this->addChildValues_)
+ this->childValues_.push_back(value);
else
- *document_ << value;
+ *this->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_.
- *document_ << '\n' << indentString_;
+ *this->document_ << '\n' << this->indentString_;
}
-void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
- if (!indented_) writeIndent();
- *document_ << value;
- indented_ = false;
+void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value)
+{
+ if (!this->indented_)
+ this->writeIndent();
+ *this->document_ << value;
+ this->indented_ = false;
}
-void StyledStreamWriter::indent() { indentString_ += indentation_; }
+void StyledStreamWriter::indent()
+{
+ this->indentString_ += this->indentation_;
+}
-void StyledStreamWriter::unindent() {
- assert(indentString_.size() >= indentation_.size());
- indentString_.resize(indentString_.size() - indentation_.size());
+void StyledStreamWriter::unindent()
+{
+ assert(this->indentString_.size() >= this->indentation_.size());
+ this->indentString_.resize(this->indentString_.size() -
+ this->indentation_.size());
}
-void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
+void StyledStreamWriter::writeCommentBeforeValue(const Value& root)
+{
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
+ if (!this->indented_)
+ this->writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- *document_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ *this->document_ << *iter;
+ if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would include newline
- *document_ << indentString_;
+ *this->document_ << this->indentString_;
++iter;
}
- indented_ = false;
+ this->indented_ = false;
}
-void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root)
+{
if (root.hasComment(commentAfterOnSameLine))
- *document_ << ' ' << root.getComment(commentAfterOnSameLine);
+ *this->document_ << ' ' << root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- writeIndent();
- *document_ << root.getComment(commentAfter);
+ this->writeIndent();
+ *this->document_ << root.getComment(commentAfter);
}
- indented_ = false;
+ this->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);
@@ -911,13 +995,10 @@ 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)
@@ -932,247 +1013,276 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
}
int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
{
- sout_ = sout;
- addChildValues_ = false;
- indented_ = true;
- indentString_.clear();
- writeCommentBeforeValue(root);
- if (!indented_) writeIndent();
- indented_ = true;
- writeValue(root);
- writeCommentAfterValueOnSameLine(root);
- *sout_ << endingLineFeedSymbol_;
- sout_ = NULL;
+ 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;
return 0;
}
-void BuiltStyledStreamWriter::writeValue(Value const& value) {
+void BuiltStyledStreamWriter::writeValue(Value const& value)
+{
switch (value.type()) {
- 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;
+ 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);
}
- *sout_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ this->unindent();
+ this->writeWithIndent("}");
}
- unindent();
- writeWithIndent("}");
- }
- } break;
+ } break;
}
}
-void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value)
+{
unsigned size = value.size();
if (size == 0)
- pushValue("[]");
+ this->pushValue("[]");
else {
- bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+ bool isMultiLine =
+ (this->cs_ == CommentStyle::All) || this->isMultineArray(value);
if (isMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
+ this->writeWithIndent("[");
+ this->indent();
+ bool hasChildValue = !this->childValues_.empty();
unsigned index = 0;
for (;;) {
Value const& childValue = value[index];
- writeCommentBeforeValue(childValue);
+ this->writeCommentBeforeValue(childValue);
if (hasChildValue)
- writeWithIndent(childValues_[index]);
+ this->writeWithIndent(this->childValues_[index]);
else {
- if (!indented_) writeIndent();
- indented_ = true;
- writeValue(childValue);
- indented_ = false;
+ if (!this->indented_)
+ this->writeIndent();
+ this->indented_ = true;
+ this->writeValue(childValue);
+ this->indented_ = false;
}
if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
+ this->writeCommentAfterValueOnSameLine(childValue);
break;
}
- *sout_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ *this->sout_ << ",";
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- unindent();
- writeWithIndent("]");
+ this->unindent();
+ this->writeWithIndent("]");
} else // output on a single line
{
- assert(childValues_.size() == size);
- *sout_ << "[";
- if (!indentation_.empty()) *sout_ << " ";
+ assert(this->childValues_.size() == size);
+ *this->sout_ << "[";
+ if (!this->indentation_.empty())
+ *this->sout_ << " ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- *sout_ << ((!indentation_.empty()) ? ", " : ",");
- *sout_ << childValues_[index];
+ *this->sout_ << ((!this->indentation_.empty()) ? ", " : ",");
+ *this->sout_ << this->childValues_[index];
}
- if (!indentation_.empty()) *sout_ << " ";
- *sout_ << "]";
+ if (!this->indentation_.empty())
+ *this->sout_ << " ";
+ *this->sout_ << "]";
}
}
}
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+bool BuiltStyledStreamWriter::isMultineArray(Value const& value)
+{
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
+ bool isMultiLine = size * 3 >= this->rightMargin_;
+ this->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
{
- childValues_.reserve(size);
- addChildValues_ = true;
+ this->childValues_.reserve(size);
+ this->addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
- writeValue(value[index]);
- lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ this->writeValue(value[index]);
+ lineLength +=
+ static_cast<ArrayIndex>(this->childValues_[index].length());
}
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ this->addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
}
return isMultiLine;
}
-void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
- if (addChildValues_)
- childValues_.push_back(value);
+void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value)
+{
+ if (this->addChildValues_)
+ this->childValues_.push_back(value);
else
- *sout_ << value;
+ *this->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 (!indentation_.empty()) {
+ if (!this->indentation_.empty()) {
// In this case, drop newlines too.
- *sout_ << '\n' << indentString_;
+ *this->sout_ << '\n' << this->indentString_;
}
}
-void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
- if (!indented_) writeIndent();
- *sout_ << value;
- indented_ = false;
+void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value)
+{
+ if (!this->indented_)
+ this->writeIndent();
+ *this->sout_ << value;
+ this->indented_ = false;
}
-void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
+void BuiltStyledStreamWriter::indent()
+{
+ this->indentString_ += this->indentation_;
+}
-void BuiltStyledStreamWriter::unindent() {
- assert(indentString_.size() >= indentation_.size());
- indentString_.resize(indentString_.size() - indentation_.size());
+void BuiltStyledStreamWriter::unindent()
+{
+ assert(this->indentString_.size() >= this->indentation_.size());
+ this->indentString_.resize(this->indentString_.size() -
+ this->indentation_.size());
}
-void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root)
+{
+ if (this->cs_ == CommentStyle::None)
+ return;
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
+ if (!this->indented_)
+ this->writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- *sout_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ *this->sout_ << *iter;
+ if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would write extra newline
- *sout_ << indentString_;
+ *this->sout_ << this->indentString_;
++iter;
}
- indented_ = false;
+ this->indented_ = false;
}
-void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
+ Value const& root)
+{
+ if (this->cs_ == CommentStyle::None)
+ return;
if (root.hasComment(commentAfterOnSameLine))
- *sout_ << " " + root.getComment(commentAfterOnSameLine);
+ *this->sout_ << " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- writeIndent();
- *sout_ << root.getComment(commentAfter);
+ this->writeIndent();
+ *this->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(&settings_);
+ setDefaults(&this->settings_);
}
StreamWriterBuilder::~StreamWriterBuilder()
-{}
+{
+}
StreamWriter* StreamWriterBuilder::newStreamWriter() const
{
- 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();
+ 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();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
cs = CommentStyle::All;
@@ -1191,11 +1301,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)
{
@@ -1210,23 +1320,24 @@ 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 = settings_.getMemberNames();
+ Value::Members keys = this->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] = settings_[key];
+ inv[key] = this->settings_[key];
}
}
return 0u == inv.size();
}
Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
{
- return settings_[key];
+ return this->settings_[key];
}
// static
void StreamWriterBuilder::setDefaults(Json::Value* settings)
@@ -1241,14 +1352,17 @@ 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 bfcaf30bb..689d98afb 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
@@ -1475,9 +1475,15 @@ CHECK_C_SOURCE_COMPILES(
"#include <sys/sysmacros.h>\nint main() { return major(256); }"
MAJOR_IN_SYSMACROS)
+CMAKE_PUSH_CHECK_STATE()
+SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES})
+SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR})
+
CHECK_C_SOURCE_COMPILES(
"#include <lzma.h>\n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}"
- HAVE_LZMA_STREAM_ENCODER_MT)
+HAVE_LZMA_STREAM_ENCODER_MT)
+
+CMAKE_POP_CHECK_STATE()
IF(HAVE_STRERROR_R)
SET(HAVE_DECL_STRERROR_R 1)
diff --git a/Utilities/cmlibarchive/libarchive/archive_random.c b/Utilities/cmlibarchive/libarchive/archive_random.c
index 9d1aa493f..65ea69157 100644
--- a/Utilities/cmlibarchive/libarchive/archive_random.c
+++ b/Utilities/cmlibarchive/libarchive/archive_random.c
@@ -173,7 +173,7 @@ arc4_init(void)
}
static inline void
-arc4_addrandom(uint8_t *dat, int datlen)
+arc4_addrandom(u_char *dat, int datlen)
{
int n;
uint8_t si;
@@ -196,7 +196,7 @@ arc4_stir(void)
struct {
struct timeval tv;
pid_t pid;
- uint8_t rnd[KEYSIZE];
+ u_char rnd[KEYSIZE];
} rdat;
if (!rs_initialized) {
@@ -216,7 +216,7 @@ arc4_stir(void)
/* We'll just take whatever was on the stack too... */
}
- arc4_addrandom((uint8_t *)&rdat, KEYSIZE);
+ arc4_addrandom((u_char *)&rdat, KEYSIZE);
/*
* Discard early keystream, as per recommendations in:
@@ -258,7 +258,7 @@ arc4_getbyte(void)
static void
arc4random_buf(void *_buf, size_t n)
{
- uint8_t *buf = (uint8_t *)_buf;
+ u_char *buf = (u_char *)_buf;
_ARC4_LOCK();
arc4_stir_if_needed();
while (n--) {
diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt
index 6b6fae63c..32a14dc23 100644
--- a/Utilities/cmliblzma/CMakeLists.txt
+++ b/Utilities/cmliblzma/CMakeLists.txt
@@ -148,7 +148,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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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/cmlibrhash/CMakeLists.txt b/Utilities/cmlibrhash/CMakeLists.txt
index 1b025fc7b..37e2399c4 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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 92d241127..f8b47af46 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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/cmnghttp2/CMakeLists.txt b/Utilities/cmnghttp2/CMakeLists.txt
index 3a11acec6..17cc6ddb2 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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 0584c5560..d266af936 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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 4f4f91fe0..323151c08 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)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
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/optional b/Utilities/std/cm/optional
index 9a5d84076..2ebc78c0b 100644
--- a/Utilities/std/cm/optional
+++ b/Utilities/std/cm/optional
@@ -68,16 +68,22 @@ public:
optional& operator=(nullopt_t) noexcept;
optional& operator=(const optional& other);
- optional& operator=(optional&& other) noexcept;
- template <
- typename U = T,
- typename = typename std::enable_if<
- !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
- std::is_constructible<T, U>::value && std::is_assignable<T&, U>::value &&
+ template <typename U = T>
+ typename std::enable_if<std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value,
+ optional&>::type
+ operator=(optional<U>&& other) noexcept;
+
+ template <typename U = T>
+ typename std::enable_if<
+ !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
+ std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value &&
(!std::is_scalar<T>::value ||
- !std::is_same<typename std::decay<U>::type, T>::value)>::type>
- optional& operator=(U&& v);
+ !std::is_same<typename std::decay<U>::type, T>::value),
+ optional&>::type
+ operator=(U&& v);
const T* operator->() const;
T* operator->();
@@ -134,19 +140,24 @@ optional<T> make_optional(Args&&... args)
template <typename T>
optional<T>::optional(nullopt_t) noexcept
+ : optional()
{
}
template <typename T>
optional<T>::optional(const optional& other)
{
- *this = other;
+ if (other.has_value()) {
+ this->emplace(*other);
+ }
}
template <typename T>
optional<T>::optional(optional&& other) noexcept
{
- *this = std::move(other);
+ if (other.has_value()) {
+ this->emplace(std::move(*other));
+ }
}
template <typename T>
@@ -192,7 +203,11 @@ optional<T>& optional<T>::operator=(const optional& other)
}
template <typename T>
-optional<T>& optional<T>::operator=(optional&& other) noexcept
+template <typename U>
+typename std::enable_if<std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value,
+ optional<T>&>::type
+optional<T>::operator=(optional<U>&& other) noexcept
{
if (other.has_value()) {
if (this->has_value()) {
@@ -207,8 +222,15 @@ optional<T>& optional<T>::operator=(optional&& other) noexcept
}
template <typename T>
-template <typename U, typename>
-optional<T>& optional<T>::operator=(U&& v)
+template <typename U>
+typename std::enable_if<
+ !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
+ std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value &&
+ (!std::is_scalar<T>::value ||
+ !std::is_same<typename std::decay<U>::type, T>::value),
+ optional<T>&>::type
+optional<T>::operator=(U&& v)
{
if (this->has_value()) {
this->value() = v;
@@ -291,7 +313,7 @@ bool operator!=(const optional<T>& opt, nullopt_t) noexcept
}
template <typename T>
-bool operator<(const optional<T>& opt, nullopt_t) noexcept
+bool operator<(const optional<T>& /*opt*/, nullopt_t) noexcept
{
return false;
}
@@ -309,7 +331,7 @@ bool operator>(const optional<T>& opt, nullopt_t) noexcept
}
template <typename T>
-bool operator>=(const optional<T>& opt, nullopt_t) noexcept
+bool operator>=(const optional<T>& /*opt*/, nullopt_t) noexcept
{
return true;
}
@@ -333,13 +355,13 @@ bool operator<(nullopt_t, const optional<T>& opt) noexcept
}
template <typename T>
-bool operator<=(nullopt_t, const optional<T>& opt) noexcept
+bool operator<=(nullopt_t, const optional<T>& /*opt*/) noexcept
{
return true;
}
template <typename T>
-bool operator>(nullopt_t, const optional<T>& opt) noexcept
+bool operator>(nullopt_t, const optional<T>& /*opt*/) noexcept
{
return false;
}
diff --git a/bootstrap b/bootstrap
index 7ec36870e..f85d57ee3 100755
--- a/bootstrap
+++ b/bootstrap
@@ -289,10 +289,10 @@ CMAKE_CXX_SOURCES="\
cmBuildCommand \
cmCMakeMinimumRequired \
cmCMakePath \
+ cmCMakePathCommand \
cmCMakePolicyCommand \
cmCPackPropertiesGenerator \
cmCacheManager \
- cmCheckCustomOutputs \
cmCommand \
cmCommandArgumentParserHelper \
cmCommands \
@@ -307,6 +307,7 @@ CMAKE_CXX_SOURCES="\
cmContinueCommand \
cmCoreTryCompile \
cmCreateTestSourceList \
+ cmCryptoHash \
cmCustomCommand \
cmCustomCommandGenerator \
cmCustomCommandLines \
@@ -412,6 +413,8 @@ CMAKE_CXX_SOURCES="\
cmProjectCommand \
cmPropertyDefinition \
cmPropertyMap \
+ cmGccDepfileLexerHelper \
+ cmGccDepfileReader \
cmReturnCommand \
cmRulePlaceholderExpander \
cmRuntimeDependencyArchive \
@@ -452,6 +455,7 @@ CMAKE_CXX_SOURCES="\
cmTest \
cmTestGenerator \
cmTimestamp \
+ cmTransformDepfile \
cmTryCompileCommand \
cmTryRunCommand \
cmUnsetCommand \
@@ -491,6 +495,7 @@ LexerParser_CXX_SOURCES="\
cmCommandArgumentParser \
cmExprLexer \
cmExprParser \
+ cmGccDepfileLexer \
"
LexerParser_C_SOURCES="\
@@ -535,6 +540,18 @@ KWSYS_FILES="\
SystemTools.hxx \
Terminal.h"
+LIBRHASH_C_SOURCES="\
+ librhash/algorithms.c \
+ librhash/byte_order.c \
+ librhash/hex.c \
+ librhash/md5.c \
+ librhash/rhash.c \
+ librhash/sha1.c \
+ librhash/sha256.c \
+ librhash/sha3.c \
+ librhash/sha512.c \
+ "
+
if ${cmake_system_mingw}; then
LIBUV_C_SOURCES="\
src/fs-poll.c \
@@ -927,11 +944,10 @@ while test $# != 0; do
done
# Make sure the generator is valid
-if test "${cmake_bootstrap_generator}" != "MSYS Makefiles" -a \
- "${cmake_bootstrap_generator}" != "Unix Makefiles" -a \
- "${cmake_bootstrap_generator}" != "Ninja"; then
- cmake_error 10 "Invalid generator: ${cmake_bootstrap_generator}"
-fi
+case "${cmake_bootstrap_generator}" in
+ 'MSYS Makefiles'|'Unix Makefiles'|'Ninja') ;;
+ *) cmake_error 10 "Invalid generator: ${cmake_bootstrap_generator}"
+esac
# If verbose, display some information about bootstrap
if test -n "${cmake_verbose}"; then
@@ -1012,7 +1028,6 @@ cmake_ld_flags=${LDFLAGS}
# Add generator-specific files
if test "${cmake_bootstrap_generator}" = "Ninja"; then
CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES} \
- cmCryptoHash \
cmFortranParserImpl \
cmGlobalNinjaGenerator \
cmLocalNinjaGenerator \
@@ -1033,32 +1048,21 @@ if test "${cmake_bootstrap_generator}" = "Ninja"; then
src/lib_json/json_value.cpp \
src/lib_json/json_writer.cpp \
"
-
- LIBRHASH_C_SOURCES="\
- librhash/algorithms.c \
- librhash/byte_order.c \
- librhash/hex.c \
- librhash/md5.c \
- librhash/rhash.c \
- librhash/sha1.c \
- librhash/sha256.c \
- librhash/sha3.c \
- librhash/sha512.c \
- "
else
CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES} \
cmDepends \
cmDependsC \
+ cmDependsCompiler \
cmGlobalUnixMakefileGenerator3 \
cmLocalUnixMakefileGenerator3 \
cmMakefileExecutableTargetGenerator \
cmMakefileLibraryTargetGenerator \
cmMakefileTargetGenerator \
cmMakefileUtilityTargetGenerator \
+ cmProcessTools \
"
JSONCPP_CXX_SOURCES=
- LIBRHASH_C_SOURCES=
fi
# Add Cygwin-specific flags
@@ -1191,8 +1195,8 @@ for std in 11 99 90; do
for compiler in ${cmake_c_compilers}; do
for std_flag in '' $std_flags; do
for thread_flag in '' $thread_flags; do
- echo "Checking whether '${compiler} ${cmake_c_flags} ${std_flag} ${thread_flag}' works." >> cmake_bootstrap.log 2>&1
- if cmake_try_run "${compiler}" "${cmake_c_flags} ${std_flag} ${thread_flag}" \
+ echo "Checking whether '${compiler} ${cmake_c_flags} ${cmake_ld_flags} ${std_flag} ${thread_flag}' works." >> cmake_bootstrap.log 2>&1
+ if cmake_try_run "${compiler}" "${cmake_c_flags} ${cmake_ld_flags} ${std_flag} ${thread_flag}" \
"${TMPFILE}.c" >> cmake_bootstrap.log 2>&1; then
cmake_c_compiler="${compiler}"
cmake_c_flags="${cmake_c_flags} ${std_flag} ${thread_flag}"
@@ -1312,8 +1316,8 @@ for std in 17 14 11; do
for compiler in ${cmake_cxx_compilers}; do
for std_flag in '' $std_flags; do
for thread_flag in '' $thread_flags; do
- echo "Checking whether '${compiler} ${cmake_cxx_flags} ${std_flag} ${thread_flag}' works." >> cmake_bootstrap.log 2>&1
- if cmake_try_run "${compiler}" "${cmake_cxx_flags} ${std_flag} ${thread_flag}" \
+ echo "Checking whether '${compiler} ${cmake_cxx_flags} ${cmake_ld_flags} ${std_flag} ${thread_flag}' works." >> cmake_bootstrap.log 2>&1
+ if cmake_try_run "${compiler}" "${cmake_cxx_flags} ${cmake_ld_flags} ${std_flag} ${thread_flag}" \
"${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then
cmake_cxx_compiler="${compiler}"
cmake_cxx_flags="${cmake_cxx_flags} ${std_flag} ${thread_flag} "
@@ -1341,8 +1345,8 @@ cmake_cxx_features="make_unique filesystem"
for feature in ${cmake_cxx_features}; do
eval "cmake_have_cxx_${feature}=0"
- echo "Checking whether '${cmake_cxx_compiler} ${cmake_cxx_flags}' supports '${feature}'." >> cmake_bootstrap.log 2>&1
- if cmake_try_run "${cmake_cxx_compiler}" "${cmake_cxx_flags}" \
+ echo "Checking whether '${cmake_cxx_compiler} ${cmake_cxx_flags} ${cmake_ld_flags}' supports '${feature}'." >> cmake_bootstrap.log 2>&1
+ if cmake_try_run "${cmake_cxx_compiler}" "${cmake_cxx_flags} ${cmake_ld_flags}" \
"${cmake_source_dir}/Source/Checks/cm_cxx_${feature}.cxx" >> cmake_bootstrap.log 2>&1; then
eval "cmake_have_cxx_${feature}=1"
fi
@@ -1449,7 +1453,7 @@ KWSYS_CXX_HAS_UTIMES=0
KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP=1
if cmake_try_run "${cmake_cxx_compiler}" \
- "${cmake_cxx_flags} -DTEST_KWSYS_CXX_HAS_SETENV" \
+ "${cmake_cxx_flags} ${cmake_ld_flags} -DTEST_KWSYS_CXX_HAS_SETENV" \
"${cmake_source_dir}/Source/kwsys/kwsysPlatformTestsCXX.cxx" >> cmake_bootstrap.log 2>&1; then
KWSYS_CXX_HAS_SETENV=1
echo "${cmake_cxx_compiler} has setenv"
@@ -1458,7 +1462,7 @@ else
fi
if cmake_try_run "${cmake_cxx_compiler}" \
- "${cmake_cxx_flags} -DTEST_KWSYS_CXX_HAS_UNSETENV" \
+ "${cmake_cxx_flags} ${cmake_ld_flags} -DTEST_KWSYS_CXX_HAS_UNSETENV" \
"${cmake_source_dir}/Source/kwsys/kwsysPlatformTestsCXX.cxx" >> cmake_bootstrap.log 2>&1; then
KWSYS_CXX_HAS_UNSETENV=1
echo "${cmake_cxx_compiler} has unsetenv"
@@ -1467,7 +1471,7 @@ else
fi
if cmake_try_run "${cmake_cxx_compiler}" \
- "${cmake_cxx_flags} -DTEST_KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H" \
+ "${cmake_cxx_flags} ${cmake_ld_flags} -DTEST_KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H" \
"${cmake_source_dir}/Source/kwsys/kwsysPlatformTestsCXX.cxx" >> cmake_bootstrap.log 2>&1; then
KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=1
echo "${cmake_cxx_compiler} has environ in stdlib.h"
@@ -1476,7 +1480,7 @@ else
fi
if cmake_try_run "${cmake_cxx_compiler}" \
- "${cmake_cxx_flags} -DTEST_KWSYS_STL_HAS_WSTRING" \
+ "${cmake_cxx_flags} ${cmake_ld_flags} -DTEST_KWSYS_STL_HAS_WSTRING" \
"${cmake_source_dir}/Source/kwsys/kwsysPlatformTestsCXX.cxx" >> cmake_bootstrap.log 2>&1; then
KWSYS_STL_HAS_WSTRING=1
echo "${cmake_cxx_compiler} has stl wstring"
@@ -1485,7 +1489,7 @@ else
fi
if cmake_try_run "${cmake_cxx_compiler}" \
- "${cmake_cxx_flags} -DTEST_KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H" \
+ "${cmake_cxx_flags} ${cmake_ld_flags} -DTEST_KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H" \
"${cmake_source_dir}/Source/kwsys/kwsysPlatformTestsCXX.cxx" >> cmake_bootstrap.log 2>&1; then
KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H=1
echo "${cmake_cxx_compiler} has <ext/stdio_filebuf.h>"
@@ -1628,17 +1632,17 @@ if test "x${bootstrap_system_libuv}" = "x"; then
objs="${objs} uv-`cmake_obj ${a}`"
done
fi
+if test "x${bootstrap_system_librhash}" = "x"; then
+ for a in ${LIBRHASH_C_SOURCES}; do
+ objs="${objs} rhash-`cmake_obj ${a}`"
+ done
+fi
if test "${cmake_bootstrap_generator}" = "Ninja"; then
if test "x${bootstrap_system_jsoncpp}" = "x"; then
for a in ${JSONCPP_CXX_SOURCES}; do
objs="${objs} jsoncpp-`cmake_obj ${a}`"
done
fi
- if test "x${bootstrap_system_librhash}" = "x"; then
- for a in ${LIBRHASH_C_SOURCES}; do
- objs="${objs} rhash-`cmake_obj ${a}`"
- done
- fi
fi
libs=""
@@ -1698,6 +1702,15 @@ else
libs="${libs} -luv"
fi
+if test "x${bootstrap_system_librhash}" != "x"; then
+ if test `which pkg-config`; then
+ use_librhash_flags="`pkg-config --cflags librhash`"
+ cmake_c_flags="${cmake_c_flags} ${use_librhash_flags}"
+ cmake_cxx_flags="${cmake_cxx_flags} ${use_librhash_flags}"
+ fi
+ libs="${libs} -lrhash"
+fi
+
if test "${cmake_bootstrap_generator}" = "Ninja"; then
jsoncpp_cxx_flags=
if test "x${bootstrap_system_jsoncpp}" = "x"; then
@@ -1709,15 +1722,6 @@ if test "${cmake_bootstrap_generator}" = "Ninja"; then
fi
libs="${libs} -ljsoncpp"
fi
-
- if test "x${bootstrap_system_librhash}" != "x"; then
- if test `which pkg-config`; then
- use_librhash_flags="`pkg-config --cflags librhash`"
- cmake_c_flags="${cmake_c_flags} ${use_librhash_flags}"
- cmake_cxx_flags="${cmake_cxx_flags} ${use_librhash_flags}"
- fi
- libs="${libs} -lrhash"
- fi
fi
if test "x${cmake_ansi_cxx_flags}" != "x"; then
@@ -1841,6 +1845,12 @@ if test "x${bootstrap_system_libuv}" = "x"; then
write_source_rule "c" "uv-`cmake_obj ${a}`" "${src}" "${uv_c_flags}"
done
fi
+if test "x${bootstrap_system_librhash}" = "x"; then
+ for a in ${LIBRHASH_C_SOURCES}; do
+ src=`cmake_escape_artifact "${cmake_source_dir}/Utilities/cmlibrhash/${a}"`
+ write_source_rule "c" "rhash-`cmake_obj ${a}`" "${src}" ""
+ done
+fi
if test "${cmake_bootstrap_generator}" = "Ninja"; then
if test "x${bootstrap_system_jsoncpp}" = "x"; then
for a in ${JSONCPP_CXX_SOURCES}; do
@@ -1848,12 +1858,6 @@ if test "${cmake_bootstrap_generator}" = "Ninja"; then
write_source_rule "cxx" "jsoncpp-`cmake_obj ${a}`" "${src}" "${jsoncpp_cxx_flags}"
done
fi
- if test "x${bootstrap_system_librhash}" = "x"; then
- for a in ${LIBRHASH_C_SOURCES}; do
- src=`cmake_escape_artifact "${cmake_source_dir}/Utilities/cmlibrhash/${a}"`
- write_source_rule "c" "rhash-`cmake_obj ${a}`" "${src}" ""
- done
- fi
fi
if test "${cmake_bootstrap_generator}" = "Ninja"; then
echo "